]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec...
authorDavid S. Miller <davem@davemloft.net>
Tue, 14 Jan 2014 07:14:25 +0000 (23:14 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 14 Jan 2014 07:14:25 +0000 (23:14 -0800)
Conflicts:
net/xfrm/xfrm_policy.c

Steffen Klassert says:

====================
This pull request has a merge conflict between commits be7928d20bab
("net: xfrm: xfrm_policy: fix inline not at beginning of declaration") and
da7c224b1baa ("net: xfrm: xfrm_policy: silence compiler warning") from
the net-next tree and commit 2f3ea9a95c58 ("xfrm: checkpatch erros with
inline keyword position") from the ipsec-next tree.

The version from net-next can be used, like it is done in linux-next.

1) Checkpatch cleanups, from Weilong Chen.

2) Fix lockdep complaints when pktgen is used with IPsec,
   from Fan Du.

3) Update pktgen to allow any combination of IPsec transport/tunnel mode
   and AH/ESP/IPcomp type, from Fan Du.

4) Make pktgen_dst_metrics static, Fengguang Wu.

5) Compile fix for pktgen when CONFIG_XFRM is not set,
   from Fan Du.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
1107 files changed:
Documentation/ABI/testing/sysfs-class-net-mesh
Documentation/block/null_blk.txt [new file with mode: 0644]
Documentation/cgroups/net_cls.txt
Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt [new file with mode: 0644]
Documentation/kernel-parameters.txt
Documentation/module-signing.txt [new file with mode: 0644]
Documentation/networking/batman-adv.txt
Documentation/networking/bonding.txt
Documentation/networking/i40evf.txt [new file with mode: 0644]
Documentation/networking/ip-sysctl.txt
Documentation/networking/packet_mmap.txt
MAINTAINERS
Makefile
arch/arc/include/asm/Kbuild
arch/arc/include/uapi/asm/unistd.h
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-pxa/include/mach/lubbock.h
arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-bockw.c
arch/arm/mach-shmobile/board-lager.c
arch/arm/xen/enlighten.c
arch/arm64/include/asm/xen/page-coherent.h
arch/arm64/kernel/ptrace.c
arch/cris/include/asm/Kbuild
arch/hexagon/include/asm/Kbuild
arch/microblaze/include/asm/Kbuild
arch/mips/bcm47xx/setup.c
arch/mn10300/include/asm/Kbuild
arch/powerpc/boot/dts/mpc5125twr.dts
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_book3s_asm.h
arch/powerpc/include/asm/switch_to.h
arch/powerpc/include/asm/unaligned.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/process.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/book3s_rmhandlers.S
arch/powerpc/kvm/booke.c
arch/powerpc/lib/copyuser_64.S
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/pci.h
arch/score/include/asm/Kbuild
arch/sh/lib/Makefile
arch/sparc/include/asm/pgtable_64.h
arch/x86/include/asm/pgtable.h
arch/x86/kernel/cpu/intel.c
arch/x86/mm/gup.c
block/blk-mq-sysfs.c
drivers/acpi/Kconfig
drivers/acpi/acpi_lpss.c
drivers/acpi/apei/Kconfig
drivers/acpi/apei/erst.c
drivers/ata/ahci.c
drivers/ata/ahci_imx.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/atm/nicstar.c
drivers/bcma/bcma_private.h
drivers/bcma/driver_chipcommon_sflash.c
drivers/bcma/main.c
drivers/block/null_blk.c
drivers/block/skd_main.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btsdio.c
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_vhci.c
drivers/cpufreq/cpufreq.c
drivers/dma/Kconfig
drivers/dma/at_hdmac_regs.h
drivers/dma/dmaengine.c
drivers/dma/dmatest.c
drivers/dma/fsldma.c
drivers/dma/mv_xor.c
drivers/dma/pl330.c
drivers/dma/ppc4xx/adma.c
drivers/dma/txx9dmac.c
drivers/firewire/sbp2.c
drivers/firmware/Makefile
drivers/firmware/efi/Kconfig
drivers/firmware/efi/Makefile
drivers/firmware/efi/efi-pstore.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/qxl/Kconfig
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/idle/intel_idle.c
drivers/iio/adc/ad7887.c
drivers/iio/imu/adis16400_core.c
drivers/iio/light/cm36651.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/ulp/ipoib/ipoib_netlink.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/irqchip/irq-renesas-intc-irqpin.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/telespci.c
drivers/isdn/i4l/isdn_net.c
drivers/md/bcache/alloc.c
drivers/md/bcache/bcache.h
drivers/md/bcache/btree.c
drivers/md/bcache/movinggc.c
drivers/md/bcache/super.c
drivers/md/bcache/sysfs.c
drivers/md/bcache/util.c
drivers/md/bcache/util.h
drivers/md/bcache/writeback.c
drivers/media/dvb-core/dvb_net.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_3ad.h
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_netlink.c
drivers/net/bonding/bond_options.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/can/Kconfig
drivers/net/can/mcp251x.c
drivers/net/ethernet/3com/3c509.c
drivers/net/ethernet/amd/7990.c
drivers/net/ethernet/amd/7990.h
drivers/net/ethernet/amd/hplance.c
drivers/net/ethernet/amd/mvme147.c
drivers/net/ethernet/amd/pcnet32.c
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/atheros/alx/alx.h
drivers/net/ethernet/atheros/alx/ethtool.c
drivers/net/ethernet/atheros/alx/hw.c
drivers/net/ethernet/atheros/alx/hw.h
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/atheros/alx/reg.h
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atlx/atl1.c
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/b44.h
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bgmac.h
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_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/broadcom/cnic.h
drivers/net/ethernet/broadcom/cnic_if.h
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
drivers/net/ethernet/chelsio/cxgb3/l2t.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
drivers/net/ethernet/chelsio/cxgb4/l2t.c
drivers/net/ethernet/chelsio/cxgb4/l2t.h
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
drivers/net/ethernet/cisco/enic/enic_pp.c
drivers/net/ethernet/dec/tulip/uli526x.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/Makefile
drivers/net/ethernet/intel/e1000e/80003es2lan.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/phy.c
drivers/net/ethernet/intel/i40e/Makefile
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_adminq.c
drivers/net/ethernet/intel/i40e/i40e_adminq.h
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
drivers/net/ethernet/intel/i40e/i40e_alloc.h
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
drivers/net/ethernet/intel/i40e/i40e_diag.c
drivers/net/ethernet/intel/i40e/i40e_diag.h
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_hmc.c
drivers/net/ethernet/intel/i40e/i40e_hmc.h
drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_nvm.c
drivers/net/ethernet/intel/i40e/i40e_osdep.h
drivers/net/ethernet/intel/i40e/i40e_prototype.h
drivers/net/ethernet/intel/i40e/i40e_ptp.c [new file with mode: 0644]
drivers/net/ethernet/intel/i40e/i40e_register.h
drivers/net/ethernet/intel/i40e/i40e_status.h
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40e/i40e_txrx.h
drivers/net/ethernet/intel/i40e/i40e_type.h
drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
drivers/net/ethernet/intel/i40evf/Makefile [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_adminq.c [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_adminq.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_alloc.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_common.c [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_hmc.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_osdep.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_prototype.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_register.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_status.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_txrx.c [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_txrx.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_type.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40evf.h [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40evf_main.c [new file with mode: 0644]
drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c [new file with mode: 0644]
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/mellanox/mlx4/Kconfig
drivers/net/ethernet/mellanox/mlx4/en_clock.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_main.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_resources.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx4/port.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/micrel/ksz884x.c
drivers/net/ethernet/neterion/vxge/vxge-main.c
drivers/net/ethernet/packetengines/yellowfin.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
drivers/net/ethernet/qlogic/qlge/qlge.h
drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/renesas/sh_eth.h
drivers/net/ethernet/seeq/sgiseeq.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smsc9420.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/cpsw_ale.c
drivers/net/ethernet/tile/Kconfig
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/fddi/skfp/fplustm.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hamradio/yam.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/irda/Kconfig
drivers/net/irda/sh_irda.c
drivers/net/irda/sh_sir.c
drivers/net/macvlan.c
drivers/net/mdio.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/plip/plip.c
drivers/net/ppp/pppoe.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/cdc_ether.c
drivers/net/usb/dm9601.c
drivers/net/usb/hso.c
drivers/net/usb/mcs7830.c
drivers/net/usb/r8152.c
drivers/net/usb/r815x.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wireless/adm8211.c
drivers/net/wireless/airo_cs.c
drivers/net/wireless/at76c50x-usb.c
drivers/net/wireless/ath/ar5523/ar5523.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath9k/Makefile
drivers/net/wireless/ath/ath9k/antenna.c
drivers/net/wireless/ath/ath9k/ar9002_hw.c
drivers/net/wireless/ath/ath9k/ar9002_mac.c
drivers/net/wireless/ath/ath9k/ar9002_phy.c
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
drivers/net/wireless/ath/ath9k/ar9003_hw.c
drivers/net/wireless/ath/ath9k/ar9003_mac.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/ar953x_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/btcoex.c
drivers/net/wireless/ath/ath9k/common.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/dfs.c
drivers/net/wireless/ath/ath9k/eeprom_4k.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/hw-ops.h
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/link.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/mac.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/mci.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/spectral.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/spectral.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/wow.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/debug.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/carl9170/rx.c
drivers/net/wireless/ath/carl9170/tx.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/ath/wil6210/interrupt.c
drivers/net/wireless/ath/wil6210/txrx.c
drivers/net/wireless/ath/wil6210/wil6210.h
drivers/net/wireless/atmel.c
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/atmel_pci.c
drivers/net/wireless/brcm80211/brcmfmac/Makefile
drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c [deleted file]
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/brcm80211/brcmfmac/fwil.c
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
drivers/net/wireless/brcm80211/brcmfmac/proto.c
drivers/net/wireless/brcm80211/brcmfmac/proto.h
drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
drivers/net/wireless/brcm80211/include/brcmu_wifi.h
drivers/net/wireless/cw1200/fwio.c
drivers/net/wireless/cw1200/main.c
drivers/net/wireless/cw1200/pm.c
drivers/net/wireless/cw1200/sta.c
drivers/net/wireless/cw1200/txrx.c
drivers/net/wireless/hostap/hostap_80211_rx.c
drivers/net/wireless/hostap/hostap_80211_tx.c
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/hostap/hostap_main.c
drivers/net/wireless/hostap/hostap_pci.c
drivers/net/wireless/hostap/hostap_plx.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/ipw2x00/ipw2200.h
drivers/net/wireless/ipw2x00/libipw_rx.c
drivers/net/wireless/iwlegacy/3945-rs.c
drivers/net/wireless/iwlegacy/3945.c
drivers/net/wireless/iwlegacy/4965-rs.c
drivers/net/wireless/iwlegacy/4965.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlwifi/dvm/agn.h
drivers/net/wireless/iwlwifi/dvm/calib.c
drivers/net/wireless/iwlwifi/dvm/calib.h
drivers/net/wireless/iwlwifi/dvm/commands.h
drivers/net/wireless/iwlwifi/dvm/debugfs.c
drivers/net/wireless/iwlwifi/dvm/dev.h
drivers/net/wireless/iwlwifi/dvm/devices.c
drivers/net/wireless/iwlwifi/dvm/led.c
drivers/net/wireless/iwlwifi/dvm/led.h
drivers/net/wireless/iwlwifi/dvm/lib.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/dvm/power.c
drivers/net/wireless/iwlwifi/dvm/power.h
drivers/net/wireless/iwlwifi/dvm/rs.c
drivers/net/wireless/iwlwifi/dvm/rs.h
drivers/net/wireless/iwlwifi/dvm/rx.c
drivers/net/wireless/iwlwifi/dvm/rxon.c
drivers/net/wireless/iwlwifi/dvm/scan.c
drivers/net/wireless/iwlwifi/dvm/sta.c
drivers/net/wireless/iwlwifi/dvm/tt.c
drivers/net/wireless/iwlwifi/dvm/tt.h
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/dvm/ucode.c
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/iwl-agn-hw.h
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-csr.h
drivers/net/wireless/iwlwifi/iwl-debug.h
drivers/net/wireless/iwlwifi/iwl-devtrace.c
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-drv.h
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
drivers/net/wireless/iwlwifi/iwl-eeprom-read.c
drivers/net/wireless/iwlwifi/iwl-eeprom-read.h
drivers/net/wireless/iwlwifi/iwl-fh.h
drivers/net/wireless/iwlwifi/iwl-fw-file.h
drivers/net/wireless/iwlwifi/iwl-fw.h
drivers/net/wireless/iwlwifi/iwl-io.c
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl-modparams.h
drivers/net/wireless/iwlwifi/iwl-notif-wait.c
drivers/net/wireless/iwlwifi/iwl-notif-wait.h
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
drivers/net/wireless/iwlwifi/iwl-op-mode.h
drivers/net/wireless/iwlwifi/iwl-phy-db.c
drivers/net/wireless/iwlwifi/iwl-phy-db.h
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/mvm/Makefile
drivers/net/wireless/iwlwifi/mvm/binding.c
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
drivers/net/wireless/iwlwifi/mvm/constants.h
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/debugfs.h
drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/led.c
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/nvm.c
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
drivers/net/wireless/iwlwifi/mvm/power.c
drivers/net/wireless/iwlwifi/mvm/power_legacy.c
drivers/net/wireless/iwlwifi/mvm/quota.c
drivers/net/wireless/iwlwifi/mvm/rs.c
drivers/net/wireless/iwlwifi/mvm/rs.h
drivers/net/wireless/iwlwifi/mvm/rx.c
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/sf.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.h
drivers/net/wireless/iwlwifi/mvm/testmode.h
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/time-event.h
drivers/net/wireless/iwlwifi/mvm/tt.c
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/utils.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mwifiex/11n.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/sta_cmd.c
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwifiex/sta_rx.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/orinoco/hermes.c
drivers/net/wireless/orinoco/orinoco_cs.c
drivers/net/wireless/orinoco/orinoco_usb.c
drivers/net/wireless/orinoco/spectrum_cs.c
drivers/net/wireless/p54/eeprom.c
drivers/net/wireless/p54/fwio.c
drivers/net/wireless/p54/led.c
drivers/net/wireless/p54/main.c
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/p54/txrx.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rtl818x/rtl8180/dev.c
drivers/net/wireless/rtl818x/rtl8180/grf5101.c
drivers/net/wireless/rtl818x/rtl8180/max2820.c
drivers/net/wireless/rtl818x/rtl8180/rtl8225.c
drivers/net/wireless/rtl818x/rtl8180/sa2400.c
drivers/net/wireless/rtl818x/rtl8187/dev.c
drivers/net/wireless/rtl818x/rtl8187/rtl8225.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/cam.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/ps.c
drivers/net/wireless/ti/wl1251/acx.c
drivers/net/wireless/ti/wl1251/acx.h
drivers/net/wireless/ti/wl1251/boot.c
drivers/net/wireless/ti/wl1251/cmd.c
drivers/net/wireless/ti/wl1251/cmd.h
drivers/net/wireless/ti/wl1251/event.c
drivers/net/wireless/ti/wl1251/event.h
drivers/net/wireless/ti/wl1251/init.c
drivers/net/wireless/ti/wl1251/main.c
drivers/net/wireless/ti/wl1251/rx.c
drivers/net/wireless/ti/wl1251/tx.c
drivers/net/wireless/ti/wl1251/wl1251.h
drivers/net/wireless/wl3501_cs.c
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/of/Kconfig
drivers/of/address.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/of/of_mdio.c
drivers/of/of_net.c
drivers/phy/Kconfig
drivers/phy/phy-core.c
drivers/pinctrl/pinctrl-baytrail.c
drivers/powercap/intel_rapl.c
drivers/scsi/qla2xxx/qla_target.c
drivers/ssb/driver_chipcommon_sflash.c
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/iio/magnetometer/hmc5843.c
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/imx-drm/imx-tve.c
drivers/staging/imx-drm/ipu-v3/ipu-common.c
drivers/staging/ozwpan/ozcdev.c
drivers/staging/ozwpan/ozproto.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/target_core_device.c
drivers/target/target_core_file.c
drivers/target/target_core_file.h
drivers/target/target_core_tpg.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/tty_ldsem.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/host.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-wdm.c
drivers/usb/dwc3/core.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/xhci-pci.c
drivers/usb/phy/Kconfig
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/phy/phy-twl6030-usb.c
drivers/usb/serial/option.c
drivers/usb/serial/zte_ev.c
drivers/virtio/virtio_balloon.c
drivers/xen/balloon.c
drivers/xen/grant-table.c
drivers/xen/privcmd.c
fs/aio.c
fs/ext2/super.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/jbd2/transaction.c
fs/pstore/platform.c
fs/sysfs/file.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_trans_buf.c
include/asm-generic/pgtable.h
include/linux/auxvec.h
include/linux/bcma/bcma.h
include/linux/cgroup_subsys.h
include/linux/if_macvlan.h
include/linux/if_tunnel.h
include/linux/if_vlan.h
include/linux/inet_lro.h
include/linux/libata.h
include/linux/lockref.h
include/linux/mdio.h
include/linux/migrate.h
include/linux/mlx4/cmd.h
include/linux/mlx4/cq.h
include/linux/mlx4/device.h
include/linux/mlx4/qp.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmc/sdio_ids.h
include/linux/netdevice.h
include/linux/netfilter/ipset/ip_set.h
include/linux/netlink.h
include/linux/of_mdio.h
include/linux/percpu-defs.h
include/linux/phy.h
include/linux/platform_data/eth-netx.h
include/linux/printk.h
include/linux/pstore.h
include/linux/reboot.h
include/linux/rtnetlink.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/tcp.h
include/net/act_api.h
include/net/arp.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
include/net/bluetooth/l2cap.h
include/net/cfg80211.h
include/net/cls_cgroup.h
include/net/genetlink.h
include/net/gre.h
include/net/inetpeer.h
include/net/ip.h
include/net/ip6_fib.h
include/net/ip6_route.h
include/net/ip6_tunnel.h
include/net/ip_tunnels.h
include/net/ipv6.h
include/net/llc.h
include/net/llc_pdu.h
include/net/mac80211.h
include/net/netfilter/ipv4/nf_conntrack_ipv4.h
include/net/netfilter/ipv4/nf_reject.h [new file with mode: 0644]
include/net/netfilter/ipv6/nf_reject.h [new file with mode: 0644]
include/net/netfilter/nf_conntrack_l3proto.h
include/net/netfilter/nf_queue.h
include/net/netfilter/nf_tables.h
include/net/netfilter/nf_tables_ipv4.h
include/net/netfilter/nf_tables_ipv6.h
include/net/netns/conntrack.h
include/net/netns/ipv4.h
include/net/netns/ipv6.h
include/net/netns/nftables.h
include/net/netprio_cgroup.h
include/net/ping.h
include/net/pkt_cls.h
include/net/protocol.h
include/net/route.h
include/net/rtnetlink.h
include/net/sch_generic.h
include/net/sctp/structs.h
include/net/sock.h
include/net/tcp.h
include/rdma/ib_verbs.h
include/target/target_core_base.h
include/uapi/linux/if_arp.h
include/uapi/linux/if_link.h
include/uapi/linux/if_packet.h
include/uapi/linux/netconf.h
include/uapi/linux/netfilter.h
include/uapi/linux/netfilter/Kbuild
include/uapi/linux/netfilter/nf_nat.h
include/uapi/linux/netfilter/nf_tables.h
include/uapi/linux/netfilter/nfnetlink_queue.h
include/uapi/linux/netfilter/xt_cgroup.h [new file with mode: 0644]
include/uapi/linux/netfilter/xt_ipcomp.h [new file with mode: 0644]
include/uapi/linux/netfilter/xt_l2tp.h [new file with mode: 0644]
include/uapi/linux/nl80211.h
include/uapi/linux/openvswitch.h
include/uapi/linux/pci_regs.h
include/uapi/linux/perf_event.h
include/uapi/linux/pkt_sched.h
include/uapi/linux/tcp_metrics.h
include/xen/interface/io/blkif.h
kernel/Makefile
kernel/bounds.c
kernel/cgroup.c
kernel/events/core.c
kernel/fork.c
kernel/freezer.c
kernel/kexec.c
kernel/power/console.c
kernel/reboot.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/trace/ftrace.c
kernel/user.c
mm/Kconfig
mm/compaction.c
mm/huge_memory.c
mm/memory-failure.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/mprotect.c
mm/page_alloc.c
mm/pgtable-generic.c
mm/rmap.c
net/8021q/vlan_dev.c
net/Kconfig
net/batman-adv/Kconfig
net/batman-adv/Makefile
net/batman-adv/bat_algo.h
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bitarray.c
net/batman-adv/bitarray.h
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/bridge_loop_avoidance.h
net/batman-adv/debugfs.c
net/batman-adv/debugfs.h
net/batman-adv/distributed-arp-table.c
net/batman-adv/distributed-arp-table.h
net/batman-adv/fragmentation.c
net/batman-adv/fragmentation.h
net/batman-adv/gateway_client.c
net/batman-adv/gateway_client.h
net/batman-adv/gateway_common.c
net/batman-adv/gateway_common.h
net/batman-adv/hard-interface.c
net/batman-adv/hard-interface.h
net/batman-adv/hash.c
net/batman-adv/hash.h
net/batman-adv/icmp_socket.c
net/batman-adv/icmp_socket.h
net/batman-adv/main.c
net/batman-adv/main.h
net/batman-adv/network-coding.c
net/batman-adv/network-coding.h
net/batman-adv/originator.c
net/batman-adv/originator.h
net/batman-adv/packet.h
net/batman-adv/routing.c
net/batman-adv/routing.h
net/batman-adv/send.c
net/batman-adv/send.h
net/batman-adv/soft-interface.c
net/batman-adv/soft-interface.h
net/batman-adv/sysfs.c
net/batman-adv/sysfs.h
net/batman-adv/translation-table.c
net/batman-adv/translation-table.h
net/batman-adv/types.h
net/bluetooth/6lowpan.c [new file with mode: 0644]
net/bluetooth/6lowpan.h [new file with mode: 0644]
net/bluetooth/Makefile
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sock.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/rfcomm/tty.c
net/bridge/br_device.c
net/bridge/br_input.c
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_sysfs_br.c
net/bridge/netfilter/nf_tables_bridge.c
net/can/gw.c
net/core/Makefile
net/core/dev.c
net/core/neighbour.c
net/core/net-sysfs.c
net/core/net-sysfs.h
net/core/netclassid_cgroup.c [new file with mode: 0644]
net/core/netpoll.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock.c
net/dccp/ccids/lib/tfrc.c
net/dccp/ccids/lib/tfrc.h
net/dccp/dccp.h
net/dccp/ipv4.c
net/dccp/options.c
net/dccp/probe.c
net/ieee802154/6lowpan.c
net/ieee802154/6lowpan.h
net/ieee802154/6lowpan_iphc.c [new file with mode: 0644]
net/ieee802154/Makefile
net/ieee802154/wpan-class.c
net/ipv4/Makefile
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/cipso_ipv4.c
net/ipv4/devinet.c
net/ipv4/fib_lookup.h
net/ipv4/fib_semantics.c
net/ipv4/gre_demux.c
net/ipv4/gre_offload.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/inet_diag.c
net/ipv4/inet_lro.c
net/ipv4/inetpeer.c
net/ipv4/ip_forward.c
net/ipv4/ip_gre.c
net/ipv4/ip_options.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_vti.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
net/ipv4/netfilter/ipt_REJECT.c
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
net/ipv4/netfilter/nf_nat_snmp_basic.c
net/ipv4/netfilter/nf_tables_arp.c
net/ipv4/netfilter/nf_tables_ipv4.c
net/ipv4/netfilter/nft_chain_nat_ipv4.c
net/ipv4/netfilter/nft_chain_route_ipv4.c
net/ipv4/ping.c
net/ipv4/proc.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_offload.c
net/ipv4/tcp_output.c
net/ipv4/tcp_probe.c
net/ipv4/tcp_yeah.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv4/xfrm4_mode_beet.c
net/ipv6/addrconf.c
net/ipv6/icmp.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/ip6t_REJECT.c
net/ipv6/netfilter/nf_tables_ipv6.c
net/ipv6/netfilter/nft_chain_nat_ipv6.c
net/ipv6/netfilter/nft_chain_route_ipv6.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/sysctl_net_ipv6.c
net/ipv6/tcp_ipv6.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/llc/af_llc.c
net/llc/llc_conn.c
net/llc/llc_core.c
net/llc/llc_sap.c
net/mac80211/aes_cmac.c
net/mac80211/aes_cmac.h
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/driver-ops.h
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh_sync.c
net/mac80211/mlme.c
net/mac80211/pm.c
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tkip.c
net/mac80211/trace.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wme.c
net/mac802154/wpan.c
net/netfilter/Kconfig
net/netfilter/Makefile
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto.c
net/netfilter/nf_conntrack_proto_dccp.c
net/netfilter/nf_conntrack_seqadj.c
net/netfilter/nf_conntrack_timestamp.c
net/netfilter/nf_nat_core.c
net/netfilter/nf_nat_proto_common.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_core.c
net/netfilter/nf_tables_inet.c [new file with mode: 0644]
net/netfilter/nfnetlink_log.c
net/netfilter/nfnetlink_queue_core.c
net/netfilter/nft_compat.c
net/netfilter/nft_ct.c
net/netfilter/nft_exthdr.c
net/netfilter/nft_log.c
net/netfilter/nft_meta.c
net/netfilter/nft_meta_target.c [deleted file]
net/netfilter/nft_queue.c [new file with mode: 0644]
net/netfilter/nft_reject.c [moved from net/ipv4/netfilter/nft_reject_ipv4.c with 78% similarity]
net/netfilter/xt_CT.c
net/netfilter/xt_NFQUEUE.c
net/netfilter/xt_cgroup.c [new file with mode: 0644]
net/netfilter/xt_ipcomp.c [new file with mode: 0644]
net/netfilter/xt_l2tp.c [new file with mode: 0644]
net/netlink/af_netlink.c
net/netlink/genetlink.c
net/openvswitch/datapath.c
net/openvswitch/datapath.h
net/openvswitch/flow.c
net/openvswitch/flow.h
net/openvswitch/flow_netlink.c
net/openvswitch/flow_netlink.h
net/openvswitch/flow_table.c
net/openvswitch/flow_table.h
net/openvswitch/vport.c
net/openvswitch/vport.h
net/packet/af_packet.c
net/rds/ib.c
net/rose/af_rose.c
net/rose/rose_dev.c
net/sched/Kconfig
net/sched/Makefile
net/sched/act_api.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/cls_api.c
net/sched/cls_basic.c
net/sched/cls_bpf.c
net/sched/cls_cgroup.c
net/sched/cls_flow.c
net/sched/cls_fw.c
net/sched/cls_route.c
net/sched/cls_rsvp.h
net/sched/cls_tcindex.c
net/sched/cls_u32.c
net/sched/sch_api.c
net/sched/sch_cbq.c
net/sched/sch_dsmark.c
net/sched/sch_gred.c
net/sched/sch_hhf.c
net/sched/sch_htb.c
net/sched/sch_netem.c
net/sched/sch_pie.c [new file with mode: 0644]
net/sched/sch_tbf.c
net/sctp/auth.c
net/sctp/chunk.c
net/sctp/input.c
net/sctp/ipv6.c
net/sctp/objcnt.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/proc.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/sctp/sm_statetable.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sctp/ulpqueue.c
net/tipc/bcast.c
net/tipc/bearer.c
net/tipc/bearer.h
net/tipc/discover.c
net/tipc/link.c
net/tipc/link.h
net/tipc/node.c
net/tipc/node.h
net/tipc/port.c
net/tipc/port.h
net/tipc/socket.c
net/wireless/ap.c
net/wireless/core.c
net/wireless/core.h
net/wireless/ibss.c
net/wireless/mesh.c
net/wireless/nl80211.c
net/wireless/radiotap.c
net/wireless/rdev-ops.h
net/wireless/reg.c
net/wireless/reg.h
net/wireless/scan.c
net/wireless/sme.c
net/wireless/trace.h
net/wireless/util.c
net/xfrm/xfrm_policy.c
scripts/link-vmlinux.sh
security/selinux/hooks.c
sound/core/pcm_lib.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/sam9x5_wm8731.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/imx-wm8962.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-pcm.c
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_i2s.c

index 0baa657b18c4719048bf7048affea6fba8f79221..4793d3dff6af04e7ac4a736ccfdbd794d5a4d7f0 100644 (file)
@@ -68,6 +68,14 @@ Description:
                 Defines the penalty which will be applied to an
                 originator message's tq-field on every hop.
 
+What:          /sys/class/net/<mesh_iface>/mesh/isolation_mark
+Date:          Nov 2013
+Contact:       Antonio Quartulli <antonio@meshcoding.com>
+Description:
+               Defines the isolation mark (and its bitmask) which
+               is used to classify clients as "isolated" by the
+               Extended Isolation feature.
+
 What:           /sys/class/net/<mesh_iface>/mesh/network_coding
 Date:           Nov 2012
 Contact:        Martin Hundeboll <martin@hundeboll.net>
diff --git a/Documentation/block/null_blk.txt b/Documentation/block/null_blk.txt
new file mode 100644 (file)
index 0000000..b2830b4
--- /dev/null
@@ -0,0 +1,72 @@
+Null block device driver
+================================================================================
+
+I. Overview
+
+The null block device (/dev/nullb*) is used for benchmarking the various
+block-layer implementations. It emulates a block device of X gigabytes in size.
+The following instances are possible:
+
+  Single-queue block-layer
+    - Request-based.
+    - Single submission queue per device.
+    - Implements IO scheduling algorithms (CFQ, Deadline, noop).
+  Multi-queue block-layer
+    - Request-based.
+    - Configurable submission queues per device.
+  No block-layer (Known as bio-based)
+    - Bio-based. IO requests are submitted directly to the device driver.
+    - Directly accepts bio data structure and returns them.
+
+All of them have a completion queue for each core in the system.
+
+II. Module parameters applicable for all instances:
+
+queue_mode=[0-2]: Default: 2-Multi-queue
+  Selects which block-layer the module should instantiate with.
+
+  0: Bio-based.
+  1: Single-queue.
+  2: Multi-queue.
+
+home_node=[0--nr_nodes]: Default: NUMA_NO_NODE
+  Selects what CPU node the data structures are allocated from.
+
+gb=[Size in GB]: Default: 250GB
+  The size of the device reported to the system.
+
+bs=[Block size (in bytes)]: Default: 512 bytes
+  The block size reported to the system.
+
+nr_devices=[Number of devices]: Default: 2
+  Number of block devices instantiated. They are instantiated as /dev/nullb0,
+  etc.
+
+irq_mode=[0-2]: Default: 1-Soft-irq
+  The completion mode used for completing IOs to the block-layer.
+
+  0: None.
+  1: Soft-irq. Uses IPI to complete IOs across CPU nodes. Simulates the overhead
+     when IOs are issued from another CPU node than the home the device is
+     connected to.
+  2: Timer: Waits a specific period (completion_nsec) for each IO before
+     completion.
+
+completion_nsec=[ns]: Default: 10.000ns
+  Combined with irq_mode=2 (timer). The time each completion event must wait.
+
+submit_queues=[0..nr_cpus]:
+  The number of submission queues attached to the device driver. If unset, it
+  defaults to 1 on single-queue and bio-based instances. For multi-queue,
+  it is ignored when use_per_node_hctx module parameter is 1.
+
+hw_queue_depth=[0..qdepth]: Default: 64
+  The hardware queue depth of the device.
+
+III: Multi-queue specific parameters
+
+use_per_node_hctx=[0/1]: Default: 0
+  0: The number of submit queues are set to the value of the submit_queues
+     parameter.
+  1: The multi-queue block layer is instantiated with a hardware dispatch
+     queue for each CPU node in the system.
index 9face6bb578ad60a19b6985c2d5df88418b6a131..ec182346dea29b0f0304011092ff6133df0c88cb 100644 (file)
@@ -6,6 +6,8 @@ tag network packets with a class identifier (classid).
 
 The Traffic Controller (tc) can be used to assign
 different priorities to packets from different cgroups.
+Also, Netfilter (iptables) can use this tag to perform
+actions on such packets.
 
 Creating a net_cls cgroups instance creates a net_cls.classid file.
 This net_cls.classid value is initialized to 0.
@@ -32,3 +34,6 @@ tc class add dev eth0 parent 10: classid 10:1 htb rate 40mbit
  - creating traffic class 10:1
 
 tc filter add dev eth0 parent 10: protocol ip prio 10 handle 1: cgroup
+
+configuring iptables, basic example:
+iptables -A OUTPUT -m cgroup ! --cgroup 0x100001 -j DROP
diff --git a/Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt b/Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt
new file mode 100644 (file)
index 0000000..ee3723b
--- /dev/null
@@ -0,0 +1,25 @@
+* Microchip MCP251X stand-alone CAN controller device tree bindings
+
+Required properties:
+ - compatible: Should be one of the following:
+   - "microchip,mcp2510" for MCP2510.
+   - "microchip,mcp2515" for MCP2515.
+ - reg: SPI chip select.
+ - clocks: The clock feeding the CAN controller.
+ - interrupt-parent: The parent interrupt controller.
+ - interrupts: Should contain IRQ line for the CAN controller.
+
+Optional properties:
+ - vdd-supply: Regulator that powers the CAN controller.
+ - xceiver-supply: Regulator that powers the CAN transceiver.
+
+Example:
+       can0: can@1 {
+               compatible = "microchip,mcp2515";
+               reg = <1>;
+               clocks = <&clk24m>;
+               interrupt-parent = <&gpio4>;
+               interrupts = <13 0x2>;
+               vdd-supply = <&reg5v0>;
+               xceiver-supply = <&reg5v0>;
+       };
index 50680a59a2ff9a913e449a1d71ced9fab3004fe4..b9e9bd85429801efa537bc1ea85f773fc92099f8 100644 (file)
@@ -1529,6 +1529,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
                        * atapi_dmadir: Enable ATAPI DMADIR bridge support
 
+                       * disable: Disable this device.
+
                        If there are multiple matching configurations changing
                        the same attribute, the last one is used.
 
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
new file mode 100644 (file)
index 0000000..2b40e04
--- /dev/null
@@ -0,0 +1,240 @@
+                       ==============================
+                       KERNEL MODULE SIGNING FACILITY
+                       ==============================
+
+CONTENTS
+
+ - Overview.
+ - Configuring module signing.
+ - Generating signing keys.
+ - Public keys in the kernel.
+ - Manually signing modules.
+ - Signed modules and stripping.
+ - Loading signed modules.
+ - Non-valid signatures and unsigned modules.
+ - Administering/protecting the private key.
+
+
+========
+OVERVIEW
+========
+
+The kernel module signing facility cryptographically signs modules during
+installation and then checks the signature upon loading the module.  This
+allows increased kernel security by disallowing the loading of unsigned modules
+or modules signed with an invalid key.  Module signing increases security by
+making it harder to load a malicious module into the kernel.  The module
+signature checking is done by the kernel so that it is not necessary to have
+trusted userspace bits.
+
+This facility uses X.509 ITU-T standard certificates to encode the public keys
+involved.  The signatures are not themselves encoded in any industrial standard
+type.  The facility currently only supports the RSA public key encryption
+standard (though it is pluggable and permits others to be used).  The possible
+hash algorithms that can be used are SHA-1, SHA-224, SHA-256, SHA-384, and
+SHA-512 (the algorithm is selected by data in the signature).
+
+
+==========================
+CONFIGURING MODULE SIGNING
+==========================
+
+The module signing facility is enabled by going to the "Enable Loadable Module
+Support" section of the kernel configuration and turning on
+
+       CONFIG_MODULE_SIG       "Module signature verification"
+
+This has a number of options available:
+
+ (1) "Require modules to be validly signed" (CONFIG_MODULE_SIG_FORCE)
+
+     This specifies how the kernel should deal with a module that has a
+     signature for which the key is not known or a module that is unsigned.
+
+     If this is off (ie. "permissive"), then modules for which the key is not
+     available and modules that are unsigned are permitted, but the kernel will
+     be marked as being tainted.
+
+     If this is on (ie. "restrictive"), only modules that have a valid
+     signature that can be verified by a public key in the kernel's possession
+     will be loaded.  All other modules will generate an error.
+
+     Irrespective of the setting here, if the module has a signature block that
+     cannot be parsed, it will be rejected out of hand.
+
+
+ (2) "Automatically sign all modules" (CONFIG_MODULE_SIG_ALL)
+
+     If this is on then modules will be automatically signed during the
+     modules_install phase of a build.  If this is off, then the modules must
+     be signed manually using:
+
+       scripts/sign-file
+
+
+ (3) "Which hash algorithm should modules be signed with?"
+
+     This presents a choice of which hash algorithm the installation phase will
+     sign the modules with:
+
+       CONFIG_SIG_SHA1         "Sign modules with SHA-1"
+       CONFIG_SIG_SHA224       "Sign modules with SHA-224"
+       CONFIG_SIG_SHA256       "Sign modules with SHA-256"
+       CONFIG_SIG_SHA384       "Sign modules with SHA-384"
+       CONFIG_SIG_SHA512       "Sign modules with SHA-512"
+
+     The algorithm selected here will also be built into the kernel (rather
+     than being a module) so that modules signed with that algorithm can have
+     their signatures checked without causing a dependency loop.
+
+
+=======================
+GENERATING SIGNING KEYS
+=======================
+
+Cryptographic keypairs are required to generate and check signatures.  A
+private key is used to generate a signature and the corresponding public key is
+used to check it.  The private key is only needed during the build, after which
+it can be deleted or stored securely.  The public key gets built into the
+kernel so that it can be used to check the signatures as the modules are
+loaded.
+
+Under normal conditions, the kernel build will automatically generate a new
+keypair using openssl if one does not exist in the files:
+
+       signing_key.priv
+       signing_key.x509
+
+during the building of vmlinux (the public part of the key needs to be built
+into vmlinux) using parameters in the:
+
+       x509.genkey
+
+file (which is also generated if it does not already exist).
+
+It is strongly recommended that you provide your own x509.genkey file.
+
+Most notably, in the x509.genkey file, the req_distinguished_name section
+should be altered from the default:
+
+       [ req_distinguished_name ]
+       O = Magrathea
+       CN = Glacier signing key
+       emailAddress = slartibartfast@magrathea.h2g2
+
+The generated RSA key size can also be set with:
+
+       [ req ]
+       default_bits = 4096
+
+
+It is also possible to manually generate the key private/public files using the
+x509.genkey key generation configuration file in the root node of the Linux
+kernel sources tree and the openssl command.  The following is an example to
+generate the public/private key files:
+
+       openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
+          -config x509.genkey -outform DER -out signing_key.x509 \
+          -keyout signing_key.priv
+
+
+=========================
+PUBLIC KEYS IN THE KERNEL
+=========================
+
+The kernel contains a ring of public keys that can be viewed by root.  They're
+in a keyring called ".system_keyring" that can be seen by:
+
+       [root@deneb ~]# cat /proc/keys
+       ...
+       223c7853 I------     1 perm 1f030000     0     0 keyring   .system_keyring: 1
+       302d2d52 I------     1 perm 1f010000     0     0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
+       ...
+
+Beyond the public key generated specifically for module signing, any file
+placed in the kernel source root directory or the kernel build root directory
+whose name is suffixed with ".x509" will be assumed to be an X.509 public key
+and will be added to the keyring.
+
+Further, the architecture code may take public keys from a hardware store and
+add those in also (e.g. from the UEFI key database).
+
+Finally, it is possible to add additional public keys by doing:
+
+       keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]
+
+e.g.:
+
+       keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
+
+Note, however, that the kernel will only permit keys to be added to
+.system_keyring _if_ the new key's X.509 wrapper is validly signed by a key
+that is already resident in the .system_keyring at the time the key was added.
+
+
+=========================
+MANUALLY SIGNING MODULES
+=========================
+
+To manually sign a module, use the scripts/sign-file tool available in
+the Linux kernel source tree.  The script requires 4 arguments:
+
+       1.  The hash algorithm (e.g., sha256)
+       2.  The private key filename
+       3.  The public key filename
+       4.  The kernel module to be signed
+
+The following is an example to sign a kernel module:
+
+       scripts/sign-file sha512 kernel-signkey.priv \
+               kernel-signkey.x509 module.ko
+
+The hash algorithm used does not have to match the one configured, but if it
+doesn't, you should make sure that hash algorithm is either built into the
+kernel or can be loaded without requiring itself.
+
+
+============================
+SIGNED MODULES AND STRIPPING
+============================
+
+A signed module has a digital signature simply appended at the end.  The string
+"~Module signature appended~." at the end of the module's file confirms that a
+signature is present but it does not confirm that the signature is valid!
+
+Signed modules are BRITTLE as the signature is outside of the defined ELF
+container.  Thus they MAY NOT be stripped once the signature is computed and
+attached.  Note the entire module is the signed payload, including any and all
+debug information present at the time of signing.
+
+
+======================
+LOADING SIGNED MODULES
+======================
+
+Modules are loaded with insmod, modprobe, init_module() or finit_module(),
+exactly as for unsigned modules as no processing is done in userspace.  The
+signature checking is all done within the kernel.
+
+
+=========================================
+NON-VALID SIGNATURES AND UNSIGNED MODULES
+=========================================
+
+If CONFIG_MODULE_SIG_FORCE is enabled or enforcemodulesig=1 is supplied on
+the kernel command line, the kernel will only load validly signed modules
+for which it has a public key.   Otherwise, it will also load modules that are
+unsigned.   Any module for which the kernel has a key, but which proves to have
+a signature mismatch will not be permitted to load.
+
+Any module that has an unparseable signature will be rejected.
+
+
+=========================================
+ADMINISTERING/PROTECTING THE PRIVATE KEY
+=========================================
+
+Since the private key is used to sign modules, viruses and malware could use
+the private key to sign modules and compromise the operating system.  The
+private key must be either destroyed or moved to a secure location and not kept
+in the root node of the kernel source tree.
index 89490beb3c0bf6bd0160c891b51e3cf07497f1ca..58e49042fc208291e3aec884c96684a606fe06d3 100644 (file)
@@ -66,11 +66,10 @@ All  mesh  wide  settings  can be found in batman's own interface
 folder:
 
 # ls /sys/class/net/bat0/mesh/
-# aggregated_ogms        gw_bandwidth           log_level
-# ap_isolation           gw_mode                orig_interval
-# bonding                gw_sel_class           routing_algo
-# bridge_loop_avoidance  hop_penalty            fragmentation
-
+#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
 
 There is a special folder for debugging information:
 
index 2cdb8b66caa934b04f42d4290a297664dcd15251..a4d925e4ba7a1f6b678d293605e63df45bdcdf66 100644 (file)
@@ -853,6 +853,14 @@ resend_igmp
 
        This option was added for bonding version 3.7.0.
 
+lp_interval
+
+       Specifies the number of seconds between instances where the bonding
+       driver sends learning packets to each slaves peer switch.
+
+       The valid range is 1 - 0x7fffffff; the default value is 1. This Option
+       has effect only in balance-tlb and balance-alb modes.
+
 3. Configuring Bonding Devices
 ==============================
 
diff --git a/Documentation/networking/i40evf.txt b/Documentation/networking/i40evf.txt
new file mode 100644 (file)
index 0000000..21e4127
--- /dev/null
@@ -0,0 +1,47 @@
+Linux* Base Driver for Intel(R) Network Connection
+==================================================
+
+Intel XL710 X710 Virtual Function Linux driver.
+Copyright(c) 2013 Intel Corporation.
+
+Contents
+========
+
+- Identifying Your Adapter
+- Known Issues/Troubleshooting
+- Support
+
+This file describes the i40evf Linux* Base Driver for the Intel(R) XL710
+X710 Virtual Function.
+
+The i40evf driver supports XL710 and X710 virtual function devices that
+can only be activated on kernels with CONFIG_PCI_IOV enabled.
+
+The guest OS loading the i40evf driver must support MSI-X interrupts.
+
+Identifying Your Adapter
+========================
+
+For more information on how to identify your adapter, go to the Adapter &
+Driver ID Guide at:
+
+    http://support.intel.com/support/go/network/adapter/idguide.htm
+
+Known Issues/Troubleshooting
+============================
+
+
+Support
+=======
+
+For general information, go to the Intel support website at:
+
+    http://support.intel.com
+
+or the Intel Wired Networking project hosted by Sourceforge at:
+
+    http://sourceforge.net/projects/e1000
+
+If an issue is identified with the released source code on the supported
+kernel with a supported adapter, email the specific information related
+to the issue to e1000-devel@lists.sf.net
index d71afa8bd82810d46e1e91f6275d8e2de3260176..c97932c88ea3a39b8547d67df667061c9b677a30 100644 (file)
@@ -26,12 +26,36 @@ ip_no_pmtu_disc - INTEGER
        discarded. Outgoing frames are handled the same as in mode 1,
        implicitly setting IP_PMTUDISC_DONT on every created socket.
 
-       Possible values: 0-2
+       Mode 3 is a hardend pmtu discover mode. The kernel will only
+       accept fragmentation-needed errors if the underlying protocol
+       can verify them besides a plain socket lookup. Current
+       protocols for which pmtu events will be honored are TCP, SCTP
+       and DCCP as they verify e.g. the sequence number or the
+       association. This mode should not be enabled globally but is
+       only intended to secure e.g. name servers in namespaces where
+       TCP path mtu must still work but path MTU information of other
+       protocols should be discarded. If enabled globally this mode
+       could break other protocols.
+
+       Possible values: 0-3
        Default: FALSE
 
 min_pmtu - INTEGER
        default 552 - minimum discovered Path MTU
 
+ip_forward_use_pmtu - BOOLEAN
+       By default we don't trust protocol path MTUs while forwarding
+       because they could be easily forged and can lead to unwanted
+       fragmentation by the router.
+       You only need to enable this if you have user-space software
+       which tries to discover path mtus by itself and depends on the
+       kernel honoring this information. This is normally not the
+       case.
+       Default: 0 (disabled)
+       Possible values:
+       0 - disabled
+       1 - enabled
+
 route/max_size - INTEGER
        Maximum number of routes allowed in the kernel.  Increase
        this when using large numbers of interfaces and/or routes.
@@ -1094,6 +1118,13 @@ bindv6only - BOOLEAN
 
        Default: FALSE (as specified in RFC3493)
 
+anycast_src_echo_reply - BOOLEAN
+       Controls the use of anycast addresses as source addresses for ICMPv6
+       echo reply
+       TRUE:  enabled
+       FALSE: disabled
+       Default: FALSE
+
 IPv6 Fragmentation:
 
 ip6frag_high_thresh - INTEGER
index 4288ffafba9fb878e348a37d2dd1849849d5f5d7..91ffe1d9e8cab8bd1c42314fb065b6ace17632bb 100644 (file)
@@ -98,6 +98,11 @@ by the kernel.
 The destruction of the socket and all associated resources
 is done by a simple call to close(fd).
 
+Similarly as without PACKET_MMAP, it is possible to use one socket
+for capture and transmission. This can be done by mapping the
+allocated RX and TX buffer ring with a single mmap() call.
+See "Mapping and use of the circular buffer (ring)".
+
 Next I will describe PACKET_MMAP settings and its constraints,
 also the mapping of the circular buffer in the user process and 
 the use of this buffer.
@@ -414,6 +419,19 @@ tp_block_size/tp_frame_size frames there will be a gap between
 the frames. This is because a frame cannot be spawn across two
 blocks. 
 
+To use one socket for capture and transmission, the mapping of both the
+RX and TX buffer ring has to be done with one call to mmap:
+
+    ...
+    setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &foo, sizeof(foo));
+    setsockopt(fd, SOL_PACKET, PACKET_TX_RING, &bar, sizeof(bar));
+    ...
+    rx_ring = mmap(0, size * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    tx_ring = rx_ring + size;
+
+RX must be the first as the kernel maps the TX ring memory right
+after the RX one.
+
 At the beginning of each frame there is an status field (see 
 struct tpacket_hdr). If this field is 0 means that the frame is ready
 to be used for the kernel, If not, there is a frame the user can read 
@@ -517,8 +535,6 @@ where 'tpacket_version' can be TPACKET_V1 (default), TPACKET_V2, TPACKET_V3.
 TPACKET_V1:
        - Default if not otherwise specified by setsockopt(2)
        - RX_RING, TX_RING available
-       - VLAN metadata information available for packets
-         (TP_STATUS_VLAN_VALID)
 
 TPACKET_V1 --> TPACKET_V2:
        - Made 64 bit clean due to unsigned long usage in TPACKET_V1
@@ -526,6 +542,13 @@ TPACKET_V1 --> TPACKET_V2:
          userspace and the like
        - Timestamp resolution in nanoseconds instead of microseconds
        - RX_RING, TX_RING available
+       - VLAN metadata information available for packets
+         (TP_STATUS_VLAN_VALID, TP_STATUS_VLAN_TPID_VALID),
+         in the tpacket2_hdr structure:
+               - TP_STATUS_VLAN_VALID bit being set into the tp_status field indicates
+                 that the tp_vlan_tci field has valid VLAN TCI value
+               - TP_STATUS_VLAN_TPID_VALID bit being set into the tp_status field
+                 indicates that the tp_vlan_tpid field has valid VLAN TPID value
        - How to switch to TPACKET_V2:
                1. Replace struct tpacket_hdr by struct tpacket2_hdr
                2. Query header len and save
index 9bae7901162d29ea007ec467091d3a47802152af..e11d4952bb26d0b61945a8163aa93edd2f16bd61 100644 (file)
@@ -783,7 +783,7 @@ F:  arch/arm/boot/dts/sama*.dts
 F:     arch/arm/boot/dts/sama*.dtsi
 
 ARM/CALXEDA HIGHBANK ARCHITECTURE
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-highbank/
@@ -1008,6 +1008,8 @@ M:        Santosh Shilimkar <santosh.shilimkar@ti.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-keystone/
+F:     drivers/clk/keystone/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
 
 ARM/LOGICPD PXA270 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
@@ -1430,7 +1432,7 @@ F:        Documentation/aoe/
 F:     drivers/block/aoe/
 
 ATHEROS ATH GENERIC UTILITIES
-M:     "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
+M:     "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
 L:     linux-wireless@vger.kernel.org
 S:     Supported
 F:     drivers/net/wireless/ath/*
@@ -1438,7 +1440,7 @@ F:        drivers/net/wireless/ath/*
 ATHEROS ATH5K WIRELESS DRIVER
 M:     Jiri Slaby <jirislaby@gmail.com>
 M:     Nick Kossifidis <mickflemm@gmail.com>
-M:     "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
+M:     "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
 L:     linux-wireless@vger.kernel.org
 L:     ath5k-devel@lists.ath5k.org
 W:     http://wireless.kernel.org/en/users/Drivers/ath5k
@@ -3823,6 +3825,12 @@ T:       git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/
 
+GUID PARTITION TABLE (GPT)
+M:     Davidlohr Bueso <davidlohr@hp.com>
+L:     linux-efi@vger.kernel.org
+S:     Maintained
+F:     block/partitions/efi.*
+
 STK1160 USB VIDEO CAPTURE DRIVER
 M:     Ezequiel Garcia <elezegarcia@gmail.com>
 L:     linux-media@vger.kernel.org
@@ -4451,7 +4459,7 @@ M:        Deepak Saxena <dsaxena@plexity.net>
 S:     Maintained
 F:     drivers/char/hw_random/ixp4xx-rng.c
 
-INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf/i40e)
+INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf/i40e/i40evf)
 M:     Jeff Kirsher <jeffrey.t.kirsher@intel.com>
 M:     Jesse Brandeburg <jesse.brandeburg@intel.com>
 M:     Bruce Allan <bruce.w.allan@intel.com>
@@ -4460,6 +4468,7 @@ M:        Don Skidmore <donald.c.skidmore@intel.com>
 M:     Greg Rose <gregory.v.rose@intel.com>
 M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
+M:     Mitch Williams <mitch.a.williams@intel.com>
 L:     e1000-devel@lists.sourceforge.net
 W:     http://www.intel.com/support/feedback.htm
 W:     http://e1000.sourceforge.net/
@@ -4475,6 +4484,7 @@ F:        Documentation/networking/ixgb.txt
 F:     Documentation/networking/ixgbe.txt
 F:     Documentation/networking/ixgbevf.txt
 F:     Documentation/networking/i40e.txt
+F:     Documentation/networking/i40evf.txt
 F:     drivers/net/ethernet/intel/
 
 INTEL-MID GPIO DRIVER
@@ -6238,7 +6248,7 @@ F:        drivers/i2c/busses/i2c-ocores.c
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE
 M:     Grant Likely <grant.likely@linaro.org>
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 L:     devicetree@vger.kernel.org
 W:     http://fdt.secretlab.ca
 T:     git git://git.secretlab.ca/git/linux-2.6.git
@@ -6250,7 +6260,7 @@ K:        of_get_property
 K:     of_match_table
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 M:     Pawel Moll <pawel.moll@arm.com>
 M:     Mark Rutland <mark.rutland@arm.com>
 M:     Ian Campbell <ijc+devicetree@hellion.org.uk>
@@ -9579,7 +9589,7 @@ F:        drivers/xen/*swiotlb*
 
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
-M:     Dave Chinner <dchinner@fromorbit.com>
+M:     Dave Chinner <david@fromorbit.com>
 M:     Ben Myers <bpm@sgi.com>
 M:     xfs@oss.sgi.com
 L:     xfs@oss.sgi.com
index 858a147fd836a668a7b35d2ed0ddb6a9adc68c29..ab80be7a38bca0261b2adc49e878f00fea113dcd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 13
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc6
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
@@ -732,19 +732,15 @@ export mod_strip_cmd
 # Select initial ramdisk compression format, default is gzip(1).
 # This shall be used by the dracut(8) tool while creating an initramfs image.
 #
-INITRD_COMPRESS=gzip
-ifeq ($(CONFIG_RD_BZIP2), y)
-        INITRD_COMPRESS=bzip2
-else ifeq ($(CONFIG_RD_LZMA), y)
-        INITRD_COMPRESS=lzma
-else ifeq ($(CONFIG_RD_XZ), y)
-        INITRD_COMPRESS=xz
-else ifeq ($(CONFIG_RD_LZO), y)
-        INITRD_COMPRESS=lzo
-else ifeq ($(CONFIG_RD_LZ4), y)
-        INITRD_COMPRESS=lz4
-endif
-export INITRD_COMPRESS
+INITRD_COMPRESS-y                  := gzip
+INITRD_COMPRESS-$(CONFIG_RD_BZIP2) := bzip2
+INITRD_COMPRESS-$(CONFIG_RD_LZMA)  := lzma
+INITRD_COMPRESS-$(CONFIG_RD_XZ)    := xz
+INITRD_COMPRESS-$(CONFIG_RD_LZO)   := lzo
+INITRD_COMPRESS-$(CONFIG_RD_LZ4)   := lz4
+# do not export INITRD_COMPRESS, since we didn't actually
+# choose a sane default compression above.
+# export INITRD_COMPRESS := $(INITRD_COMPRESS-y)
 
 ifdef CONFIG_MODULE_SIG_ALL
 MODSECKEY = ./signing_key.priv
index 93e6ca9196202a769c6d8d5725f8952672d812b5..cf29d84fd9c2e6bfd904771c77d6bf76e689b16d 100644 (file)
@@ -11,6 +11,7 @@ generic-y += fcntl.h
 generic-y += fb.h
 generic-y += ftrace.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -47,4 +48,3 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += preempt.h
-generic-y += hash.h
index 68125dd766c68feeb9de6715c9d1694ed24e5491..39e58d1cdf90b7d8f84d108d8024d8974c3b800c 100644 (file)
@@ -8,7 +8,11 @@
 
 /******** no-legacy-syscalls-ABI *******/
 
-#ifndef _UAPI_ASM_ARC_UNISTD_H
+/*
+ * Non-typical guard macro to enable inclusion twice in ARCH sys.c
+ * That is how the Generic syscall wrapper generator works
+ */
+#if !defined(_UAPI_ASM_ARC_UNISTD_H) || defined(__SYSCALL)
 #define _UAPI_ASM_ARC_UNISTD_H
 
 #define __ARCH_WANT_SYS_EXECVE
@@ -36,4 +40,6 @@ __SYSCALL(__NR_arc_gettls, sys_arc_gettls)
 #define __NR_sysfs             (__NR_arch_specific_syscall + 3)
 __SYSCALL(__NR_sysfs, sys_sysfs)
 
+#undef __SYSCALL
+
 #endif
index ee845fad939b895a1bfb907c6597f9f916d926f8..9987dd0e9c599929042b1ce70d4b1d6c3ec1ebfb 100644 (file)
@@ -87,9 +87,9 @@
                interrupts = <1 9 0xf04>;
        };
 
-       gpio0: gpio@ffc40000 {
+       gpio0: gpio@e6050000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc40000 0 0x2c>;
+               reg = <0 0xe6050000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 4 0x4>;
                #gpio-cells = <2>;
@@ -99,9 +99,9 @@
                interrupt-controller;
        };
 
-       gpio1: gpio@ffc41000 {
+       gpio1: gpio@e6051000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc41000 0 0x2c>;
+               reg = <0 0xe6051000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 5 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio2: gpio@ffc42000 {
+       gpio2: gpio@e6052000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc42000 0 0x2c>;
+               reg = <0 0xe6052000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 6 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio3: gpio@ffc43000 {
+       gpio3: gpio@e6053000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc43000 0 0x2c>;
+               reg = <0 0xe6053000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 7 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio4: gpio@ffc44000 {
+       gpio4: gpio@e6054000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc44000 0 0x2c>;
+               reg = <0 0xe6054000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 8 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio5: gpio@ffc45000 {
+       gpio5: gpio@e6055000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc45000 0 0x2c>;
+               reg = <0 0xe6055000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 9 0x4>;
                #gpio-cells = <2>;
 
        sdhi0: sdhi@ee100000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee100000 0 0x100>;
+               reg = <0 0xee100000 0 0x200>;
                interrupt-parent = <&gic>;
                interrupts = <0 165 4>;
                cap-sd-highspeed;
 
        sdhi1: sdhi@ee120000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee120000 0 0x100>;
+               reg = <0 0xee120000 0 0x200>;
                interrupt-parent = <&gic>;
                interrupts = <0 166 4>;
                cap-sd-highspeed;
index 4ec8d82b0492f3e66e75bec0aa7cff8cd25a5faa..44a59c3abfb0535e8c9168284a5bf67ed0f13bb6 100644 (file)
@@ -242,12 +242,18 @@ static void __init ldp_display_init(void)
 
 static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
 {
+       int res;
+
        /* LCD enable GPIO */
        ldp_lcd_pdata.enable_gpio = gpio + 7;
 
        /* Backlight enable GPIO */
        ldp_lcd_pdata.backlight_gpio = gpio + 15;
 
+       res = platform_device_register(&ldp_lcd_device);
+       if (res)
+               pr_err("Unable to register LCD: %d\n", res);
+
        return 0;
 }
 
@@ -346,7 +352,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 
 static struct platform_device *ldp_devices[] __initdata = {
        &ldp_gpio_keys_device,
-       &ldp_lcd_device,
 };
 
 #ifdef CONFIG_OMAP_MUX
index 58347bb874a01dcd4d203f4f191712d473a338a3..4cf165502b35cfdd06c09696a20b09758d974169 100644 (file)
@@ -101,13 +101,51 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
        { "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
+static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+{
+       u32 enable_mask, enable_shift;
+       u32 pipd_mask, pipd_shift;
+       u32 reg;
+
+       if (dsi_id == 0) {
+               enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
+               enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
+               pipd_mask = OMAP4_DSI1_PIPD_MASK;
+               pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
+       } else if (dsi_id == 1) {
+               enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
+               enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
+               pipd_mask = OMAP4_DSI2_PIPD_MASK;
+               pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
+       } else {
+               return -ENODEV;
+       }
+
+       reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+       reg &= ~enable_mask;
+       reg &= ~pipd_mask;
+
+       reg |= (lanes << enable_shift) & enable_mask;
+       reg |= (lanes << pipd_shift) & pipd_mask;
+
+       omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+       return 0;
+}
+
 static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
+       if (cpu_is_omap44xx())
+               return omap4_dsi_mux_pads(dsi_id, lane_mask);
+
        return 0;
 }
 
 static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
+       if (cpu_is_omap44xx())
+               omap4_dsi_mux_pads(dsi_id, 0);
 }
 
 static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput)
index 56cebb05509e15c0054f342e158a21214b7a6603..d23c77fadb31036058ab7b750cf02495d2ef33ab 100644 (file)
@@ -796,7 +796,7 @@ struct omap_hwmod omap2xxx_counter_32k_hwmod = {
 
 /* gpmc */
 static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = {
-       { .irq = 20 },
+       { .irq = 20 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -841,7 +841,7 @@ static struct omap_hwmod_class omap2_rng_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap2_rng_mpu_irqs[] = {
-       { .irq = 52 },
+       { .irq = 52 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
index d33742908f970a21b24c2cefeef03799d3d84532..4c3b1e6df50806700cbcfc3c4f582650b36cc3a3 100644 (file)
@@ -2165,7 +2165,7 @@ static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
-       { .irq = 20 },
+       { .irq = 20 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -2999,7 +2999,7 @@ static struct omap_mmu_dev_attr mmu_isp_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mmu_isp_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_mmu_isp_irqs[] = {
-       { .irq = 24 },
+       { .irq = 24 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -3041,7 +3041,7 @@ static struct omap_mmu_dev_attr mmu_iva_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mmu_iva_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_mmu_iva_irqs[] = {
-       { .irq = 28 },
+       { .irq = 28 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
index db32d5380b118cda247e6f8e863bc14906eed6bc..18f333c440db3b72ff49577ef71d24b64dbcc916 100644 (file)
@@ -1637,7 +1637,7 @@ static struct omap_hwmod dra7xx_uart1_hwmod = {
        .class          = &dra7xx_uart_hwmod_class,
        .clkdm_name     = "l4per_clkdm",
        .main_clk       = "uart1_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
+       .flags          = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP2UART1_FLAGS,
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = DRA7XX_CM_L4PER_UART1_CLKCTRL_OFFSET,
index 2a086e8373eb7bf1104892784aba7a5236a3bd5b..958cd6af93842566308a33d11f1799dd78f332d9 100644 (file)
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <mach/irqs.h>
+
 #define LUBBOCK_ETH_PHYS       PXA_CS3_PHYS
 
 #define LUBBOCK_FPGA_PHYS      PXA_CS2_PHYS
index 7eb9a10fc1af68d81b1dd308ebfd352d28c9e416..2fddf38192df3ad0f67bc646914e7d4121a6b41c 100644 (file)
@@ -8,8 +8,6 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/clk-provider.h>
-#include <linux/irqchip.h>
 #include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
@@ -48,15 +46,9 @@ static void __init s3c64xx_dt_map_io(void)
                panic("SoC is not S3C64xx!");
 }
 
-static void __init s3c64xx_dt_init_irq(void)
-{
-       of_clk_init(NULL);
-       samsung_wdt_reset_of_init();
-       irqchip_init();
-};
-
 static void __init s3c64xx_dt_init_machine(void)
 {
+       samsung_wdt_reset_of_init();
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
@@ -79,7 +71,6 @@ DT_MACHINE_START(S3C6400_DT, "Samsung S3C64xx (Flattened Device Tree)")
        /* Maintainer: Tomasz Figa <tomasz.figa@gmail.com> */
        .dt_compat      = s3c64xx_dt_compat,
        .map_io         = s3c64xx_dt_map_io,
-       .init_irq       = s3c64xx_dt_init_irq,
        .init_machine   = s3c64xx_dt_init_machine,
        .restart        = s3c64xx_dt_restart,
 MACHINE_END
index 958e3cbf0ac2f2110e7f4fc9ca41dc19e66e4ca8..c186891230233fe617161531b5f637246b4e0da7 100644 (file)
@@ -614,6 +614,11 @@ static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
        REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
 };
 
+/* Fixed 3.3V regulator used by LCD backlight */
+static struct regulator_consumer_supply fixed5v0_power_consumers[] = {
+       REGULATOR_SUPPLY("power", "pwm-backlight.0"),
+};
+
 /* Fixed 3.3V regulator to be used by SDHI0 */
 static struct regulator_consumer_supply vcc_sdhi0_consumers[] = {
        REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
@@ -1196,6 +1201,8 @@ static void __init eva_init(void)
 
        regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
                                     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+       regulator_register_always_on(3, "fixed-5.0V", fixed5v0_power_consumers,
+                                    ARRAY_SIZE(fixed5v0_power_consumers), 5000000);
 
        pinctrl_register_mappings(eva_pinctrl_map, ARRAY_SIZE(eva_pinctrl_map));
        pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
index 38611526fe9a55953372afcd2662aa668b34e080..3c4995aebd220870406934ba905d90d5949d18ca 100644 (file)
@@ -679,7 +679,7 @@ static void __init bockw_init(void)
                        .id             = i,
                        .data           = &rsnd_card_info[i],
                        .size_data      = sizeof(struct asoc_simple_card_info),
-                       .dma_mask       = ~0,
+                       .dma_mask       = DMA_BIT_MASK(32),
                };
 
                platform_device_register_full(&cardinfo);
index a8d3ce646fb900514fa983964bf8d70d0e88c278..e0406fd373906e4d43d53769a7d7cfa548b6f388 100644 (file)
@@ -245,7 +245,9 @@ static void __init lager_init(void)
 {
        lager_add_standard_devices();
 
-       phy_register_fixup_for_id("r8a7790-ether-ff:01", lager_ksz8041_fixup);
+       if (IS_ENABLED(CONFIG_PHYLIB))
+               phy_register_fixup_for_id("r8a7790-ether-ff:01",
+                                         lager_ksz8041_fixup);
 }
 
 static const char * const lager_boards_compat_dt[] __initconst = {
index 83e4f959ee47c6b9b18a77d9f50995b7b4fc5ab0..85501238b4258316272f9448ad8829b18a1111b2 100644 (file)
@@ -96,7 +96,7 @@ static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
        struct remap_data *info = data;
        struct page *page = info->pages[info->index++];
        unsigned long pfn = page_to_pfn(page);
-       pte_t pte = pfn_pte(pfn, info->prot);
+       pte_t pte = pte_mkspecial(pfn_pte(pfn, info->prot));
 
        if (map_foreign_page(pfn, info->fgmfn, info->domid))
                return -EFAULT;
@@ -224,10 +224,10 @@ static int __init xen_guest_init(void)
        }
        if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
                return 0;
-       xen_hvm_resume_frames = res.start >> PAGE_SHIFT;
+       xen_hvm_resume_frames = res.start;
        xen_events_irq = irq_of_parse_and_map(node, 0);
        pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n",
-                       version, xen_events_irq, xen_hvm_resume_frames);
+                       version, xen_events_irq, (xen_hvm_resume_frames >> PAGE_SHIFT));
        xen_domain_type = XEN_HVM_DOMAIN;
 
        xen_setup_features();
index 2820f1a6eebe0252d280e5d56e0a6bc60ac14182..dde3fc9c49f015c80b43f9ca21f1d996b9d2a910 100644 (file)
@@ -23,25 +23,21 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir,
             struct dma_attrs *attrs)
 {
-       __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
 }
 
 static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir,
                struct dma_attrs *attrs)
 {
-       __generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
 }
 
 static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
-       __generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
 }
 
 static inline void xen_dma_sync_single_for_device(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
-       __generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
 }
 #endif /* _ASM_ARM64_XEN_PAGE_COHERENT_H */
index 6777a2192b83846f1065f442f5777d4092e9bc0c..6a8928bba03c9e8135c4481b497268f7018ca393 100644 (file)
@@ -214,31 +214,29 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
 {
        int err, len, type, disabled = !ctrl.enabled;
 
-       if (disabled) {
-               len = 0;
-               type = HW_BREAKPOINT_EMPTY;
-       } else {
-               err = arch_bp_generic_fields(ctrl, &len, &type);
-               if (err)
-                       return err;
-
-               switch (note_type) {
-               case NT_ARM_HW_BREAK:
-                       if ((type & HW_BREAKPOINT_X) != type)
-                               return -EINVAL;
-                       break;
-               case NT_ARM_HW_WATCH:
-                       if ((type & HW_BREAKPOINT_RW) != type)
-                               return -EINVAL;
-                       break;
-               default:
+       attr->disabled = disabled;
+       if (disabled)
+               return 0;
+
+       err = arch_bp_generic_fields(ctrl, &len, &type);
+       if (err)
+               return err;
+
+       switch (note_type) {
+       case NT_ARM_HW_BREAK:
+               if ((type & HW_BREAKPOINT_X) != type)
                        return -EINVAL;
-               }
+               break;
+       case NT_ARM_HW_WATCH:
+               if ((type & HW_BREAKPOINT_RW) != type)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
        }
 
        attr->bp_len    = len;
        attr->bp_type   = type;
-       attr->disabled  = disabled;
 
        return 0;
 }
index c5963b3e4624a9bfd6162fcfb44235a614afde6c..406cbd3ebd5849cb485861b8f5488ab1550686ee 100644 (file)
@@ -5,6 +5,7 @@ header-y += arch-v32/
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += kvm_para.h
 generic-y += linkage.h
 generic-y += module.h
@@ -12,4 +13,3 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += preempt.h
-generic-y += hash.h
index 469d223950ff4eaa0a875d0fa900097d227a4b1c..ae45d75a3187e0e4bb17c60d56caf61ba9a6395d 100644 (file)
@@ -15,6 +15,7 @@ generic-y += fb.h
 generic-y += fcntl.h
 generic-y += ftrace.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -54,4 +55,3 @@ generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += xor.h
 generic-y += preempt.h
-generic-y += hash.h
index 43eec338ff504edfac853626ed872349152170c8..ca60945ddf307cddaef5989df64258db8638362d 100644 (file)
@@ -1,7 +1,7 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += trace_clock.h
 generic-y += syscalls.h
 generic-y += preempt.h
-generic-y += hash.h
index 1f30571968e78194ad6338b4f0ac3cb3b64332bc..9057728ac56b4cfa2130b122f2130df966ca7275 100644 (file)
@@ -28,6 +28,9 @@
 
 #include <linux/export.h>
 #include <linux/types.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_embedded.h>
 #include <linux/bcma/bcma_soc.h>
@@ -225,6 +228,12 @@ void __init plat_mem_setup(void)
        bcm47xx_board_detect();
 }
 
+static struct fixed_phy_status bcm47xx_fixed_phy_status __initdata = {
+       .link   = 1,
+       .speed  = SPEED_100,
+       .duplex = DUPLEX_FULL,
+};
+
 static int __init bcm47xx_register_bus_complete(void)
 {
        switch (bcm47xx_bus_type) {
@@ -239,6 +248,7 @@ static int __init bcm47xx_register_bus_complete(void)
                break;
 #endif
        }
+       fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status);
        return 0;
 }
 device_initcall(bcm47xx_register_bus_complete);
index bc42f14c9c2e706081c66b3805a9369d65e4bce9..199345207d8292f56118c8bc39b74584ad4a1dde 100644 (file)
@@ -1,6 +1,6 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += trace_clock.h
 generic-y += preempt.h
-generic-y += hash.h
index 4177b62240c2440ff19f6089cb84cd5b9e0d27a0..a618dfc13e4c8f88a5ff70b88325fd39675c9e8a 100644 (file)
@@ -58,7 +58,6 @@
                compatible = "fsl,mpc5121-immr";
                #address-cells = <1>;
                #size-cells = <1>;
-               #interrupt-cells = <2>;
                ranges = <0x0 0x80000000 0x400000>;
                reg = <0x80000000 0x400000>;
                bus-frequency = <66000000>;     // 66 MHz ips bus
                        reg = <0xA000 0x1000>;
                };
 
+               // disable USB1 port
+               // TODO:
+               // correct pinmux config and fix USB3320 ulpi dependency
+               // before re-enabling it
                usb@3000 {
                        compatible = "fsl,mpc5121-usb2-dr";
                        reg = <0x3000 0x400>;
                        interrupts = <43 0x8>;
                        dr_mode = "host";
                        phy_type = "ulpi";
+                       status = "disabled";
                };
 
                // 5125 PSCs are not 52xx or 5121 PSC compatible
index 894662a5d4d5c5aa25f43e30653609d80d901774..243ce69ad685ffd335041537e6f0b33b0aafe3df 100644 (file)
@@ -284,7 +284,7 @@ do_kvm_##n:                                                         \
        subi    r1,r1,INT_FRAME_SIZE;   /* alloc frame on kernel stack  */ \
        beq-    1f;                                                        \
        ld      r1,PACAKSAVE(r13);      /* kernel stack to use          */ \
-1:     cmpdi   cr1,r1,0;               /* check if r1 is in userspace  */ \
+1:     cmpdi   cr1,r1,-INT_FRAME_SIZE; /* check if r1 is in userspace  */ \
        blt+    cr1,3f;                 /* abort if it is               */ \
        li      r1,(n);                 /* will be reloaded later       */ \
        sth     r1,PACA_TRAP_SAVE(r13);                                    \
index 4a594b76674d4e536ce714b40c183f598bf380d6..bc23b1ba798068b1c5a1f21e93da8bd47018ff55 100644 (file)
@@ -192,6 +192,10 @@ extern void kvmppc_load_up_vsx(void);
 extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
 extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
 extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
+extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
+                                struct kvm_vcpu *vcpu);
+extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
+                                  struct kvmppc_book3s_shadow_vcpu *svcpu);
 
 static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 {
index 0bd9348a4db91264d5e8a104f17ed77afcd5f815..192917d2239c4ed5a0eafd36b1206d176f0dddaa 100644 (file)
@@ -79,6 +79,7 @@ struct kvmppc_host_state {
        ulong vmhandler;
        ulong scratch0;
        ulong scratch1;
+       ulong scratch2;
        u8 in_guest;
        u8 restore_hid5;
        u8 napping;
@@ -106,6 +107,7 @@ struct kvmppc_host_state {
 };
 
 struct kvmppc_book3s_shadow_vcpu {
+       bool in_use;
        ulong gpr[14];
        u32 cr;
        u32 xer;
index 9ee12610af02bdca7fd61b9b7f6b16f2c74d36d0..aace90547614db30ea638945d30d143fbdfb336e 100644 (file)
@@ -35,7 +35,7 @@ extern void giveup_vsx(struct task_struct *);
 extern void enable_kernel_spe(void);
 extern void giveup_spe(struct task_struct *);
 extern void load_up_spe(struct task_struct *);
-extern void switch_booke_debug_regs(struct thread_struct *new_thread);
+extern void switch_booke_debug_regs(struct debug_reg *new_debug);
 
 #ifndef CONFIG_SMP
 extern void discard_lazy_cpu_state(void);
index 5f1b1e3c21374d5a1833ed00c9af9d5c06a35123..8296381ae43294e679976f6a82d3bb936d64921f 100644 (file)
@@ -4,13 +4,18 @@
 #ifdef __KERNEL__
 
 /*
- * The PowerPC can do unaligned accesses itself in big endian mode.
+ * The PowerPC can do unaligned accesses itself based on its endian mode.
  */
 #include <linux/unaligned/access_ok.h>
 #include <linux/unaligned/generic.h>
 
+#ifdef __LITTLE_ENDIAN__
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
+#else
 #define get_unaligned  __get_unaligned_be
 #define put_unaligned  __put_unaligned_be
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UNALIGNED_H */
index 2ea5cc033ec8b633febb50071c43cfd31958f4f3..d3de01066f7dd786cd531614046b801ff7ebb18f 100644 (file)
@@ -576,6 +576,7 @@ int main(void)
        HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
        HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
        HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
+       HSTATE_FIELD(HSTATE_SCRATCH2, scratch2);
        HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
        HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
        HSTATE_FIELD(HSTATE_NAPPING, napping);
index 2ae41aba40530f7facf916f6ce101ad3196a7363..4f0946de2d5c917540f6f51a50c13640011fea8c 100644 (file)
@@ -80,6 +80,7 @@ END_FTR_SECTION(0, 1)
         * of the function that the cpu should jump to to continue
         * initialization.
         */
+       .balign 8
        .globl  __secondary_hold_spinloop
 __secondary_hold_spinloop:
        .llong  0x0
@@ -470,6 +471,7 @@ _STATIC(__after_prom_start)
        mtctr   r8
        bctr
 
+.balign 8
 p_end: .llong  _end - _stext
 
 4:     /* Now copy the rest of the kernel up to _end */
index 3386d8ab7eb0607b3c9d6f03e68824d4abe4bd88..4a96556fd2d49e484c143ed3643db6c8a24962df 100644 (file)
@@ -339,7 +339,7 @@ static void set_debug_reg_defaults(struct thread_struct *thread)
 #endif
 }
 
-static void prime_debug_regs(struct thread_struct *thread)
+static void prime_debug_regs(struct debug_reg *debug)
 {
        /*
         * We could have inherited MSR_DE from userspace, since
@@ -348,22 +348,22 @@ static void prime_debug_regs(struct thread_struct *thread)
         */
        mtmsr(mfmsr() & ~MSR_DE);
 
-       mtspr(SPRN_IAC1, thread->debug.iac1);
-       mtspr(SPRN_IAC2, thread->debug.iac2);
+       mtspr(SPRN_IAC1, debug->iac1);
+       mtspr(SPRN_IAC2, debug->iac2);
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
-       mtspr(SPRN_IAC3, thread->debug.iac3);
-       mtspr(SPRN_IAC4, thread->debug.iac4);
+       mtspr(SPRN_IAC3, debug->iac3);
+       mtspr(SPRN_IAC4, debug->iac4);
 #endif
-       mtspr(SPRN_DAC1, thread->debug.dac1);
-       mtspr(SPRN_DAC2, thread->debug.dac2);
+       mtspr(SPRN_DAC1, debug->dac1);
+       mtspr(SPRN_DAC2, debug->dac2);
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
-       mtspr(SPRN_DVC1, thread->debug.dvc1);
-       mtspr(SPRN_DVC2, thread->debug.dvc2);
+       mtspr(SPRN_DVC1, debug->dvc1);
+       mtspr(SPRN_DVC2, debug->dvc2);
 #endif
-       mtspr(SPRN_DBCR0, thread->debug.dbcr0);
-       mtspr(SPRN_DBCR1, thread->debug.dbcr1);
+       mtspr(SPRN_DBCR0, debug->dbcr0);
+       mtspr(SPRN_DBCR1, debug->dbcr1);
 #ifdef CONFIG_BOOKE
-       mtspr(SPRN_DBCR2, thread->debug.dbcr2);
+       mtspr(SPRN_DBCR2, debug->dbcr2);
 #endif
 }
 /*
@@ -371,11 +371,11 @@ static void prime_debug_regs(struct thread_struct *thread)
  * debug registers, set the debug registers from the values
  * stored in the new thread.
  */
-void switch_booke_debug_regs(struct thread_struct *new_thread)
+void switch_booke_debug_regs(struct debug_reg *new_debug)
 {
        if ((current->thread.debug.dbcr0 & DBCR0_IDM)
-               || (new_thread->debug.dbcr0 & DBCR0_IDM))
-                       prime_debug_regs(new_thread);
+               || (new_debug->dbcr0 & DBCR0_IDM))
+                       prime_debug_regs(new_debug);
 }
 EXPORT_SYMBOL_GPL(switch_booke_debug_regs);
 #else  /* !CONFIG_PPC_ADV_DEBUG_REGS */
@@ -683,7 +683,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-       switch_booke_debug_regs(&new->thread);
+       switch_booke_debug_regs(&new->thread.debug);
 #else
 /*
  * For PPC_BOOK3S_64, we use the hw-breakpoint interfaces that would
index f3ff587a8b7d58e064e6364606e98a0e6473f106..c5d148434c08197034eba8ababd951176adb6a1f 100644 (file)
@@ -469,11 +469,14 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
                slb_v = vcpu->kvm->arch.vrma_slb_v;
        }
 
+       preempt_disable();
        /* Find the HPTE in the hash table */
        index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
                                         HPTE_V_VALID | HPTE_V_ABSENT);
-       if (index < 0)
+       if (index < 0) {
+               preempt_enable();
                return -ENOENT;
+       }
        hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
        v = hptep[0] & ~HPTE_V_HVLOCK;
        gr = kvm->arch.revmap[index].guest_rpte;
@@ -481,6 +484,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
        /* Unlock the HPTE */
        asm volatile("lwsync" : : : "memory");
        hptep[0] = v;
+       preempt_enable();
 
        gpte->eaddr = eaddr;
        gpte->vpage = ((v & HPTE_V_AVPN) << 4) | ((eaddr >> 12) & 0xfff);
@@ -665,6 +669,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        return -EFAULT;
        } else {
                page = pages[0];
+               pfn = page_to_pfn(page);
                if (PageHuge(page)) {
                        page = compound_head(page);
                        pte_size <<= compound_order(page);
@@ -689,7 +694,6 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        }
                        rcu_read_unlock_sched();
                }
-               pfn = page_to_pfn(page);
        }
 
        ret = -EFAULT;
@@ -707,8 +711,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                r = (r & ~(HPTE_R_W|HPTE_R_I|HPTE_R_G)) | HPTE_R_M;
        }
 
-       /* Set the HPTE to point to pfn */
-       r = (r & ~(HPTE_R_PP0 - pte_size)) | (pfn << PAGE_SHIFT);
+       /*
+        * Set the HPTE to point to pfn.
+        * Since the pfn is at PAGE_SIZE granularity, make sure we
+        * don't mask out lower-order bits if psize < PAGE_SIZE.
+        */
+       if (psize < PAGE_SIZE)
+               psize = PAGE_SIZE;
+       r = (r & ~(HPTE_R_PP0 - psize)) | ((pfn << PAGE_SHIFT) & ~(psize - 1));
        if (hpte_is_writable(r) && !write_ok)
                r = hpte_make_readonly(r);
        ret = RESUME_GUEST;
index 072287f1c3bc7347b6ff4f959843c97053fa4aa1..b51d5db780684ea5dcb3b6dae5c5bc70224dca43 100644 (file)
@@ -131,8 +131,9 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
 static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
+       unsigned long flags;
 
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE &&
            vc->preempt_tb != TB_NIL) {
                vc->stolen_tb += mftb() - vc->preempt_tb;
@@ -143,19 +144,20 @@ static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu)
                vcpu->arch.busy_stolen += mftb() - vcpu->arch.busy_preempt;
                vcpu->arch.busy_preempt = TB_NIL;
        }
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags);
 }
 
 static void kvmppc_core_vcpu_put_hv(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
+       unsigned long flags;
 
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
                vc->preempt_tb = mftb();
        if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST)
                vcpu->arch.busy_preempt = mftb();
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags);
 }
 
 static void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr)
@@ -486,11 +488,11 @@ static u64 vcore_stolen_time(struct kvmppc_vcore *vc, u64 now)
         */
        if (vc->vcore_state != VCORE_INACTIVE &&
            vc->runner->arch.run_task != current) {
-               spin_lock(&vc->runner->arch.tbacct_lock);
+               spin_lock_irq(&vc->runner->arch.tbacct_lock);
                p = vc->stolen_tb;
                if (vc->preempt_tb != TB_NIL)
                        p += now - vc->preempt_tb;
-               spin_unlock(&vc->runner->arch.tbacct_lock);
+               spin_unlock_irq(&vc->runner->arch.tbacct_lock);
        } else {
                p = vc->stolen_tb;
        }
@@ -512,10 +514,10 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
        core_stolen = vcore_stolen_time(vc, now);
        stolen = core_stolen - vcpu->arch.stolen_logged;
        vcpu->arch.stolen_logged = core_stolen;
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irq(&vcpu->arch.tbacct_lock);
        stolen += vcpu->arch.busy_stolen;
        vcpu->arch.busy_stolen = 0;
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irq(&vcpu->arch.tbacct_lock);
        if (!dt || !vpa)
                return;
        memset(dt, 0, sizeof(struct dtl_entry));
@@ -589,7 +591,9 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
                if (list_empty(&vcpu->kvm->arch.rtas_tokens))
                        return RESUME_HOST;
 
+               idx = srcu_read_lock(&vcpu->kvm->srcu);
                rc = kvmppc_rtas_hcall(vcpu);
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
                if (rc == -ENOENT)
                        return RESUME_HOST;
@@ -1115,13 +1119,13 @@ static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
 
        if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
                return;
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irq(&vcpu->arch.tbacct_lock);
        now = mftb();
        vcpu->arch.busy_stolen += vcore_stolen_time(vc, now) -
                vcpu->arch.stolen_logged;
        vcpu->arch.busy_preempt = now;
        vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irq(&vcpu->arch.tbacct_lock);
        --vc->n_runnable;
        list_del(&vcpu->arch.run_list);
 }
index 9c515440ad1ae7e0451d3b3b67dd029ab06a0ebb..8689e2e308573b0df26996e2ebfed77e235df59c 100644 (file)
@@ -225,6 +225,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                is_io = pa & (HPTE_R_I | HPTE_R_W);
                pte_size = PAGE_SIZE << (pa & KVMPPC_PAGE_ORDER_MASK);
                pa &= PAGE_MASK;
+               pa |= gpa & ~PAGE_MASK;
        } else {
                /* Translate to host virtual address */
                hva = __gfn_to_hva_memslot(memslot, gfn);
@@ -238,13 +239,13 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                                ptel = hpte_make_readonly(ptel);
                        is_io = hpte_cache_bits(pte_val(pte));
                        pa = pte_pfn(pte) << PAGE_SHIFT;
+                       pa |= hva & (pte_size - 1);
+                       pa |= gpa & ~PAGE_MASK;
                }
        }
 
        if (pte_size < psize)
                return H_PARAMETER;
-       if (pa && pte_size > psize)
-               pa |= gpa & (pte_size - 1);
 
        ptel &= ~(HPTE_R_PP0 - psize);
        ptel |= pa;
@@ -749,6 +750,10 @@ static int slb_base_page_shift[4] = {
        20,     /* 1M, unsupported */
 };
 
+/* When called from virtmode, this func should be protected by
+ * preempt_disable(), otherwise, the holding of HPTE_V_HVLOCK
+ * can trigger deadlock issue.
+ */
 long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
                              unsigned long valid)
 {
index bc8de75b1925cd34ad1d11379fee8c09f1d275e5..be4fa04a37c96d56d5f07d241395afe22e1627dd 100644 (file)
@@ -153,7 +153,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 13:    b       machine_check_fwnmi
 
-
 /*
  * We come in here when wakened from nap mode on a secondary hw thread.
  * Relocation is off and most register values are lost.
@@ -224,6 +223,11 @@ kvm_start_guest:
        /* Clear our vcpu pointer so we don't come back in early */
        li      r0, 0
        std     r0, HSTATE_KVM_VCPU(r13)
+       /*
+        * Make sure we clear HSTATE_KVM_VCPU(r13) before incrementing
+        * the nap_count, because once the increment to nap_count is
+        * visible we could be given another vcpu.
+        */
        lwsync
        /* Clear any pending IPI - we're an offline thread */
        ld      r5, HSTATE_XICS_PHYS(r13)
@@ -241,7 +245,6 @@ kvm_start_guest:
        /* increment the nap count and then go to nap mode */
        ld      r4, HSTATE_KVM_VCORE(r13)
        addi    r4, r4, VCORE_NAP_COUNT
-       lwsync                          /* make previous updates visible */
 51:    lwarx   r3, 0, r4
        addi    r3, r3, 1
        stwcx.  r3, 0, r4
@@ -751,15 +754,14 @@ kvmppc_interrupt_hv:
         * guest CR, R12 saved in shadow VCPU SCRATCH1/0
         * guest R13 saved in SPRN_SCRATCH0
         */
-       /* abuse host_r2 as third scratch area; we get r2 from PACATOC(r13) */
-       std     r9, HSTATE_HOST_R2(r13)
+       std     r9, HSTATE_SCRATCH2(r13)
 
        lbz     r9, HSTATE_IN_GUEST(r13)
        cmpwi   r9, KVM_GUEST_MODE_HOST_HV
        beq     kvmppc_bad_host_intr
 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
        cmpwi   r9, KVM_GUEST_MODE_GUEST
-       ld      r9, HSTATE_HOST_R2(r13)
+       ld      r9, HSTATE_SCRATCH2(r13)
        beq     kvmppc_interrupt_pr
 #endif
        /* We're now back in the host but in guest MMU context */
@@ -779,7 +781,7 @@ kvmppc_interrupt_hv:
        std     r6, VCPU_GPR(R6)(r9)
        std     r7, VCPU_GPR(R7)(r9)
        std     r8, VCPU_GPR(R8)(r9)
-       ld      r0, HSTATE_HOST_R2(r13)
+       ld      r0, HSTATE_SCRATCH2(r13)
        std     r0, VCPU_GPR(R9)(r9)
        std     r10, VCPU_GPR(R10)(r9)
        std     r11, VCPU_GPR(R11)(r9)
@@ -990,14 +992,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
         */
        /* Increment the threads-exiting-guest count in the 0xff00
           bits of vcore->entry_exit_count */
-       lwsync
        ld      r5,HSTATE_KVM_VCORE(r13)
        addi    r6,r5,VCORE_ENTRY_EXIT
 41:    lwarx   r3,0,r6
        addi    r0,r3,0x100
        stwcx.  r0,0,r6
        bne     41b
-       lwsync
+       isync           /* order stwcx. vs. reading napping_threads */
 
        /*
         * At this point we have an interrupt that we have to pass
@@ -1030,6 +1031,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        sld     r0,r0,r4
        andc.   r3,r3,r0                /* no sense IPI'ing ourselves */
        beq     43f
+       /* Order entry/exit update vs. IPIs */
+       sync
        mulli   r4,r4,PACA_SIZE         /* get paca for thread 0 */
        subf    r6,r4,r13
 42:    andi.   r0,r3,1
@@ -1638,10 +1641,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
        bge     kvm_cede_exit
        stwcx.  r4,0,r6
        bne     31b
+       /* order napping_threads update vs testing entry_exit_count */
+       isync
        li      r0,1
        stb     r0,HSTATE_NAPPING(r13)
-       /* order napping_threads update vs testing entry_exit_count */
-       lwsync
        mr      r4,r3
        lwz     r7,VCORE_ENTRY_EXIT(r5)
        cmpwi   r7,0x100
index f4dd041c14eac9400fb012beae92792fe9c9cfd1..f779450cb07c728681ede6d566ef85920117337e 100644 (file)
@@ -129,29 +129,32 @@ kvm_start_lightweight:
         * R12      = exit handler id
         * R13      = PACA
         * SVCPU.*  = guest *
+        * MSR.EE   = 1
         *
         */
 
+       PPC_LL  r3, GPR4(r1)            /* vcpu pointer */
+
+       /*
+        * kvmppc_copy_from_svcpu can clobber volatile registers, save
+        * the exit handler id to the vcpu and restore it from there later.
+        */
+       stw     r12, VCPU_TRAP(r3)
+
        /* Transfer reg values from shadow vcpu back to vcpu struct */
        /* On 64-bit, interrupts are still off at this point */
-       PPC_LL  r3, GPR4(r1)            /* vcpu pointer */
+
        GET_SHADOW_VCPU(r4)
        bl      FUNC(kvmppc_copy_from_svcpu)
        nop
 
 #ifdef CONFIG_PPC_BOOK3S_64
-       /* Re-enable interrupts */
-       ld      r3, HSTATE_HOST_MSR(r13)
-       ori     r3, r3, MSR_EE
-       MTMSR_EERI(r3)
-
        /*
         * Reload kernel SPRG3 value.
         * No need to save guest value as usermode can't modify SPRG3.
         */
        ld      r3, PACA_SPRG3(r13)
        mtspr   SPRN_SPRG3, r3
-
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
        /* R7 = vcpu */
@@ -177,7 +180,7 @@ kvm_start_lightweight:
        PPC_STL r31, VCPU_GPR(R31)(r7)
 
        /* Pass the exit number as 3rd argument to kvmppc_handle_exit */
-       mr      r5, r12
+       lwz     r5, VCPU_TRAP(r7)
 
        /* Restore r3 (kvm_run) and r4 (vcpu) */
        REST_2GPRS(3, r1)
index fe14ca3dd171cd60b3c07191fa3bdd78a141e2a6..5b9e9063cfaf0c407be267a67ab26d35fcc84a93 100644 (file)
@@ -66,6 +66,7 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
        memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb));
        svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
+       svcpu->in_use = 0;
        svcpu_put(svcpu);
 #endif
        vcpu->cpu = smp_processor_id();
@@ -78,6 +79,9 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       if (svcpu->in_use) {
+               kvmppc_copy_from_svcpu(vcpu, svcpu);
+       }
        memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
        to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
        svcpu_put(svcpu);
@@ -110,12 +114,26 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
        svcpu->ctr = vcpu->arch.ctr;
        svcpu->lr  = vcpu->arch.lr;
        svcpu->pc  = vcpu->arch.pc;
+       svcpu->in_use = true;
 }
 
 /* Copy data touched by real-mode code from shadow vcpu back to vcpu */
 void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
                            struct kvmppc_book3s_shadow_vcpu *svcpu)
 {
+       /*
+        * vcpu_put would just call us again because in_use hasn't
+        * been updated yet.
+        */
+       preempt_disable();
+
+       /*
+        * Maybe we were already preempted and synced the svcpu from
+        * our preempt notifiers. Don't bother touching this svcpu then.
+        */
+       if (!svcpu->in_use)
+               goto out;
+
        vcpu->arch.gpr[0] = svcpu->gpr[0];
        vcpu->arch.gpr[1] = svcpu->gpr[1];
        vcpu->arch.gpr[2] = svcpu->gpr[2];
@@ -139,6 +157,10 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
        vcpu->arch.fault_dar   = svcpu->fault_dar;
        vcpu->arch.fault_dsisr = svcpu->fault_dsisr;
        vcpu->arch.last_inst   = svcpu->last_inst;
+       svcpu->in_use = false;
+
+out:
+       preempt_enable();
 }
 
 static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu)
index a38c4c9edab87aca16929b5e96377368b5016fbd..c3c5231adade6f3871709a318fed1abc752040fe 100644 (file)
@@ -153,15 +153,11 @@ _GLOBAL(kvmppc_entry_trampoline)
 
        li      r6, MSR_IR | MSR_DR
        andc    r6, r5, r6      /* Clear DR and IR in MSR value */
-#ifdef CONFIG_PPC_BOOK3S_32
        /*
         * Set EE in HOST_MSR so that it's enabled when we get into our
-        * C exit handler function.  On 64-bit we delay enabling
-        * interrupts until we have finished transferring stuff
-        * to or from the PACA.
+        * C exit handler function.
         */
        ori     r5, r5, MSR_EE
-#endif
        mtsrr0  r7
        mtsrr1  r6
        RFI
index 53e65a210b9a451ab1089bfe788277ddda071cf3..0591e05db74b1a1a1f906af6a2a67cf9770320fa 100644 (file)
@@ -681,7 +681,7 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
        int ret, s;
-       struct thread_struct thread;
+       struct debug_reg debug;
 #ifdef CONFIG_PPC_FPU
        struct thread_fp_state fp;
        int fpexc_mode;
@@ -723,9 +723,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 
        /* Switch to guest debug context */
-       thread.debug = vcpu->arch.shadow_dbg_reg;
-       switch_booke_debug_regs(&thread);
-       thread.debug = current->thread.debug;
+       debug = vcpu->arch.shadow_dbg_reg;
+       switch_booke_debug_regs(&debug);
+       debug = current->thread.debug;
        current->thread.debug = vcpu->arch.shadow_dbg_reg;
 
        kvmppc_fix_ee_before_entry();
@@ -736,8 +736,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
           We also get here with interrupts enabled. */
 
        /* Switch back to user space debug context */
-       switch_booke_debug_regs(&thread);
-       current->thread.debug = thread.debug;
+       switch_booke_debug_regs(&debug);
+       current->thread.debug = debug;
 
 #ifdef CONFIG_PPC_FPU
        kvmppc_save_guest_fp(vcpu);
index d73a5901490018486fed19115fce46d88084f701..596a285c07554d65dfd561367a52ffed47aba55d 100644 (file)
@@ -9,6 +9,14 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 
+#ifdef __BIG_ENDIAN__
+#define sLd sld                /* Shift towards low-numbered address. */
+#define sHd srd                /* Shift towards high-numbered address. */
+#else
+#define sLd srd                /* Shift towards low-numbered address. */
+#define sHd sld                /* Shift towards high-numbered address. */
+#endif
+
        .align  7
 _GLOBAL(__copy_tofrom_user)
 BEGIN_FTR_SECTION
@@ -118,10 +126,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 24:    ld      r9,0(r4)        /* 3+2n loads, 2+2n stores */
 25:    ld      r0,8(r4)
-       sld     r6,r9,r10
+       sLd     r6,r9,r10
 26:    ldu     r9,16(r4)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        or      r7,r7,r6
        blt     cr6,79f
 27:    ld      r0,8(r4)
@@ -129,35 +137,35 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 28:    ld      r0,0(r4)        /* 4+2n loads, 3+2n stores */
 29:    ldu     r9,8(r4)
-       sld     r8,r0,r10
+       sLd     r8,r0,r10
        addi    r3,r3,-8
        blt     cr6,5f
 30:    ld      r0,8(r4)
-       srd     r12,r9,r11
-       sld     r6,r9,r10
+       sHd     r12,r9,r11
+       sLd     r6,r9,r10
 31:    ldu     r9,16(r4)
        or      r12,r8,r12
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        addi    r3,r3,16
        beq     cr6,78f
 
 1:     or      r7,r7,r6
 32:    ld      r0,8(r4)
 76:    std     r12,8(r3)
-2:     srd     r12,r9,r11
-       sld     r6,r9,r10
+2:     sHd     r12,r9,r11
+       sLd     r6,r9,r10
 33:    ldu     r9,16(r4)
        or      r12,r8,r12
 77:    stdu    r7,16(r3)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        bdnz    1b
 
 78:    std     r12,8(r3)
        or      r7,r7,r6
 79:    std     r7,16(r3)
-5:     srd     r12,r9,r11
+5:     sHd     r12,r9,r11
        or      r12,r8,r12
 80:    std     r12,24(r3)
        bne     6f
@@ -165,23 +173,38 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        blr
 6:     cmpwi   cr1,r5,8
        addi    r3,r3,32
-       sld     r9,r9,r10
+       sLd     r9,r9,r10
        ble     cr1,7f
 34:    ld      r0,8(r4)
-       srd     r7,r0,r11
+       sHd     r7,r0,r11
        or      r9,r7,r9
 7:
        bf      cr7*4+1,1f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,32
+#endif
 94:    stw     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,32
+#endif
        addi    r3,r3,4
 1:     bf      cr7*4+2,2f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,16
+#endif
 95:    sth     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,16
+#endif
        addi    r3,r3,2
 2:     bf      cr7*4+3,3f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,8
+#endif
 96:    stb     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,8
+#endif
 3:     li      r3,0
        blr
 
index 02245cee78183852d52f3a907023dcd9a63529bf..d7ddcee7feb8bc8084d18be32f348263c8de6e0e 100644 (file)
@@ -36,7 +36,6 @@
 #include "powernv.h"
 #include "pci.h"
 
-static char *hub_diag = NULL;
 static int ioda_eeh_nb_init = 0;
 
 static int ioda_eeh_event(struct notifier_block *nb,
@@ -140,15 +139,6 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
                ioda_eeh_nb_init = 1;
        }
 
-       /* We needn't HUB diag-data on PHB3 */
-       if (phb->type == PNV_PHB_IODA1 && !hub_diag) {
-               hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-               if (!hub_diag) {
-                       pr_err("%s: Out of memory !\n", __func__);
-                       return -ENOMEM;
-               }
-       }
-
 #ifdef CONFIG_DEBUG_FS
        if (phb->dbgfs) {
                debugfs_create_file("err_injct_outbound", 0600,
@@ -633,11 +623,10 @@ static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data)
 static void ioda_eeh_hub_diag(struct pci_controller *hose)
 {
        struct pnv_phb *phb = hose->private_data;
-       struct OpalIoP7IOCErrorData *data;
+       struct OpalIoP7IOCErrorData *data = &phb->diag.hub_diag;
        long rc;
 
-       data = (struct OpalIoP7IOCErrorData *)ioda_eeh_hub_diag;
-       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, PAGE_SIZE);
+       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data));
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n",
                           __func__, phb->hub_id, rc);
@@ -820,14 +809,15 @@ static void ioda_eeh_phb_diag(struct pci_controller *hose)
        struct OpalIoPhbErrorCommon *common;
        long rc;
 
-       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
-       rc = opal_pci_get_phb_diag_data2(phb->opal_id, common, PAGE_SIZE);
+       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+                                        PNV_PCI_DIAG_BUF_SIZE);
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
                            __func__, hose->global_number, rc);
                return;
        }
 
+       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
        switch (common->ioType) {
        case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
                ioda_eeh_p7ioc_phb_diag(hose, common);
index 911c24ef033e0ae207036e5d5cab8bceaf07e14a..1ed8d5f40f5ad1423f78c9ae7fdac42abac4376d 100644 (file)
@@ -172,11 +172,13 @@ struct pnv_phb {
                } ioda;
        };
 
-       /* PHB status structure */
+       /* PHB and hub status structure */
        union {
                unsigned char                   blob[PNV_PCI_DIAG_BUF_SIZE];
                struct OpalIoP7IOCPhbErrorData  p7ioc;
+               struct OpalIoP7IOCErrorData     hub_diag;
        } diag;
+
 };
 
 extern struct pci_ops pnv_pci_ops;
index 099e7ba405995b641cd0c89bfbb6b4e1d99c26e4..1d35e33ccf8688364a5be12c4b6aac734c50e942 100644 (file)
@@ -2,8 +2,8 @@
 header-y +=
 
 generic-y += clkdev.h
+generic-y += hash.h
 generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += preempt.h
-generic-y += hash.h
 
index 7b95f29e31749ec180e67028424580fadda1c3af..3baff31e58cf22c30b2d770162ee3c4b10c087ea 100644 (file)
@@ -6,7 +6,7 @@ lib-y  = delay.o memmove.o memchr.o \
         checksum.o strlen.o div64.o div64-generic.o
 
 # Extracted from libgcc
-lib-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
+obj-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
         ashlsi3.o ashrsi3.o ashiftrt.o lshrsi3.o \
         udiv_qrnnd.o
 
index 8358dc144959aacc8b369830c21c130593b9a804..0f9e94537eee78d9d41fffe82e32fc0098811ed2 100644 (file)
@@ -619,7 +619,7 @@ static inline unsigned long pte_present(pte_t pte)
 }
 
 #define pte_accessible pte_accessible
-static inline unsigned long pte_accessible(pte_t a)
+static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
 {
        return pte_val(a) & _PAGE_VALID;
 }
@@ -847,7 +847,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
         * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
         *             and SUN4V pte layout, so this inline test is fine.
         */
-       if (likely(mm != &init_mm) && pte_accessible(orig))
+       if (likely(mm != &init_mm) && pte_accessible(mm, orig))
                tlb_batch_add(mm, addr, ptep, orig, fullmm);
 }
 
index 3d1999458709231affdc977df99530acf3a833ac..bbc8b12fa443d47ee9a8faa59b36767e7aec866c 100644 (file)
@@ -452,9 +452,16 @@ static inline int pte_present(pte_t a)
 }
 
 #define pte_accessible pte_accessible
-static inline int pte_accessible(pte_t a)
+static inline bool pte_accessible(struct mm_struct *mm, pte_t a)
 {
-       return pte_flags(a) & _PAGE_PRESENT;
+       if (pte_flags(a) & _PAGE_PRESENT)
+               return true;
+
+       if ((pte_flags(a) & (_PAGE_PROTNONE | _PAGE_NUMA)) &&
+                       mm_tlb_flush_pending(mm))
+               return true;
+
+       return false;
 }
 
 static inline int pte_hidden(pte_t pte)
index dc1ec0dff939ecff5e55bcccaeb5bea322ad982a..ea04b342c026f8c8871f70a0c383d80651e12524 100644 (file)
@@ -387,7 +387,8 @@ static void init_intel(struct cpuinfo_x86 *c)
                        set_cpu_cap(c, X86_FEATURE_PEBS);
        }
 
-       if (c->x86 == 6 && c->x86_model == 29 && cpu_has_clflush)
+       if (c->x86 == 6 && cpu_has_clflush &&
+           (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
                set_cpu_cap(c, X86_FEATURE_CLFLUSH_MONITOR);
 
 #ifdef CONFIG_X86_64
index dd74e46828c0fc243740b61a18c2dea654fafb5e..0596e8e0cc1992b1fc32a00277a4f879cd07a8f3 100644 (file)
@@ -83,6 +83,12 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
                pte_t pte = gup_get_pte(ptep);
                struct page *page;
 
+               /* Similar to the PMD case, NUMA hinting must take slow path */
+               if (pte_numa(pte)) {
+                       pte_unmap(ptep);
+                       return 0;
+               }
+
                if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) {
                        pte_unmap(ptep);
                        return 0;
@@ -167,6 +173,13 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                if (pmd_none(pmd) || pmd_trans_splitting(pmd))
                        return 0;
                if (unlikely(pmd_large(pmd))) {
+                       /*
+                        * NUMA hinting faults need to be handled in the GUP
+                        * slowpath for accounting purposes and so that they
+                        * can be serialised against THP migration.
+                        */
+                       if (pmd_numa(pmd))
+                               return 0;
                        if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))
                                return 0;
                } else {
index ba6cf8e9aa0a598a50d4b24eb2c8f2914bf5c5ef..b91ce75bd35db9e00edb4c4af0a0e3036fd66df8 100644 (file)
@@ -335,9 +335,22 @@ static struct kobj_type blk_mq_hw_ktype = {
 void blk_mq_unregister_disk(struct gendisk *disk)
 {
        struct request_queue *q = disk->queue;
+       struct blk_mq_hw_ctx *hctx;
+       struct blk_mq_ctx *ctx;
+       int i, j;
+
+       queue_for_each_hw_ctx(q, hctx, i) {
+               hctx_for_each_ctx(hctx, ctx, j) {
+                       kobject_del(&ctx->kobj);
+                       kobject_put(&ctx->kobj);
+               }
+               kobject_del(&hctx->kobj);
+               kobject_put(&hctx->kobj);
+       }
 
        kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
        kobject_del(&q->mq_kobj);
+       kobject_put(&q->mq_kobj);
 
        kobject_put(&disk_to_dev(disk)->kobj);
 }
index 5d9248526d780b06c51bee967cdd088c9c90e5e5..4770de5707b9b9eb0a4c27f14c7ec9ad13035257 100644 (file)
@@ -348,7 +348,6 @@ source "drivers/acpi/apei/Kconfig"
 config ACPI_EXTLOG
        tristate "Extended Error Log support"
        depends on X86_MCE && X86_LOCAL_APIC
-       select EFI
        select UEFI_CPER
        default n
        help
index 6745fe137b9ea541ae729429035eaeca8fc8fc07..e603905973721c415a912c04e2c7f3926fcd5634 100644 (file)
@@ -162,6 +162,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
        { "80860F14", (unsigned long)&byt_sdio_dev_desc },
        { "80860F41", (unsigned long)&byt_i2c_dev_desc },
        { "INT33B2", },
+       { "INT33FC", },
 
        { "INT3430", (unsigned long)&lpt_dev_desc },
        { "INT3431", (unsigned long)&lpt_dev_desc },
index 786294bb682c104f111525ca17df7ccfafab0d88..3650b21832279a91568266208059296fadfab94c 100644 (file)
@@ -2,7 +2,6 @@ config ACPI_APEI
        bool "ACPI Platform Error Interface (APEI)"
        select MISC_FILESYSTEMS
        select PSTORE
-       select EFI
        select UEFI_CPER
        depends on X86
        help
index 26311f23c824f91354b3e47fe6fa5e5e448275dc..cb1d557fc22c054fa36beb1f74bfae42ea49f2c2 100644 (file)
@@ -942,6 +942,7 @@ static int erst_clearer(enum pstore_type_id type, u64 id, int count,
 static struct pstore_info erst_info = {
        .owner          = THIS_MODULE,
        .name           = "erst",
+       .flags          = PSTORE_FLAGS_FRAGILE,
        .open           = erst_open_pstore,
        .close          = erst_close_pstore,
        .read           = erst_reader,
index 14f1e95063380a5e2a315428fc8a4d5e8bcc39d3..c0ed4f273cf22b50a486b08f08c811e563781b07 100644 (file)
@@ -1238,15 +1238,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
-       /* AHCI controllers often implement SFF compatible interface.
-        * Grab all PCI BARs just in case.
-        */
-       rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
-       if (rc == -EBUSY)
-               pcim_pin_device(pdev);
-       if (rc)
-               return rc;
-
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
            (pdev->device == 0x2652 || pdev->device == 0x2653)) {
                u8 map;
@@ -1263,6 +1254,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
+       /* AHCI controllers often implement SFF compatible interface.
+        * Grab all PCI BARs just in case.
+        */
+       rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
+       if (rc == -EBUSY)
+               pcim_pin_device(pdev);
+       if (rc)
+               return rc;
+
        hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
        if (!hpriv)
                return -ENOMEM;
index ae2d73fe321e2f2c62d8e5709a788905edfd5a89..3e23e9941dad0080d629581723243c6550d4d476 100644 (file)
@@ -113,7 +113,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
        /*
         * set PHY Paremeters, two steps to configure the GPR13,
         * one write for rest of parameters, mask of first write
-        * is 0x07fffffd, and the other one write for setting
+        * is 0x07ffffff, and the other one write for setting
         * the mpll_clk_en.
         */
        regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK
@@ -124,6 +124,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
                        | IMX6Q_GPR13_SATA_TX_ATTEN_MASK
                        | IMX6Q_GPR13_SATA_TX_BOOST_MASK
                        | IMX6Q_GPR13_SATA_TX_LVL_MASK
+                       | IMX6Q_GPR13_SATA_MPLL_CLK_EN
                        | IMX6Q_GPR13_SATA_TX_EDGE_RATE
                        , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB
                        | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M
index 75b93678bbcd7f4231e0c2028995795487db671c..1393a5890ed5356e5ef36965ea74e49e226c0a29 100644 (file)
@@ -2149,9 +2149,16 @@ static int ata_dev_config_ncq(struct ata_device *dev,
                                    "failed to get NCQ Send/Recv Log Emask 0x%x\n",
                                    err_mask);
                } else {
+                       u8 *cmds = dev->ncq_send_recv_cmds;
+
                        dev->flags |= ATA_DFLAG_NCQ_SEND_RECV;
-                       memcpy(dev->ncq_send_recv_cmds, ap->sector_buf,
-                               ATA_LOG_NCQ_SEND_RECV_SIZE);
+                       memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE);
+
+                       if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) {
+                               ata_dev_dbg(dev, "disabling queued TRIM support\n");
+                               cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &=
+                                       ~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM;
+                       }
                }
        }
 
@@ -4156,6 +4163,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "ST3320[68]13AS",     "SD1[5-9]",     ATA_HORKAGE_NONCQ |
                                                ATA_HORKAGE_FIRMWARE_WARN },
 
+       /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
+       { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
        { "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, },
@@ -4202,6 +4212,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "PIONEER DVD-RW  DVR-212D",   NULL,   ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
+       /* devices that don't properly handle queued TRIM commands */
+       { "Micron_M500*",               NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Crucial_CT???M500SSD1",      NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+
        /* End Marker */
        { }
 };
@@ -6519,6 +6533,7 @@ static int __init ata_parse_force_one(char **cur,
                { "norst",      .lflags         = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
                { "rstonce",    .lflags         = ATA_LFLAG_RST_ONCE },
                { "atapi_dmadir", .horkage_on   = ATA_HORKAGE_ATAPI_DMADIR },
+               { "disable",    .horkage_on     = ATA_HORKAGE_DISABLE },
        };
        char *start = *cur, *p = *cur;
        char *id, *val, *endp;
index ab58556d347c19120c9724389583c2ae67a2d81e..377eb889f555dd2029c46a01254a3a204744ac81 100644 (file)
@@ -3872,6 +3872,27 @@ void ata_scsi_hotplug(struct work_struct *work)
                return;
        }
 
+       /*
+        * XXX - UGLY HACK
+        *
+        * The block layer suspend/resume path is fundamentally broken due
+        * to freezable kthreads and workqueue and may deadlock if a block
+        * device gets removed while resume is in progress.  I don't know
+        * what the solution is short of removing freezable kthreads and
+        * workqueues altogether.
+        *
+        * The following is an ugly hack to avoid kicking off device
+        * removal while freezer is active.  This is a joke but does avoid
+        * this particular deadlock scenario.
+        *
+        * https://bugzilla.kernel.org/show_bug.cgi?id=62801
+        * http://marc.info/?l=linux-kernel&m=138695698516487
+        */
+#ifdef CONFIG_FREEZER
+       while (pm_freezing)
+               msleep(10);
+#endif
+
        DPRINTK("ENTER\n");
        mutex_lock(&ap->scsi_scan_mutex);
 
index 5aca5f4c545896c567c892716a64b6cb22452b43..9587e959ce1af0cefca7d814ad161aa1c709c9bb 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/atomic.h>
+#include <linux/etherdevice.h>
 #include "nicstar.h"
 #ifdef CONFIG_ATM_NICSTAR_USE_SUNI
 #include "suni.h"
@@ -781,8 +782,7 @@ static int ns_init_card(int i, struct pci_dev *pcidev)
        if (mac[i] == NULL || !mac_pton(mac[i], card->atmdev->esi)) {
                nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET,
                                   card->atmdev->esi, 6);
-               if (memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6) ==
-                   0) {
+               if (ether_addr_equal(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00")) {
                        nicstar_read_eprom(card->membase,
                                           NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT,
                                           card->atmdev->esi, 6);
index 0215f9ad755cebb2de648035d801f042b1a29383..09b632ad0fe20ec97f3452df80e0cc525e7bfdd3 100644 (file)
@@ -33,8 +33,6 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
 int bcma_bus_suspend(struct bcma_bus *bus);
 int bcma_bus_resume(struct bcma_bus *bus);
 #endif
-struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
-                                       u8 unit);
 
 /* scan.c */
 int bcma_bus_scan(struct bcma_bus *bus);
index 4d07cce9c5d97ad2d7d9733c90209bfcb5a094da..7e11ef4cb7dbed69bd52685cf03a177fe6a8a01a 100644 (file)
@@ -38,7 +38,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
        { "M25P32", 0x15, 0x10000, 64, },
        { "M25P64", 0x16, 0x10000, 128, },
        { "M25FL128", 0x17, 0x10000, 256, },
-       { 0 },
+       { NULL },
 };
 
 static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
@@ -56,7 +56,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
        { "SST25VF016", 0x41, 0x1000, 512, },
        { "SST25VF032", 0x4a, 0x1000, 1024, },
        { "SST25VF064", 0x4b, 0x1000, 2048, },
-       { 0 },
+       { NULL },
 };
 
 static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
@@ -67,7 +67,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
        { "AT45DB161", 0x2c, 512, 4096, },
        { "AT45DB321", 0x34, 512, 8192, },
        { "AT45DB642", 0x3c, 1024, 8192, },
-       { 0 },
+       { NULL },
 };
 
 static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
index e15430a82e90e766163c7f5f40e26559b3fabbe1..34ea4c588d36bd798ee83bc9db6273eba6baf034 100644 (file)
@@ -78,18 +78,6 @@ static u16 bcma_cc_core_id(struct bcma_bus *bus)
        return BCMA_CORE_CHIPCOMMON;
 }
 
-struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
-{
-       struct bcma_device *core;
-
-       list_for_each_entry(core, &bus->cores, list) {
-               if (core->id.id == coreid)
-                       return core;
-       }
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(bcma_find_core);
-
 struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
                                        u8 unit)
 {
@@ -101,6 +89,7 @@ struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
        }
        return NULL;
 }
+EXPORT_SYMBOL_GPL(bcma_find_core_unit);
 
 bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
                     int timeout)
@@ -176,6 +165,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
                        bcma_err(bus,
                                 "Could not register dev for core 0x%03X\n",
                                 core->id.id);
+                       put_device(&core->dev);
                        continue;
                }
                core->dev_registered = true;
index f370fc13aea5d7d8c2a2c78fb40722da0cc27407..a2e69d26266d9b7faef4244aef695180d4c6eaef 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/module.h>
+
 #include <linux/moduleparam.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -65,7 +66,7 @@ enum {
        NULL_Q_MQ               = 2,
 };
 
-static int submit_queues = 1;
+static int submit_queues;
 module_param(submit_queues, int, S_IRUGO);
 MODULE_PARM_DESC(submit_queues, "Number of submission queues");
 
@@ -101,9 +102,9 @@ static int hw_queue_depth = 64;
 module_param(hw_queue_depth, int, S_IRUGO);
 MODULE_PARM_DESC(hw_queue_depth, "Queue depth for each hardware queue. Default: 64");
 
-static bool use_per_node_hctx = true;
+static bool use_per_node_hctx = false;
 module_param(use_per_node_hctx, bool, S_IRUGO);
-MODULE_PARM_DESC(use_per_node_hctx, "Use per-node allocation for hardware context queues. Default: true");
+MODULE_PARM_DESC(use_per_node_hctx, "Use per-node allocation for hardware context queues. Default: false");
 
 static void put_tag(struct nullb_queue *nq, unsigned int tag)
 {
@@ -346,8 +347,37 @@ static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq)
 
 static struct blk_mq_hw_ctx *null_alloc_hctx(struct blk_mq_reg *reg, unsigned int hctx_index)
 {
-       return kzalloc_node(sizeof(struct blk_mq_hw_ctx), GFP_KERNEL,
-                               hctx_index);
+       int b_size = DIV_ROUND_UP(reg->nr_hw_queues, nr_online_nodes);
+       int tip = (reg->nr_hw_queues % nr_online_nodes);
+       int node = 0, i, n;
+
+       /*
+        * Split submit queues evenly wrt to the number of nodes. If uneven,
+        * fill the first buckets with one extra, until the rest is filled with
+        * no extra.
+        */
+       for (i = 0, n = 1; i < hctx_index; i++, n++) {
+               if (n % b_size == 0) {
+                       n = 0;
+                       node++;
+
+                       tip--;
+                       if (!tip)
+                               b_size = reg->nr_hw_queues / nr_online_nodes;
+               }
+       }
+
+       /*
+        * A node might not be online, therefore map the relative node id to the
+        * real node id.
+        */
+       for_each_online_node(n) {
+               if (!node)
+                       break;
+               node--;
+       }
+
+       return kzalloc_node(sizeof(struct blk_mq_hw_ctx), GFP_KERNEL, n);
 }
 
 static void null_free_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_index)
@@ -355,16 +385,24 @@ static void null_free_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_index)
        kfree(hctx);
 }
 
+static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq)
+{
+       BUG_ON(!nullb);
+       BUG_ON(!nq);
+
+       init_waitqueue_head(&nq->wait);
+       nq->queue_depth = nullb->queue_depth;
+}
+
 static int null_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
                          unsigned int index)
 {
        struct nullb *nullb = data;
        struct nullb_queue *nq = &nullb->queues[index];
 
-       init_waitqueue_head(&nq->wait);
-       nq->queue_depth = nullb->queue_depth;
-       nullb->nr_queues++;
        hctx->driver_data = nq;
+       null_init_queue(nullb, nq);
+       nullb->nr_queues++;
 
        return 0;
 }
@@ -417,13 +455,13 @@ static int setup_commands(struct nullb_queue *nq)
 
        nq->cmds = kzalloc(nq->queue_depth * sizeof(*cmd), GFP_KERNEL);
        if (!nq->cmds)
-               return 1;
+               return -ENOMEM;
 
        tag_size = ALIGN(nq->queue_depth, BITS_PER_LONG) / BITS_PER_LONG;
        nq->tag_map = kzalloc(tag_size * sizeof(unsigned long), GFP_KERNEL);
        if (!nq->tag_map) {
                kfree(nq->cmds);
-               return 1;
+               return -ENOMEM;
        }
 
        for (i = 0; i < nq->queue_depth; i++) {
@@ -454,33 +492,37 @@ static void cleanup_queues(struct nullb *nullb)
 
 static int setup_queues(struct nullb *nullb)
 {
-       struct nullb_queue *nq;
-       int i;
-
-       nullb->queues = kzalloc(submit_queues * sizeof(*nq), GFP_KERNEL);
+       nullb->queues = kzalloc(submit_queues * sizeof(struct nullb_queue),
+                                                               GFP_KERNEL);
        if (!nullb->queues)
-               return 1;
+               return -ENOMEM;
 
        nullb->nr_queues = 0;
        nullb->queue_depth = hw_queue_depth;
 
-       if (queue_mode == NULL_Q_MQ)
-               return 0;
+       return 0;
+}
+
+static int init_driver_queues(struct nullb *nullb)
+{
+       struct nullb_queue *nq;
+       int i, ret = 0;
 
        for (i = 0; i < submit_queues; i++) {
                nq = &nullb->queues[i];
-               init_waitqueue_head(&nq->wait);
-               nq->queue_depth = hw_queue_depth;
-               if (setup_commands(nq))
-                       break;
+
+               null_init_queue(nullb, nq);
+
+               ret = setup_commands(nq);
+               if (ret)
+                       goto err_queue;
                nullb->nr_queues++;
        }
 
-       if (i == submit_queues)
-               return 0;
-
+       return 0;
+err_queue:
        cleanup_queues(nullb);
-       return 1;
+       return ret;
 }
 
 static int null_add_dev(void)
@@ -518,11 +560,13 @@ static int null_add_dev(void)
        } else if (queue_mode == NULL_Q_BIO) {
                nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node);
                blk_queue_make_request(nullb->q, null_queue_bio);
+               init_driver_queues(nullb);
        } else {
                nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node);
                blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
                if (nullb->q)
                        blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
+               init_driver_queues(nullb);
        }
 
        if (!nullb->q)
@@ -579,7 +623,13 @@ static int __init null_init(void)
        }
 #endif
 
-       if (submit_queues > nr_cpu_ids)
+       if (queue_mode == NULL_Q_MQ && use_per_node_hctx) {
+               if (submit_queues < nr_online_nodes) {
+                       pr_warn("null_blk: submit_queues param is set to %u.",
+                                                       nr_online_nodes);
+                       submit_queues = nr_online_nodes;
+               }
+       } else if (submit_queues > nr_cpu_ids)
                submit_queues = nr_cpu_ids;
        else if (!submit_queues)
                submit_queues = 1;
index 9199c93be926ed97f33eaa95fc9ce4ec0549cea7..eb6e1e0e8db25f78f2d2407e0d54dafc2a2b9583 100644 (file)
@@ -5269,7 +5269,7 @@ const char *skd_skdev_state_to_str(enum skd_drvr_state state)
        }
 }
 
-const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
+static const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
 {
        switch (state) {
        case SKD_MSG_STATE_IDLE:
@@ -5281,7 +5281,7 @@ const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
        }
 }
 
-const char *skd_skreq_state_to_str(enum skd_req_state state)
+static const char *skd_skreq_state_to_str(enum skd_req_state state)
 {
        switch (state) {
        case SKD_REQ_STATE_IDLE:
index d3fdc32b579d72afcee794d9ba68c68b1f4c367d..106d1d8e16ad4f87ac510f5d02b53dc36e8f23ef 100644 (file)
@@ -88,6 +88,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0CF3, 0xE004) },
        { USB_DEVICE(0x0CF3, 0xE005) },
        { USB_DEVICE(0x0930, 0x0219) },
+       { USB_DEVICE(0x0930, 0x0220) },
        { USB_DEVICE(0x0489, 0xe057) },
        { USB_DEVICE(0x13d3, 0x3393) },
        { USB_DEVICE(0x0489, 0xe04e) },
@@ -132,6 +133,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
index b61440aaee658210143f435a872ed51e649485e6..83f6437dd91df4014e27084f53ac6b02be5ed68a 100644 (file)
@@ -73,6 +73,7 @@ struct btsdio_data {
 #define REG_CL_INTRD 0x13      /* Interrupt Clear */
 #define REG_EN_INTRD 0x14      /* Interrupt Enable */
 #define REG_MD_STAT  0x20      /* Bluetooth Mode Status */
+#define REG_MD_SET   0x20      /* Bluetooth Mode Set */
 
 static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)
 {
@@ -212,7 +213,7 @@ static int btsdio_open(struct hci_dev *hdev)
        }
 
        if (data->func->class == SDIO_CLASS_BT_B)
-               sdio_writeb(data->func, 0x00, REG_MD_STAT, NULL);
+               sdio_writeb(data->func, 0x00, REG_MD_SET, NULL);
 
        sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL);
 
@@ -333,6 +334,9 @@ static int btsdio_probe(struct sdio_func *func,
        hdev->flush    = btsdio_flush;
        hdev->send     = btsdio_send_frame;
 
+       if (func->vendor == 0x0104 && func->device == 0x00c5)
+               set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
+
        err = hci_register_dev(hdev);
        if (err < 0) {
                hci_free_dev(hdev);
index bfbcc5a772a61ecb1619d6bbb988eb22bb9f0fef..baeaaed299e4e339ee455833c94c9d7aa24421c4 100644 (file)
@@ -155,6 +155,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
@@ -964,6 +965,45 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev)
        return 0;
 }
 
+static int btusb_setup_csr(struct hci_dev *hdev)
+{
+       struct hci_rp_read_local_version *rp;
+       struct sk_buff *skb;
+       int ret;
+
+       BT_DBG("%s", hdev->name);
+
+       skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
+                            HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb)) {
+               BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb));
+               return -PTR_ERR(skb);
+       }
+
+       rp = (struct hci_rp_read_local_version *) skb->data;
+
+       if (!rp->status) {
+               if (le16_to_cpu(rp->manufacturer) != 10) {
+                       /* Clear the reset quirk since this is not an actual
+                        * early Bluetooth 1.1 device from CSR.
+                        */
+                       clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
+
+                       /* These fake CSR controllers have all a broken
+                        * stored link key handling and so just disable it.
+                        */
+                       set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY,
+                               &hdev->quirks);
+               }
+       }
+
+       ret = -bt_to_errno(rp->status);
+
+       kfree_skb(skb);
+
+       return ret;
+}
+
 struct intel_version {
        u8 status;
        u8 hw_platform;
@@ -1464,10 +1504,15 @@ static int btusb_probe(struct usb_interface *intf,
 
        if (id->driver_info & BTUSB_CSR) {
                struct usb_device *udev = data->udev;
+               u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);
 
                /* Old firmware would otherwise execute USB reset */
-               if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117)
+               if (bcdDevice < 0x117)
                        set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
+
+               /* Fake CSR devices with broken commands */
+               if (bcdDevice <= 0x100)
+                       hdev->setup = btusb_setup_csr;
        }
 
        if (id->driver_info & BTUSB_SNIFFER) {
index 7b167385a1c4e8bdf7d0974707f0b0b43ea21f43..1ef6990a5c7e7c0387b4d9b6aafcb7a5c6f5cdc2 100644 (file)
@@ -141,22 +141,28 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
 }
 
 static inline ssize_t vhci_get_user(struct vhci_data *data,
-                                   const char __user *buf, size_t count)
+                                   const struct iovec *iov,
+                                   unsigned long count)
 {
+       size_t len = iov_length(iov, count);
        struct sk_buff *skb;
        __u8 pkt_type, dev_type;
+       unsigned long i;
        int ret;
 
-       if (count < 2 || count > HCI_MAX_FRAME_SIZE)
+       if (len < 2 || len > HCI_MAX_FRAME_SIZE)
                return -EINVAL;
 
-       skb = bt_skb_alloc(count, GFP_KERNEL);
+       skb = bt_skb_alloc(len, GFP_KERNEL);
        if (!skb)
                return -ENOMEM;
 
-       if (copy_from_user(skb_put(skb, count), buf, count)) {
-               kfree_skb(skb);
-               return -EFAULT;
+       for (i = 0; i < count; i++) {
+               if (copy_from_user(skb_put(skb, iov[i].iov_len),
+                                  iov[i].iov_base, iov[i].iov_len)) {
+                       kfree_skb(skb);
+                       return -EFAULT;
+               }
        }
 
        pkt_type = *((__u8 *) skb->data);
@@ -205,7 +211,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
                return -EINVAL;
        }
 
-       return (ret < 0) ? ret : count;
+       return (ret < 0) ? ret : len;
 }
 
 static inline ssize_t vhci_put_user(struct vhci_data *data,
@@ -272,12 +278,13 @@ static ssize_t vhci_read(struct file *file,
        return ret;
 }
 
-static ssize_t vhci_write(struct file *file,
-                         const char __user *buf, size_t count, loff_t *pos)
+static ssize_t vhci_write(struct kiocb *iocb, const struct iovec *iov,
+                         unsigned long count, loff_t pos)
 {
+       struct file *file = iocb->ki_filp;
        struct vhci_data *data = file->private_data;
 
-       return vhci_get_user(data, buf, count);
+       return vhci_get_user(data, iov, count);
 }
 
 static unsigned int vhci_poll(struct file *file, poll_table *wait)
@@ -342,7 +349,7 @@ static int vhci_release(struct inode *inode, struct file *file)
 static const struct file_operations vhci_fops = {
        .owner          = THIS_MODULE,
        .read           = vhci_read,
-       .write          = vhci_write,
+       .aio_write      = vhci_write,
        .poll           = vhci_poll,
        .open           = vhci_open,
        .release        = vhci_release,
index 02d534da22dda0bb22277c4f80f7c1d27f24cd65..16d7b4ac94be21210779cd7c87d9440a78666162 100644 (file)
@@ -828,6 +828,12 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
        int ret = 0;
 
        memcpy(&new_policy, policy, sizeof(*policy));
+
+       /* Use the default policy if its valid. */
+       if (cpufreq_driver->setpolicy)
+               cpufreq_parse_governor(policy->governor->name,
+                                       &new_policy.policy, NULL);
+
        /* assure that the starting sequence is run in cpufreq_set_policy */
        policy->governor = NULL;
 
@@ -845,8 +851,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
 
 #ifdef CONFIG_HOTPLUG_CPU
 static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
-                                 unsigned int cpu, struct device *dev,
-                                 bool frozen)
+                                 unsigned int cpu, struct device *dev)
 {
        int ret = 0;
        unsigned long flags;
@@ -877,11 +882,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
                }
        }
 
-       /* Don't touch sysfs links during light-weight init */
-       if (!frozen)
-               ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
-
-       return ret;
+       return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
 }
 #endif
 
@@ -926,6 +927,27 @@ err_free_policy:
        return NULL;
 }
 
+static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
+{
+       struct kobject *kobj;
+       struct completion *cmp;
+
+       down_read(&policy->rwsem);
+       kobj = &policy->kobj;
+       cmp = &policy->kobj_unregister;
+       up_read(&policy->rwsem);
+       kobject_put(kobj);
+
+       /*
+        * We need to make sure that the underlying kobj is
+        * actually not referenced anymore by anybody before we
+        * proceed with unloading.
+        */
+       pr_debug("waiting for dropping of refcount\n");
+       wait_for_completion(cmp);
+       pr_debug("wait complete\n");
+}
+
 static void cpufreq_policy_free(struct cpufreq_policy *policy)
 {
        free_cpumask_var(policy->related_cpus);
@@ -986,7 +1008,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
        list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
                if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
                        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
-                       ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev, frozen);
+                       ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev);
                        up_read(&cpufreq_rwsem);
                        return ret;
                }
@@ -1096,7 +1118,10 @@ err_get_freq:
        if (cpufreq_driver->exit)
                cpufreq_driver->exit(policy);
 err_set_policy_cpu:
+       if (frozen)
+               cpufreq_policy_put_kobj(policy);
        cpufreq_policy_free(policy);
+
 nomem_out:
        up_read(&cpufreq_rwsem);
 
@@ -1118,7 +1143,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 }
 
 static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
-                                          unsigned int old_cpu, bool frozen)
+                                          unsigned int old_cpu)
 {
        struct device *cpu_dev;
        int ret;
@@ -1126,10 +1151,6 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
        /* first sibling now owns the new sysfs dir */
        cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
 
-       /* Don't touch sysfs files during light-weight tear-down */
-       if (frozen)
-               return cpu_dev->id;
-
        sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
        ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
        if (ret) {
@@ -1196,7 +1217,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
                if (!frozen)
                        sysfs_remove_link(&dev->kobj, "cpufreq");
        } else if (cpus > 1) {
-               new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
+               new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
                if (new_cpu >= 0) {
                        update_policy_cpu(policy, new_cpu);
 
@@ -1218,8 +1239,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
        int ret;
        unsigned long flags;
        struct cpufreq_policy *policy;
-       struct kobject *kobj;
-       struct completion *cmp;
 
        read_lock_irqsave(&cpufreq_driver_lock, flags);
        policy = per_cpu(cpufreq_cpu_data, cpu);
@@ -1249,22 +1268,8 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                        }
                }
 
-               if (!frozen) {
-                       down_read(&policy->rwsem);
-                       kobj = &policy->kobj;
-                       cmp = &policy->kobj_unregister;
-                       up_read(&policy->rwsem);
-                       kobject_put(kobj);
-
-                       /*
-                        * We need to make sure that the underlying kobj is
-                        * actually not referenced anymore by anybody before we
-                        * proceed with unloading.
-                        */
-                       pr_debug("waiting for dropping of refcount\n");
-                       wait_for_completion(cmp);
-                       pr_debug("wait complete\n");
-               }
+               if (!frozen)
+                       cpufreq_policy_put_kobj(policy);
 
                /*
                 * Perform the ->exit() even during light-weight tear-down,
index 446687cc2334ed2f60a0b6f0170382fe733aae01..c823daaf90430bb501ff9bc168e88adbcecf87ef 100644 (file)
@@ -62,6 +62,7 @@ config INTEL_IOATDMA
        tristate "Intel I/OAT DMA support"
        depends on PCI && X86
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select DCA
        help
          Enable support for the Intel(R) I/OAT DMA engine present
@@ -112,6 +113,7 @@ config MV_XOR
        bool "Marvell XOR engine support"
        depends on PLAT_ORION
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        ---help---
          Enable support for the Marvell XOR engine.
@@ -187,6 +189,7 @@ config AMCC_PPC440SPE_ADMA
        tristate "AMCC PPC440SPe ADMA support"
        depends on 440SPe || 440SP
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ARCH_HAS_ASYNC_TX_FIND_CHANNEL
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        help
@@ -352,6 +355,7 @@ config NET_DMA
        bool "Network: TCP receive copy offload"
        depends on DMA_ENGINE && NET
        default (INTEL_IOATDMA || FSL_DMA)
+       depends on BROKEN
        help
          This enables the use of DMA engines in the network stack to
          offload receive copy-to-user operations, freeing CPU cycles.
@@ -377,4 +381,7 @@ config DMATEST
          Simple DMA test client. Say N unless you're debugging a
          DMA Device driver.
 
+config DMA_ENGINE_RAID
+       bool
+
 endif
index f31d647acdfaac3730371e1366ff964e245435ac..2787aba60c6bdee8ed0489cb932338d6a81528ac 100644 (file)
@@ -347,10 +347,6 @@ static struct device *chan2dev(struct dma_chan *chan)
 {
        return &chan->dev->device;
 }
-static struct device *chan2parent(struct dma_chan *chan)
-{
-       return chan->dev->device.parent;
-}
 
 #if defined(VERBOSE_DEBUG)
 static void vdbg_dump_regs(struct at_dma_chan *atchan)
index ea806bdc12ef92418c528be0b950758de59c3ee7..ef63b9058f3c09d9d9dea56096bc5edda6d3b125 100644 (file)
@@ -912,7 +912,7 @@ struct dmaengine_unmap_pool {
 #define __UNMAP_POOL(x) { .size = x, .name = "dmaengine-unmap-" __stringify(x) }
 static struct dmaengine_unmap_pool unmap_pool[] = {
        __UNMAP_POOL(2),
-       #if IS_ENABLED(CONFIG_ASYNC_TX_DMA)
+       #if IS_ENABLED(CONFIG_DMA_ENGINE_RAID)
        __UNMAP_POOL(16),
        __UNMAP_POOL(128),
        __UNMAP_POOL(256),
@@ -1054,7 +1054,7 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
        dma_cookie_t cookie;
        unsigned long flags;
 
-       unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOIO);
+       unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOWAIT);
        if (!unmap)
                return -ENOMEM;
 
index 20f9a3aaf9266ea6daa71a18f08d258afa8a1a1e..9dfcaf5c12888d3de80483329ffccc7fbbacd02a 100644 (file)
@@ -539,9 +539,9 @@ static int dmatest_func(void *data)
 
                um->len = params->buf_size;
                for (i = 0; i < src_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->srcs[i];
+                       void *buf = thread->srcs[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
                                                   um->len, DMA_TO_DEVICE);
@@ -559,9 +559,9 @@ static int dmatest_func(void *data)
                /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
                dsts = &um->addr[src_cnt];
                for (i = 0; i < dst_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->dsts[i];
+                       void *buf = thread->dsts[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
                                               DMA_BIDIRECTIONAL);
index 7086a16a55f2ed488573e475e615600c80be767e..f157c6f76b32b8c98dce28eed6253db033acc258 100644 (file)
@@ -86,11 +86,6 @@ static void set_desc_cnt(struct fsldma_chan *chan,
        hw->count = CPU_TO_DMA(chan, count, 32);
 }
 
-static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
-{
-       return DMA_TO_CPU(chan, desc->hw.count, 32);
-}
-
 static void set_desc_src(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
@@ -101,16 +96,6 @@ static void set_desc_src(struct fsldma_chan *chan,
        hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
 }
 
-static dma_addr_t get_desc_src(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_dst(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
@@ -121,16 +106,6 @@ static void set_desc_dst(struct fsldma_chan *chan,
        hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
 }
 
-static dma_addr_t get_desc_dst(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_next(struct fsldma_chan *chan,
                          struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
@@ -408,7 +383,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
        struct fsl_desc_sw *child;
        unsigned long flags;
-       dma_cookie_t cookie;
+       dma_cookie_t cookie = -EINVAL;
 
        spin_lock_irqsave(&chan->desc_lock, flags);
 
@@ -854,10 +829,6 @@ static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
                                      struct fsl_desc_sw *desc)
 {
        struct dma_async_tx_descriptor *txd = &desc->async_tx;
-       struct device *dev = chan->common.device->dev;
-       dma_addr_t src = get_desc_src(chan, desc);
-       dma_addr_t dst = get_desc_dst(chan, desc);
-       u32 len = get_desc_cnt(chan, desc);
 
        /* Run the link descriptor callback function */
        if (txd->callback) {
index 7807f0ef4e209c25ad90db9d32f7bc13955391cf..53fb0c8365b0b27f29a893a3072103c9fb2360e9 100644 (file)
@@ -54,12 +54,6 @@ static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags)
        hw_desc->desc_command = (1 << 31);
 }
 
-static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc)
-{
-       struct mv_xor_desc *hw_desc = desc->hw_desc;
-       return hw_desc->phy_dest_addr;
-}
-
 static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc,
                                   u32 byte_count)
 {
@@ -787,7 +781,6 @@ static void mv_xor_issue_pending(struct dma_chan *chan)
 /*
  * Perform a transaction to verify the HW works.
  */
-#define MV_XOR_TEST_SIZE 2000
 
 static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
 {
@@ -797,20 +790,21 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        struct dma_chan *dma_chan;
        dma_cookie_t cookie;
        struct dma_async_tx_descriptor *tx;
+       struct dmaengine_unmap_data *unmap;
        int err = 0;
 
-       src = kmalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+       src = kmalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
        if (!src)
                return -ENOMEM;
 
-       dest = kzalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+       dest = kzalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
        if (!dest) {
                kfree(src);
                return -ENOMEM;
        }
 
        /* Fill in src buffer */
-       for (i = 0; i < MV_XOR_TEST_SIZE; i++)
+       for (i = 0; i < PAGE_SIZE; i++)
                ((u8 *) src)[i] = (u8)i;
 
        dma_chan = &mv_chan->dmachan;
@@ -819,14 +813,26 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
                goto out;
        }
 
-       dest_dma = dma_map_single(dma_chan->device->dev, dest,
-                                 MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+       unmap = dmaengine_get_unmap_data(dma_chan->device->dev, 2, GFP_KERNEL);
+       if (!unmap) {
+               err = -ENOMEM;
+               goto free_resources;
+       }
+
+       src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src), 0,
+                                PAGE_SIZE, DMA_TO_DEVICE);
+       unmap->to_cnt = 1;
+       unmap->addr[0] = src_dma;
 
-       src_dma = dma_map_single(dma_chan->device->dev, src,
-                                MV_XOR_TEST_SIZE, DMA_TO_DEVICE);
+       dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest), 0,
+                                 PAGE_SIZE, DMA_FROM_DEVICE);
+       unmap->from_cnt = 1;
+       unmap->addr[1] = dest_dma;
+
+       unmap->len = PAGE_SIZE;
 
        tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
-                                   MV_XOR_TEST_SIZE, 0);
+                                   PAGE_SIZE, 0);
        cookie = mv_xor_tx_submit(tx);
        mv_xor_issue_pending(dma_chan);
        async_tx_ack(tx);
@@ -841,8 +847,8 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
 
        dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
-                               MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
-       if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
+                               PAGE_SIZE, DMA_FROM_DEVICE);
+       if (memcmp(src, dest, PAGE_SIZE)) {
                dev_err(dma_chan->device->dev,
                        "Self-test copy failed compare, disabling\n");
                err = -ENODEV;
@@ -850,6 +856,7 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
 
 free_resources:
+       dmaengine_unmap_put(unmap);
        mv_xor_free_chan_resources(dma_chan);
 out:
        kfree(src);
@@ -867,13 +874,15 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST];
        dma_addr_t dest_dma;
        struct dma_async_tx_descriptor *tx;
+       struct dmaengine_unmap_data *unmap;
        struct dma_chan *dma_chan;
        dma_cookie_t cookie;
        u8 cmp_byte = 0;
        u32 cmp_word;
        int err = 0;
+       int src_count = MV_XOR_NUM_SRC_TEST;
 
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+       for (src_idx = 0; src_idx < src_count; src_idx++) {
                xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
                if (!xor_srcs[src_idx]) {
                        while (src_idx--)
@@ -890,13 +899,13 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        }
 
        /* Fill in src buffers */
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+       for (src_idx = 0; src_idx < src_count; src_idx++) {
                u8 *ptr = page_address(xor_srcs[src_idx]);
                for (i = 0; i < PAGE_SIZE; i++)
                        ptr[i] = (1 << src_idx);
        }
 
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++)
+       for (src_idx = 0; src_idx < src_count; src_idx++)
                cmp_byte ^= (u8) (1 << src_idx);
 
        cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
@@ -910,16 +919,29 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
                goto out;
        }
 
+       unmap = dmaengine_get_unmap_data(dma_chan->device->dev, src_count + 1,
+                                        GFP_KERNEL);
+       if (!unmap) {
+               err = -ENOMEM;
+               goto free_resources;
+       }
+
        /* test xor */
-       dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
-                               DMA_FROM_DEVICE);
+       for (i = 0; i < src_count; i++) {
+               unmap->addr[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+                                             0, PAGE_SIZE, DMA_TO_DEVICE);
+               dma_srcs[i] = unmap->addr[i];
+               unmap->to_cnt++;
+       }
 
-       for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++)
-               dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
-                                          0, PAGE_SIZE, DMA_TO_DEVICE);
+       unmap->addr[src_count] = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
+                                     DMA_FROM_DEVICE);
+       dest_dma = unmap->addr[src_count];
+       unmap->from_cnt = 1;
+       unmap->len = PAGE_SIZE;
 
        tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
-                                MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0);
+                                src_count, PAGE_SIZE, 0);
 
        cookie = mv_xor_tx_submit(tx);
        mv_xor_issue_pending(dma_chan);
@@ -948,9 +970,10 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        }
 
 free_resources:
+       dmaengine_unmap_put(unmap);
        mv_xor_free_chan_resources(dma_chan);
 out:
-       src_idx = MV_XOR_NUM_SRC_TEST;
+       src_idx = src_count;
        while (src_idx--)
                __free_page(xor_srcs[src_idx]);
        __free_page(dest);
@@ -1176,6 +1199,7 @@ static int mv_xor_probe(struct platform_device *pdev)
                int i = 0;
 
                for_each_child_of_node(pdev->dev.of_node, np) {
+                       struct mv_xor_chan *chan;
                        dma_cap_mask_t cap_mask;
                        int irq;
 
@@ -1193,21 +1217,21 @@ static int mv_xor_probe(struct platform_device *pdev)
                                goto err_channel_add;
                        }
 
-                       xordev->channels[i] =
-                               mv_xor_channel_add(xordev, pdev, i,
-                                                  cap_mask, irq);
-                       if (IS_ERR(xordev->channels[i])) {
-                               ret = PTR_ERR(xordev->channels[i]);
-                               xordev->channels[i] = NULL;
+                       chan = mv_xor_channel_add(xordev, pdev, i,
+                                                 cap_mask, irq);
+                       if (IS_ERR(chan)) {
+                               ret = PTR_ERR(chan);
                                irq_dispose_mapping(irq);
                                goto err_channel_add;
                        }
 
+                       xordev->channels[i] = chan;
                        i++;
                }
        } else if (pdata && pdata->channels) {
                for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
                        struct mv_xor_channel_data *cd;
+                       struct mv_xor_chan *chan;
                        int irq;
 
                        cd = &pdata->channels[i];
@@ -1222,13 +1246,14 @@ static int mv_xor_probe(struct platform_device *pdev)
                                goto err_channel_add;
                        }
 
-                       xordev->channels[i] =
-                               mv_xor_channel_add(xordev, pdev, i,
-                                                  cd->cap_mask, irq);
-                       if (IS_ERR(xordev->channels[i])) {
-                               ret = PTR_ERR(xordev->channels[i]);
+                       chan = mv_xor_channel_add(xordev, pdev, i,
+                                                 cd->cap_mask, irq);
+                       if (IS_ERR(chan)) {
+                               ret = PTR_ERR(chan);
                                goto err_channel_add;
                        }
+
+                       xordev->channels[i] = chan;
                }
        }
 
index cdf0483b8f2dfb8f746b786fd6bf84b0d5f6657b..536632f6479c6966029022614f2bf863974256b4 100644 (file)
@@ -2492,12 +2492,9 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
 
 static inline void _init_desc(struct dma_pl330_desc *desc)
 {
-       desc->pchan = NULL;
        desc->req.x = &desc->px;
        desc->req.token = desc;
        desc->rqcfg.swap = SWAP_NO;
-       desc->rqcfg.privileged = 0;
-       desc->rqcfg.insnaccess = 0;
        desc->rqcfg.scctl = SCCTRL0;
        desc->rqcfg.dcctl = DCCTRL0;
        desc->req.cfg = &desc->rqcfg;
@@ -2517,7 +2514,7 @@ static int add_desc(struct dma_pl330_dmac *pdmac, gfp_t flg, int count)
        if (!pdmac)
                return 0;
 
-       desc = kmalloc(count * sizeof(*desc), flg);
+       desc = kcalloc(count, sizeof(*desc), flg);
        if (!desc)
                return 0;
 
index 8da48c6b2a38ccd76f3e127d53e4be5ab7be425c..8bba298535b0984e241793403af6920399d7366d 100644 (file)
@@ -532,29 +532,6 @@ static void ppc440spe_desc_init_memcpy(struct ppc440spe_adma_desc_slot *desc,
        hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
 }
 
-/**
- * ppc440spe_desc_init_memset - initialize the descriptor for MEMSET operation
- */
-static void ppc440spe_desc_init_memset(struct ppc440spe_adma_desc_slot *desc,
-                                       int value, unsigned long flags)
-{
-       struct dma_cdb *hw_desc = desc->hw_desc;
-
-       memset(desc->hw_desc, 0, sizeof(struct dma_cdb));
-       desc->hw_next = NULL;
-       desc->src_cnt = 1;
-       desc->dst_cnt = 1;
-
-       if (flags & DMA_PREP_INTERRUPT)
-               set_bit(PPC440SPE_DESC_INT, &desc->flags);
-       else
-               clear_bit(PPC440SPE_DESC_INT, &desc->flags);
-
-       hw_desc->sg1u = hw_desc->sg1l = cpu_to_le32((u32)value);
-       hw_desc->sg3u = hw_desc->sg3l = cpu_to_le32((u32)value);
-       hw_desc->opc = DMA_CDB_OPC_DFILL128;
-}
-
 /**
  * ppc440spe_desc_set_src_addr - set source address into the descriptor
  */
@@ -1504,8 +1481,6 @@ static dma_cookie_t ppc440spe_adma_run_tx_complete_actions(
                struct ppc440spe_adma_chan *chan,
                dma_cookie_t cookie)
 {
-       int i;
-
        BUG_ON(desc->async_tx.cookie < 0);
        if (desc->async_tx.cookie > 0) {
                cookie = desc->async_tx.cookie;
@@ -3898,7 +3873,7 @@ static void ppc440spe_adma_init_capabilities(struct ppc440spe_adma_device *adev)
                        ppc440spe_adma_prep_dma_interrupt;
        }
        pr_info("%s: AMCC(R) PPC440SP(E) ADMA Engine: "
-         "( %s%s%s%s%s%s%s)\n",
+         "( %s%s%s%s%s%s)\n",
          dev_name(adev->dev),
          dma_has_cap(DMA_PQ, adev->common.cap_mask) ? "pq " : "",
          dma_has_cap(DMA_PQ_VAL, adev->common.cap_mask) ? "pq_val " : "",
index bae6c29f5502ab951f7926bdf621977703bc96b1..17686caf64d5c4beedd0d189dd4487a57acb1254 100644 (file)
@@ -406,7 +406,6 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
        dma_async_tx_callback callback;
        void *param;
        struct dma_async_tx_descriptor *txd = &desc->txd;
-       struct txx9dmac_slave *ds = dc->chan.private;
 
        dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
                 txd->cookie, desc);
index b0bb056458a363b0ee457beea13a8b926a63d483..281029daf98c7ea291886d46ecf05378bfa98718 100644 (file)
@@ -1623,7 +1623,6 @@ static struct scsi_host_template scsi_driver_template = {
        .cmd_per_lun            = 1,
        .can_queue              = 1,
        .sdev_attrs             = sbp2_scsi_sysfs_attrs,
-       .no_write_same          = 1,
 };
 
 MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
index 299fad6b5867287f0869648e4a99eaa9b581d872..5373dc5b60114f31af5cf66cdbb923bdc6b0f973 100644 (file)
@@ -14,3 +14,4 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
 
 obj-$(CONFIG_GOOGLE_FIRMWARE)  += google/
 obj-$(CONFIG_EFI)              += efi/
+obj-$(CONFIG_UEFI_CPER)                += efi/
index 3150aa4874e8f67e4360635934acdcb11bac6fef..6aecbc86ec9482f322e55735de02c9daa1e4775a 100644 (file)
@@ -36,7 +36,7 @@ config EFI_VARS_PSTORE_DEFAULT_DISABLE
          backend for pstore by default. This setting can be overridden
          using the efivars module's pstore_disable parameter.
 
-config UEFI_CPER
-       def_bool n
-
 endmenu
+
+config UEFI_CPER
+       bool
index 9ba156d3c7755e6854595b9983fc23db20fa2111..6c2a41ec21baf63989e9d676b569a21132c006c8 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Makefile for linux kernel
 #
-obj-y                                  += efi.o vars.o
+obj-$(CONFIG_EFI)                      += efi.o vars.o
 obj-$(CONFIG_EFI_VARS)                 += efivars.o
 obj-$(CONFIG_EFI_VARS_PSTORE)          += efi-pstore.o
 obj-$(CONFIG_UEFI_CPER)                        += cper.o
index 743fd426f21bf29299b850833d0137348a2bca64..4b9dc836dcf956e86c3800398946d40b0d1cf6dc 100644 (file)
@@ -356,6 +356,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 static struct pstore_info efi_pstore_info = {
        .owner          = THIS_MODULE,
        .name           = "efi",
+       .flags          = PSTORE_FLAGS_FRAGILE,
        .open           = efi_pstore_open,
        .close          = efi_pstore_close,
        .read           = efi_pstore_read,
index 621c7c67a6439b2e785fc4b0f9898784aad47b01..76d3d1ab73c6965063eba62527594dce82dc41d4 100644 (file)
@@ -2343,15 +2343,24 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request)
        kfree(request);
 }
 
-static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
-                                     struct intel_ring_buffer *ring)
+static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
+                                      struct intel_ring_buffer *ring)
 {
-       u32 completed_seqno;
-       u32 acthd;
+       u32 completed_seqno = ring->get_seqno(ring, false);
+       u32 acthd = intel_ring_get_active_head(ring);
+       struct drm_i915_gem_request *request;
+
+       list_for_each_entry(request, &ring->request_list, list) {
+               if (i915_seqno_passed(completed_seqno, request->seqno))
+                       continue;
 
-       acthd = intel_ring_get_active_head(ring);
-       completed_seqno = ring->get_seqno(ring, false);
+               i915_set_reset_status(ring, request, acthd);
+       }
+}
 
+static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
+                                       struct intel_ring_buffer *ring)
+{
        while (!list_empty(&ring->request_list)) {
                struct drm_i915_gem_request *request;
 
@@ -2359,9 +2368,6 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
                                           struct drm_i915_gem_request,
                                           list);
 
-               if (request->seqno > completed_seqno)
-                       i915_set_reset_status(ring, request, acthd);
-
                i915_gem_free_request(request);
        }
 
@@ -2403,8 +2409,16 @@ void i915_gem_reset(struct drm_device *dev)
        struct intel_ring_buffer *ring;
        int i;
 
+       /*
+        * Before we free the objects from the requests, we need to inspect
+        * them for finding the guilty party. As the requests only borrow
+        * their reference to the objects, the inspection must be done first.
+        */
+       for_each_ring(ring, dev_priv, i)
+               i915_gem_reset_ring_status(dev_priv, ring);
+
        for_each_ring(ring, dev_priv, i)
-               i915_gem_reset_ring_lists(dev_priv, ring);
+               i915_gem_reset_ring_cleanup(dev_priv, ring);
 
        i915_gem_cleanup_ringbuffer(dev);
 
index b7e787fb4649321cd67d7456aef11af861757aac..a3ba9a8cd68794bbfd163c9236c91c7be9d15965 100644 (file)
@@ -93,7 +93,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
 {
        struct drm_i915_gem_object *obj;
        struct list_head objects;
-       int i, ret = 0;
+       int i, ret;
 
        INIT_LIST_HEAD(&objects);
        spin_lock(&file->table_lock);
@@ -106,7 +106,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Invalid object handle %d at index %d\n",
                                   exec[i].handle, i);
                        ret = -ENOENT;
-                       goto out;
+                       goto err;
                }
 
                if (!list_empty(&obj->obj_exec_link)) {
@@ -114,7 +114,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n",
                                   obj, exec[i].handle, i);
                        ret = -EINVAL;
-                       goto out;
+                       goto err;
                }
 
                drm_gem_object_reference(&obj->base);
@@ -123,9 +123,13 @@ eb_lookup_vmas(struct eb_vmas *eb,
        spin_unlock(&file->table_lock);
 
        i = 0;
-       list_for_each_entry(obj, &objects, obj_exec_link) {
+       while (!list_empty(&objects)) {
                struct i915_vma *vma;
 
+               obj = list_first_entry(&objects,
+                                      struct drm_i915_gem_object,
+                                      obj_exec_link);
+
                /*
                 * NOTE: We can leak any vmas created here when something fails
                 * later on. But that's no issue since vma_unbind can deal with
@@ -138,10 +142,12 @@ eb_lookup_vmas(struct eb_vmas *eb,
                if (IS_ERR(vma)) {
                        DRM_DEBUG("Failed to lookup VMA\n");
                        ret = PTR_ERR(vma);
-                       goto out;
+                       goto err;
                }
 
+               /* Transfer ownership from the objects list to the vmas list. */
                list_add_tail(&vma->exec_list, &eb->vmas);
+               list_del_init(&obj->obj_exec_link);
 
                vma->exec_entry = &exec[i];
                if (eb->and < 0) {
@@ -155,16 +161,22 @@ eb_lookup_vmas(struct eb_vmas *eb,
                ++i;
        }
 
+       return 0;
+
 
-out:
+err:
        while (!list_empty(&objects)) {
                obj = list_first_entry(&objects,
                                       struct drm_i915_gem_object,
                                       obj_exec_link);
                list_del_init(&obj->obj_exec_link);
-               if (ret)
-                       drm_gem_object_unreference(&obj->base);
+               drm_gem_object_unreference(&obj->base);
        }
+       /*
+        * Objects already transfered to the vmas list will be unreferenced by
+        * eb_destroy.
+        */
+
        return ret;
 }
 
index 8b8bde7dce53abce2fea3c655e06ef765433d50f..54e82a80cf507fe90366ad1e0fb33f082073ca83 100644 (file)
@@ -6303,7 +6303,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
        uint32_t val;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
-               WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
+               WARN(crtc->active, "CRTC for pipe %c enabled\n",
                     pipe_name(crtc->pipe));
 
        WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
@@ -11126,14 +11126,15 @@ void intel_connector_attach_encoder(struct intel_connector *connector,
 int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
        u16 gmch_ctrl;
 
-       pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
+       pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl);
        if (state)
                gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
        else
                gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
-       pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
+       pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl);
        return 0;
 }
 
index 3657ab43c8fd1e20fc9deb10856166b4c35ec0d4..26c29c173221058aeeaa9a3c0d889500b8db9fec 100644 (file)
@@ -5688,6 +5688,8 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
        unsigned long irqflags;
        uint32_t tmp;
 
+       WARN_ON(dev_priv->pc8.enabled);
+
        tmp = I915_READ(HSW_PWR_WELL_DRIVER);
        is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
        enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
@@ -5747,16 +5749,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 static void __intel_power_well_get(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
-       if (!power_well->count++)
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!power_well->count++) {
+               hsw_disable_package_c8(dev_priv);
                __intel_set_power_well(dev, true);
+       }
 }
 
 static void __intel_power_well_put(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        WARN_ON(!power_well->count);
-       if (!--power_well->count && i915_disable_power_well)
+       if (!--power_well->count && i915_disable_power_well) {
                __intel_set_power_well(dev, false);
+               hsw_enable_package_c8(dev_priv);
+       }
 }
 
 void intel_display_power_get(struct drm_device *dev,
index 037d324bf58f6ccfda14ff471f3c98b4405981a0..66ac0ff95f5a30408bf722b43e49e76138e74546 100644 (file)
@@ -8,5 +8,6 @@ config DRM_QXL
         select DRM_KMS_HELPER
        select DRM_KMS_FB_HELPER
         select DRM_TTM
+       select CRC32
        help
                QXL virtual GPU for Spice virtualization desktop integration. Do not enable this driver unless your distro ships a corresponding X.org QXL driver that can handle kernel modesetting.
index 5e827c29d1948a658cf61205b7607ff5a53263d7..d70aafb83307d2a085afdbba6a2d4762309667ea 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 
-#include "linux/crc32.h"
+#include <linux/crc32.h>
 
 #include "qxl_drv.h"
 #include "qxl_object.h"
index de86493cbc44af60a8079028e8e509f8cee81c7e..713a5d35990102ea315fa078a93c11d6c1aae1f5 100644 (file)
@@ -174,7 +174,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
        }
@@ -235,7 +235,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
        }
@@ -308,7 +308,9 @@ int dce6_audio_init(struct radeon_device *rdev)
        rdev->audio.enabled = true;
 
        if (ASIC_IS_DCE8(rdev))
-               rdev->audio.num_pins = 7;
+               rdev->audio.num_pins = 6;
+       else if (ASIC_IS_DCE61(rdev))
+               rdev->audio.num_pins = 4;
        else
                rdev->audio.num_pins = 6;
 
index aa695c4feb3d00d393c2e9b74e2395a3a7395164..0c6d5cef4cf121770c63fcb559bf6cc187640292 100644 (file)
@@ -118,7 +118,7 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
        }
@@ -173,7 +173,7 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
        }
index 11aab2ab54ce27fb5c0279cbaaad797e95bea42f..f59a9e9fccf8a803ce6097e4e185d8824ad5f714 100644 (file)
@@ -895,6 +895,10 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                    (rdev->pdev->device == 0x999C)) {
                        rdev->config.cayman.max_simds_per_se = 6;
                        rdev->config.cayman.max_backends_per_se = 2;
+                       rdev->config.cayman.max_hw_contexts = 8;
+                       rdev->config.cayman.sx_max_export_size = 256;
+                       rdev->config.cayman.sx_max_export_pos_size = 64;
+                       rdev->config.cayman.sx_max_export_smx_size = 192;
                } else if ((rdev->pdev->device == 0x9903) ||
                           (rdev->pdev->device == 0x9904) ||
                           (rdev->pdev->device == 0x990A) ||
@@ -905,6 +909,10 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->pdev->device == 0x999D)) {
                        rdev->config.cayman.max_simds_per_se = 4;
                        rdev->config.cayman.max_backends_per_se = 2;
+                       rdev->config.cayman.max_hw_contexts = 8;
+                       rdev->config.cayman.sx_max_export_size = 256;
+                       rdev->config.cayman.sx_max_export_pos_size = 64;
+                       rdev->config.cayman.sx_max_export_smx_size = 192;
                } else if ((rdev->pdev->device == 0x9919) ||
                           (rdev->pdev->device == 0x9990) ||
                           (rdev->pdev->device == 0x9991) ||
@@ -915,9 +923,17 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->pdev->device == 0x99A0)) {
                        rdev->config.cayman.max_simds_per_se = 3;
                        rdev->config.cayman.max_backends_per_se = 1;
+                       rdev->config.cayman.max_hw_contexts = 4;
+                       rdev->config.cayman.sx_max_export_size = 128;
+                       rdev->config.cayman.sx_max_export_pos_size = 32;
+                       rdev->config.cayman.sx_max_export_smx_size = 96;
                } else {
                        rdev->config.cayman.max_simds_per_se = 2;
                        rdev->config.cayman.max_backends_per_se = 1;
+                       rdev->config.cayman.max_hw_contexts = 4;
+                       rdev->config.cayman.sx_max_export_size = 128;
+                       rdev->config.cayman.sx_max_export_pos_size = 32;
+                       rdev->config.cayman.sx_max_export_smx_size = 96;
                }
                rdev->config.cayman.max_texture_channel_caches = 2;
                rdev->config.cayman.max_gprs = 256;
@@ -925,10 +941,6 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                rdev->config.cayman.max_gs_threads = 32;
                rdev->config.cayman.max_stack_entries = 512;
                rdev->config.cayman.sx_num_of_sets = 8;
-               rdev->config.cayman.sx_max_export_size = 256;
-               rdev->config.cayman.sx_max_export_pos_size = 64;
-               rdev->config.cayman.sx_max_export_smx_size = 192;
-               rdev->config.cayman.max_hw_contexts = 8;
                rdev->config.cayman.sq_num_cf_insts = 2;
 
                rdev->config.cayman.sc_prim_fifo_size = 0x40;
index 913b025ae9b399695bed47af97cccf08fe68caf7..374499db20c7e59b55d956b066a30bdc42b4f71f 100644 (file)
@@ -2328,6 +2328,12 @@ void rv770_get_engine_memory_ss(struct radeon_device *rdev)
        pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
                                                       ASIC_INTERNAL_MEMORY_SS, 0);
 
+       /* disable ss, causes hangs on some cayman boards */
+       if (rdev->family == CHIP_CAYMAN) {
+               pi->sclk_ss = false;
+               pi->mclk_ss = false;
+       }
+
        if (pi->sclk_ss || pi->mclk_ss)
                pi->dynamic_ss = true;
        else
index 15b86a94949dcb875d3cd716322875ad8c763e88..4061521523154e0fbc102623b6a9d348e03d0313 100644 (file)
@@ -353,7 +353,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
         * Don't move nonexistent data. Clear destination instead.
         */
        if (old_iomap == NULL &&
-           (ttm == NULL || ttm->state == tt_unpopulated)) {
+           (ttm == NULL || (ttm->state == tt_unpopulated &&
+                            !(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)))) {
                memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE);
                goto out2;
        }
index 92d1206482a62ca57128690e49735dea2f00aaa3..f80b700f821ca4ece2a17ef1db08c099738f74fe 100644 (file)
@@ -377,6 +377,9 @@ static int intel_idle(struct cpuidle_device *dev,
 
        if (!current_set_polling_and_test()) {
 
+               if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
+                       clflush((void *)&current_thread_info()->flags);
+
                __monitor((void *)&current_thread_info()->flags, 0, 0);
                smp_mb();
                if (!need_resched())
index acb7f90359a3460371c9d1e8a00cd15c3a77a26d..749a6cadab8b3708d9a9e2d50f9d086f6f17e80e 100644 (file)
@@ -200,7 +200,13 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
                        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                        .address = 1,
                        .scan_index = 1,
-                       .scan_type = IIO_ST('u', 12, 16, 0),
+                       .scan_type = {
+                               .sign = 'u',
+                               .realbits = 12,
+                               .storagebits = 16,
+                               .shift = 0,
+                               .endianness = IIO_BE,
+                       },
                },
                .channel[1] = {
                        .type = IIO_VOLTAGE,
@@ -210,7 +216,13 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
                        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                        .address = 0,
                        .scan_index = 0,
-                       .scan_type = IIO_ST('u', 12, 16, 0),
+                       .scan_type = {
+                               .sign = 'u',
+                               .realbits = 12,
+                               .storagebits = 16,
+                               .shift = 0,
+                               .endianness = IIO_BE,
+                       },
                },
                .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
                .int_vref_mv = 2500,
index 3fb7757a10287b1991b4ef23676a8e4d2b315dad..368660dfe135a51c3cac05dd90d7dcb75dacb7c2 100644 (file)
@@ -651,7 +651,12 @@ static const struct iio_chan_spec adis16448_channels[] = {
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = ADIS16448_BARO_OUT,
                .scan_index = ADIS16400_SCAN_BARO,
-               .scan_type = IIO_ST('s', 16, 16, 0),
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 16,
+                       .storagebits = 16,
+                       .endianness = IIO_BE,
+               },
        },
        ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
        IIO_CHAN_SOFT_TIMESTAMP(11)
index 21df5713001831f91f5dbd592df94837bf612186..0922e39b0ea979a8355ac5da395d527ab871d269 100644 (file)
@@ -387,7 +387,7 @@ static int cm36651_read_int_time(struct cm36651_data *cm36651,
                return -EINVAL;
        }
 
-       return IIO_VAL_INT_PLUS_MICRO;
+       return IIO_VAL_INT;
 }
 
 static int cm36651_write_int_time(struct cm36651_data *cm36651,
index c47c2034ca71f9a95f3153fbc31756fc34b1fde0..0717940ec3b5080083cb53e8d8526bdf692c829a 100644 (file)
@@ -181,9 +181,16 @@ static void add_ref(struct iw_cm_id *cm_id)
 static void rem_ref(struct iw_cm_id *cm_id)
 {
        struct iwcm_id_private *cm_id_priv;
+       int cb_destroy;
+
        cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
-       if (iwcm_deref_id(cm_id_priv) &&
-           test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
+
+       /*
+        * Test bit before deref in case the cm_id gets freed on another
+        * thread.
+        */
+       cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
+       if (iwcm_deref_id(cm_id_priv) && cb_destroy) {
                BUG_ON(!list_empty(&cm_id_priv->work_list));
                free_cm_id(cm_id_priv);
        }
index bdc842e9faefe4ba477b96c479975643bfdc6366..a283274a5a09fa17b0dede8f5819ef9dfaf4458b 100644 (file)
 
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)                      \
        do {                                                            \
-               (udata)->inbuf  = (void __user *) (ibuf);               \
+               (udata)->inbuf  = (const void __user *) (ibuf);         \
                (udata)->outbuf = (void __user *) (obuf);               \
                (udata)->inlen  = (ilen);                               \
                (udata)->outlen = (olen);                               \
        } while (0)
 
+#define INIT_UDATA_BUF_OR_NULL(udata, ibuf, obuf, ilen, olen)                  \
+       do {                                                                    \
+               (udata)->inbuf  = (ilen) ? (const void __user *) (ibuf) : NULL; \
+               (udata)->outbuf = (olen) ? (void __user *) (obuf) : NULL;       \
+               (udata)->inlen  = (ilen);                                       \
+               (udata)->outlen = (olen);                                       \
+       } while (0)
+
 /*
  * Our lifetime rules for these structs are the following:
  *
index 65f6e7dc380c382cc0335e495fb2f583a4eef7b7..f1cc83855af65dd334a21d7c82a94f252413e42a 100644 (file)
@@ -2593,6 +2593,9 @@ out_put:
 static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
                                union ib_flow_spec *ib_spec)
 {
+       if (kern_spec->reserved)
+               return -EINVAL;
+
        ib_spec->type = kern_spec->type;
 
        switch (ib_spec->type) {
@@ -2646,6 +2649,9 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
        void *ib_spec;
        int i;
 
+       if (ucore->inlen < sizeof(cmd))
+               return -EINVAL;
+
        if (ucore->outlen < sizeof(resp))
                return -ENOSPC;
 
@@ -2671,6 +2677,10 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
            (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec)))
                return -EINVAL;
 
+       if (cmd.flow_attr.reserved[0] ||
+           cmd.flow_attr.reserved[1])
+               return -EINVAL;
+
        if (cmd.flow_attr.num_of_specs) {
                kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size,
                                         GFP_KERNEL);
@@ -2731,6 +2741,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
        if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) {
                pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n",
                        i, cmd.flow_attr.size);
+               err = -EINVAL;
                goto err_free;
        }
        flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER);
@@ -2791,10 +2802,16 @@ int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file,
        struct ib_uobject               *uobj;
        int                             ret;
 
+       if (ucore->inlen < sizeof(cmd))
+               return -EINVAL;
+
        ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
        if (ret)
                return ret;
 
+       if (cmd.comp_mask)
+               return -EINVAL;
+
        uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle,
                              file->ucontext);
        if (!uobj)
index 34386943ebcff4cf18849082add568f5fc73bc5a..08219fb3338b0652f350da1af864b4cfb355ff3c 100644 (file)
@@ -668,25 +668,30 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
                if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count)
                        return -EINVAL;
 
+               if (ex_hdr.cmd_hdr_reserved)
+                       return -EINVAL;
+
                if (ex_hdr.response) {
                        if (!hdr.out_words && !ex_hdr.provider_out_words)
                                return -EINVAL;
+
+                       if (!access_ok(VERIFY_WRITE,
+                                      (void __user *) (unsigned long) ex_hdr.response,
+                                      (hdr.out_words + ex_hdr.provider_out_words) * 8))
+                               return -EFAULT;
                } else {
                        if (hdr.out_words || ex_hdr.provider_out_words)
                                return -EINVAL;
                }
 
-               INIT_UDATA(&ucore,
-                          (hdr.in_words) ? buf : 0,
-                          (unsigned long)ex_hdr.response,
-                          hdr.in_words * 8,
-                          hdr.out_words * 8);
-
-               INIT_UDATA(&uhw,
-                          (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0,
-                          (ex_hdr.provider_out_words) ? (unsigned long)ex_hdr.response + ucore.outlen : 0,
-                          ex_hdr.provider_in_words * 8,
-                          ex_hdr.provider_out_words * 8);
+               INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response,
+                                      hdr.in_words * 8, hdr.out_words * 8);
+
+               INIT_UDATA_BUF_OR_NULL(&uhw,
+                                      buf + ucore.inlen,
+                                      (unsigned long) ex_hdr.response + ucore.outlen,
+                                      ex_hdr.provider_in_words * 8,
+                                      ex_hdr.provider_out_words * 8);
 
                err = uverbs_ex_cmd_table[command](file,
                                                   &ucore,
index 12fef76c791c524454bd9a0c48d5b4a967ac19af..45126879ad28a2149351232a1f9c4a2551f06c09 100644 (file)
@@ -524,50 +524,6 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
        return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
-#define VLAN_NONE 0xfff
-#define FILTER_SEL_VLAN_NONE 0xffff
-#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */
-#define FILTER_SEL_WIDTH_VIN_P_FC \
-       (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/
-#define FILTER_SEL_WIDTH_TAG_P_FC \
-       (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */
-#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
-
-static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst,
-                                 struct l2t_entry *l2t)
-{
-       unsigned int ntuple = 0;
-       u32 viid;
-
-       switch (dev->rdev.lldi.filt_mode) {
-
-       /* default filter mode */
-       case HW_TPL_FR_MT_PR_IV_P_FC:
-               if (l2t->vlan == VLAN_NONE)
-                       ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
-               else {
-                       ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC;
-                       ntuple |= 1 << FILTER_SEL_WIDTH_TAG_P_FC;
-               }
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       case HW_TPL_FR_MT_PR_OV_P_FC: {
-               viid = cxgb4_port_viid(l2t->neigh->dev);
-
-               ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC;
-               ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
-               ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       }
-       default:
-               break;
-       }
-       return ntuple;
-}
-
 static int send_connect(struct c4iw_ep *ep)
 {
        struct cpl_act_open_req *req;
@@ -641,8 +597,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req->local_ip = la->sin_addr.s_addr;
                        req->peer_ip = ra->sin_addr.s_addr;
                        req->opt0 = cpu_to_be64(opt0);
-                       req->params = cpu_to_be32(select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t));
+                       req->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req->opt2 = cpu_to_be32(opt2);
                } else {
                        req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen);
@@ -662,9 +619,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req6->peer_ip_lo = *((__be64 *)
                                                (ra6->sin6_addr.s6_addr + 8));
                        req6->opt0 = cpu_to_be64(opt0);
-                       req6->params = cpu_to_be32(
-                                       select_ntuple(ep->com.dev, ep->dst,
-                                                     ep->l2t));
+                       req6->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req6->opt2 = cpu_to_be32(opt2);
                }
        } else {
@@ -681,8 +638,9 @@ static int send_connect(struct c4iw_ep *ep)
                        t5_req->peer_ip = ra->sin_addr.s_addr;
                        t5_req->opt0 = cpu_to_be64(opt0);
                        t5_req->params = cpu_to_be64(V_FILTER_TUPLE(
-                                               select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t)));
+                                                    cxgb4_select_ntuple(
+                                            ep->com.dev->rdev.lldi.ports[0],
+                                            ep->l2t)));
                        t5_req->opt2 = cpu_to_be32(opt2);
                } else {
                        t5_req6 = (struct cpl_t5_act_open_req6 *)
@@ -703,7 +661,9 @@ static int send_connect(struct c4iw_ep *ep)
                                                (ra6->sin6_addr.s6_addr + 8));
                        t5_req6->opt0 = cpu_to_be64(opt0);
                        t5_req6->params = (__force __be64)cpu_to_be32(
-                               select_ntuple(ep->com.dev, ep->dst, ep->l2t));
+                                                       cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        t5_req6->opt2 = cpu_to_be32(opt2);
                }
        }
@@ -1630,7 +1590,8 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
        memset(req, 0, sizeof(*req));
        req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR));
        req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16)));
-       req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst,
+       req->le.filter = cpu_to_be32(cxgb4_select_ntuple(
+                                    ep->com.dev->rdev.lldi.ports[0],
                                     ep->l2t));
        sin = (struct sockaddr_in *)&ep->com.local_addr;
        req->le.lport = sin->sin_port;
@@ -2938,7 +2899,8 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
        /*
         * Allocate a server TID.
         */
-       if (dev->rdev.lldi.enable_fw_ofld_conn)
+       if (dev->rdev.lldi.enable_fw_ofld_conn &&
+           ep->com.local_addr.ss_family == AF_INET)
                ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids,
                                             cm_id->local_addr.ss_family, ep);
        else
@@ -3323,9 +3285,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        /*
         * Calculate the server tid from filter hit index from cpl_rx_pkt.
         */
-       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val)
-                                         - dev->rdev.lldi.tids->sftid_base
-                                         + dev->rdev.lldi.tids->nstids;
+       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val);
 
        lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid);
        if (!lep) {
@@ -3397,7 +3357,9 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        window = (__force u16) htons((__force u16)tcph->window);
 
        /* Calcuate filter portion for LE region. */
-       filter = (__force unsigned int) cpu_to_be32(select_ntuple(dev, dst, e));
+       filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple(
+                                                   dev->rdev.lldi.ports[0],
+                                                   e));
 
        /*
         * Synthesize the cpl_pass_accept_req. We have everything except the
index 4cb8eb24497cfa61821b4863c4026ff5a061405a..84e45006451cd3983cd1b28bfb22d2c0a9c02ef7 100644 (file)
@@ -173,7 +173,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
        return ret;
 }
 
-int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
+static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
 {
        u32 remain = len;
        u32 dmalen;
index 6b29249aa85a9ed59b24df4c5fc42636371b9181..9c9f2f57e960e1803b831aaf1a94b87011822844 100644 (file)
@@ -1354,8 +1354,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
                                  neigh->ha, ntohl(rt->rt_gateway));
 
                        if (arpindex >= 0) {
-                               if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
-                                           neigh->ha, ETH_ALEN)) {
+                               if (ether_addr_equal(nesadapter->arp_table[arpindex].mac_addr, neigh->ha)) {
                                        /* Mac address same as in nes_arp_table */
                                        goto out;
                                }
index c29b5c8388331458bb2a2caf85580d76031f1dcb..cdc7df4fdb8aedea8c9026de82d774e5f5fe502b 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/if_arp.h>      /* For ARPHRD_xxx */
 #include <linux/module.h>
 #include <net/rtnetlink.h>
 #include "ipoib.h"
@@ -103,7 +104,7 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
                return -EINVAL;
 
        pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
-       if (!pdev)
+       if (!pdev || pdev->type != ARPHRD_INFINIBAND)
                return -ENODEV;
 
        ppriv = netdev_priv(pdev);
index 6be57c38638d28dd0a39464bffe391c4a093f478..9804fca6bf0605a074c13f470e4bf6cf8413bd66 100644 (file)
@@ -207,7 +207,9 @@ isert_free_rx_descriptors(struct isert_conn *isert_conn)
        isert_conn->conn_rx_descs = NULL;
 }
 
+static void isert_cq_tx_work(struct work_struct *);
 static void isert_cq_tx_callback(struct ib_cq *, void *);
+static void isert_cq_rx_work(struct work_struct *);
 static void isert_cq_rx_callback(struct ib_cq *, void *);
 
 static int
@@ -259,26 +261,36 @@ isert_create_device_ib_res(struct isert_device *device)
                cq_desc[i].device = device;
                cq_desc[i].cq_index = i;
 
+               INIT_WORK(&cq_desc[i].cq_rx_work, isert_cq_rx_work);
                device->dev_rx_cq[i] = ib_create_cq(device->ib_device,
                                                isert_cq_rx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
                                                ISER_MAX_RX_CQ_LEN, i);
-               if (IS_ERR(device->dev_rx_cq[i]))
+               if (IS_ERR(device->dev_rx_cq[i])) {
+                       ret = PTR_ERR(device->dev_rx_cq[i]);
+                       device->dev_rx_cq[i] = NULL;
                        goto out_cq;
+               }
 
+               INIT_WORK(&cq_desc[i].cq_tx_work, isert_cq_tx_work);
                device->dev_tx_cq[i] = ib_create_cq(device->ib_device,
                                                isert_cq_tx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
                                                ISER_MAX_TX_CQ_LEN, i);
-               if (IS_ERR(device->dev_tx_cq[i]))
+               if (IS_ERR(device->dev_tx_cq[i])) {
+                       ret = PTR_ERR(device->dev_tx_cq[i]);
+                       device->dev_tx_cq[i] = NULL;
                        goto out_cq;
+               }
 
-               if (ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP))
+               ret = ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP);
+               if (ret)
                        goto out_cq;
 
-               if (ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP))
+               ret = ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP);
+               if (ret)
                        goto out_cq;
        }
 
@@ -1724,7 +1736,6 @@ isert_cq_tx_callback(struct ib_cq *cq, void *context)
 {
        struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context;
 
-       INIT_WORK(&cq_desc->cq_tx_work, isert_cq_tx_work);
        queue_work(isert_comp_wq, &cq_desc->cq_tx_work);
 }
 
@@ -1768,7 +1779,6 @@ isert_cq_rx_callback(struct ib_cq *cq, void *context)
 {
        struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context;
 
-       INIT_WORK(&cq_desc->cq_rx_work, isert_cq_rx_work);
        queue_work(isert_rx_wq, &cq_desc->cq_rx_work);
 }
 
index 82cec63a90112e184c96a2e21e612df977adf7b7..3ee78f02e5d7d940d531aa6ab03c8dc681c9cb3c 100644 (file)
@@ -149,8 +149,9 @@ static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
 static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
                                         int irq, int do_mask)
 {
-       int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
-       int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
+       /* The PRIO register is assumed to be 32-bit with fixed 4-bit fields. */
+       int bitfield_width = 4;
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
                                      shift, bitfield_width,
@@ -159,8 +160,9 @@ static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
 
 static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
 {
+       /* The SENSE register is assumed to be 32-bit. */
        int bitfield_width = p->config.sense_bitfield_width;
-       int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
 
index 497bd026c2378eec6e781df68d007c135be4c1f7..4a48255281887e8c03f9dbacccf404f4f9c52476 100644 (file)
@@ -1643,10 +1643,6 @@ setup_hfcpci(struct IsdnCard *card)
        int i;
        struct pci_dev *tmp_hfcpci = NULL;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, hfcpci_revision);
        printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
 
index f6ab63aa699590278531ba9ae6ceabe75ba90813..33eeb4602c7e7131078d78d97b24f09971b8396e 100644 (file)
@@ -290,10 +290,6 @@ int setup_telespci(struct IsdnCard *card)
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, telespci_revision);
        printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
        if (cs->typ != ISDN_CTYPE_TELESPCI)
index 8b98d53d99764be297362969fc1c88d1865639ec..d9aebbc510cc77d4116fa17c5349034f329e2362 100644 (file)
@@ -1371,7 +1371,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
        eth = eth_hdr(skb);
 
        if (*eth->h_dest & 1) {
-               if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+               if (ether_addr_equal(eth->h_dest, dev->broadcast))
                        skb->pkt_type = PACKET_BROADCAST;
                else
                        skb->pkt_type = PACKET_MULTICAST;
@@ -1382,7 +1382,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
         */
 
        else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
-               if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+               if (!ether_addr_equal(eth->h_dest, dev->dev_addr))
                        skb->pkt_type = PACKET_OTHERHOST;
        }
        if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
index 2b46bf1d7e40ca7375517ebb97a2225475844a91..4c9852d92b0a909d5b103510ae77d55f4bb05ad0 100644 (file)
@@ -421,9 +421,11 @@ out:
 
        if (watermark <= WATERMARK_METADATA) {
                SET_GC_MARK(b, GC_MARK_METADATA);
+               SET_GC_MOVE(b, 0);
                b->prio = BTREE_PRIO;
        } else {
                SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
+               SET_GC_MOVE(b, 0);
                b->prio = INITIAL_PRIO;
        }
 
index 4beb55a0ff30dc9da10c340270e9cbd1c0e1c0b0..754f4317748322e7450d69da9591b6b72aff6dc4 100644 (file)
@@ -197,7 +197,7 @@ struct bucket {
        uint8_t         disk_gen;
        uint8_t         last_gc; /* Most out of date gen in the btree */
        uint8_t         gc_gen;
-       uint16_t        gc_mark;
+       uint16_t        gc_mark; /* Bitfield used by GC. See below for field */
 };
 
 /*
@@ -209,7 +209,8 @@ BITMASK(GC_MARK,     struct bucket, gc_mark, 0, 2);
 #define GC_MARK_RECLAIMABLE    0
 #define GC_MARK_DIRTY          1
 #define GC_MARK_METADATA       2
-BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 14);
+BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 13);
+BITMASK(GC_MOVE, struct bucket, gc_mark, 15, 1);
 
 #include "journal.h"
 #include "stats.h"
@@ -372,14 +373,14 @@ struct cached_dev {
        unsigned char           writeback_percent;
        unsigned                writeback_delay;
 
-       int                     writeback_rate_change;
-       int64_t                 writeback_rate_derivative;
        uint64_t                writeback_rate_target;
+       int64_t                 writeback_rate_proportional;
+       int64_t                 writeback_rate_derivative;
+       int64_t                 writeback_rate_change;
 
        unsigned                writeback_rate_update_seconds;
        unsigned                writeback_rate_d_term;
        unsigned                writeback_rate_p_term_inverse;
-       unsigned                writeback_rate_d_smooth;
 };
 
 enum alloc_watermarks {
@@ -445,7 +446,6 @@ struct cache {
         * call prio_write() to keep gens from wrapping.
         */
        uint8_t                 need_save_prio;
-       unsigned                gc_move_threshold;
 
        /*
         * If nonzero, we know we aren't going to find any buckets to invalidate
index 5e2765aadce174e9b7cffd479667a2c48bcf500f..31bb53fcc67a40806cf73659a596f98297d36128 100644 (file)
@@ -1561,6 +1561,28 @@ size_t bch_btree_gc_finish(struct cache_set *c)
                SET_GC_MARK(PTR_BUCKET(c, &c->uuid_bucket, i),
                            GC_MARK_METADATA);
 
+       /* don't reclaim buckets to which writeback keys point */
+       rcu_read_lock();
+       for (i = 0; i < c->nr_uuids; i++) {
+               struct bcache_device *d = c->devices[i];
+               struct cached_dev *dc;
+               struct keybuf_key *w, *n;
+               unsigned j;
+
+               if (!d || UUID_FLASH_ONLY(&c->uuids[i]))
+                       continue;
+               dc = container_of(d, struct cached_dev, disk);
+
+               spin_lock(&dc->writeback_keys.lock);
+               rbtree_postorder_for_each_entry_safe(w, n,
+                                       &dc->writeback_keys.keys, node)
+                       for (j = 0; j < KEY_PTRS(&w->key); j++)
+                               SET_GC_MARK(PTR_BUCKET(c, &w->key, j),
+                                           GC_MARK_DIRTY);
+               spin_unlock(&dc->writeback_keys.lock);
+       }
+       rcu_read_unlock();
+
        for_each_cache(ca, c, i) {
                uint64_t *i;
 
@@ -1817,7 +1839,8 @@ static bool fix_overlapping_extents(struct btree *b, struct bkey *insert,
                        if (KEY_START(k) > KEY_START(insert) + sectors_found)
                                goto check_failed;
 
-                       if (KEY_PTRS(replace_key) != KEY_PTRS(k))
+                       if (KEY_PTRS(k) != KEY_PTRS(replace_key) ||
+                           KEY_DIRTY(k) != KEY_DIRTY(replace_key))
                                goto check_failed;
 
                        /* skip past gen */
@@ -2217,7 +2240,7 @@ struct btree_insert_op {
        struct bkey     *replace_key;
 };
 
-int btree_insert_fn(struct btree_op *b_op, struct btree *b)
+static int btree_insert_fn(struct btree_op *b_op, struct btree *b)
 {
        struct btree_insert_op *op = container_of(b_op,
                                        struct btree_insert_op, op);
index 7c1275e66025b691ec8ee4896448d46e28a2c5d9..f2f0998c4a91872407dd036a54fe72d243885fed 100644 (file)
@@ -25,10 +25,9 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
        unsigned i;
 
        for (i = 0; i < KEY_PTRS(k); i++) {
-               struct cache *ca = PTR_CACHE(c, k, i);
                struct bucket *g = PTR_BUCKET(c, k, i);
 
-               if (GC_SECTORS_USED(g) < ca->gc_move_threshold)
+               if (GC_MOVE(g))
                        return true;
        }
 
@@ -65,11 +64,16 @@ static void write_moving_finish(struct closure *cl)
 
 static void read_moving_endio(struct bio *bio, int error)
 {
+       struct bbio *b = container_of(bio, struct bbio, bio);
        struct moving_io *io = container_of(bio->bi_private,
                                            struct moving_io, cl);
 
        if (error)
                io->op.error = error;
+       else if (!KEY_DIRTY(&b->key) &&
+                ptr_stale(io->op.c, &b->key, 0)) {
+               io->op.error = -EINTR;
+       }
 
        bch_bbio_endio(io->op.c, bio, error, "reading data to move");
 }
@@ -141,6 +145,11 @@ static void read_moving(struct cache_set *c)
                if (!w)
                        break;
 
+               if (ptr_stale(c, &w->key, 0)) {
+                       bch_keybuf_del(&c->moving_gc_keys, w);
+                       continue;
+               }
+
                io = kzalloc(sizeof(struct moving_io) + sizeof(struct bio_vec)
                             * DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
                             GFP_KERNEL);
@@ -184,7 +193,8 @@ static bool bucket_cmp(struct bucket *l, struct bucket *r)
 
 static unsigned bucket_heap_top(struct cache *ca)
 {
-       return GC_SECTORS_USED(heap_peek(&ca->heap));
+       struct bucket *b;
+       return (b = heap_peek(&ca->heap)) ? GC_SECTORS_USED(b) : 0;
 }
 
 void bch_moving_gc(struct cache_set *c)
@@ -226,9 +236,8 @@ void bch_moving_gc(struct cache_set *c)
                        sectors_to_move -= GC_SECTORS_USED(b);
                }
 
-               ca->gc_move_threshold = bucket_heap_top(ca);
-
-               pr_debug("threshold %u", ca->gc_move_threshold);
+               while (heap_pop(&ca->heap, b, bucket_cmp))
+                       SET_GC_MOVE(b, 1);
        }
 
        mutex_unlock(&c->bucket_lock);
index dec15cd2d797eaaa7fa0585abf8867c9f70a4cef..c57bfa071a57c58b06fabeb194cbf98f5f4fbf56 100644 (file)
@@ -1676,7 +1676,7 @@ err:
 static bool can_attach_cache(struct cache *ca, struct cache_set *c)
 {
        return ca->sb.block_size        == c->sb.block_size &&
-               ca->sb.bucket_size      == c->sb.block_size &&
+               ca->sb.bucket_size      == c->sb.bucket_size &&
                ca->sb.nr_in_set        == c->sb.nr_in_set;
 }
 
index 80d4c2bee18aa3fd1af0f58c050145af8e0a1c98..a1f85612f0b3dfc5c90b768aaef48118034c02c7 100644 (file)
@@ -83,7 +83,6 @@ rw_attribute(writeback_rate);
 rw_attribute(writeback_rate_update_seconds);
 rw_attribute(writeback_rate_d_term);
 rw_attribute(writeback_rate_p_term_inverse);
-rw_attribute(writeback_rate_d_smooth);
 read_attribute(writeback_rate_debug);
 
 read_attribute(stripe_size);
@@ -129,31 +128,41 @@ SHOW(__bch_cached_dev)
        var_printf(writeback_running,   "%i");
        var_print(writeback_delay);
        var_print(writeback_percent);
-       sysfs_print(writeback_rate,     dc->writeback_rate.rate);
+       sysfs_hprint(writeback_rate,    dc->writeback_rate.rate << 9);
 
        var_print(writeback_rate_update_seconds);
        var_print(writeback_rate_d_term);
        var_print(writeback_rate_p_term_inverse);
-       var_print(writeback_rate_d_smooth);
 
        if (attr == &sysfs_writeback_rate_debug) {
+               char rate[20];
                char dirty[20];
-               char derivative[20];
                char target[20];
-               bch_hprint(dirty,
-                          bcache_dev_sectors_dirty(&dc->disk) << 9);
-               bch_hprint(derivative,  dc->writeback_rate_derivative << 9);
+               char proportional[20];
+               char derivative[20];
+               char change[20];
+               s64 next_io;
+
+               bch_hprint(rate,        dc->writeback_rate.rate << 9);
+               bch_hprint(dirty,       bcache_dev_sectors_dirty(&dc->disk) << 9);
                bch_hprint(target,      dc->writeback_rate_target << 9);
+               bch_hprint(proportional,dc->writeback_rate_proportional << 9);
+               bch_hprint(derivative,  dc->writeback_rate_derivative << 9);
+               bch_hprint(change,      dc->writeback_rate_change << 9);
+
+               next_io = div64_s64(dc->writeback_rate.next - local_clock(),
+                                   NSEC_PER_MSEC);
 
                return sprintf(buf,
-                              "rate:\t\t%u\n"
-                              "change:\t\t%i\n"
+                              "rate:\t\t%s/sec\n"
                               "dirty:\t\t%s\n"
+                              "target:\t\t%s\n"
+                              "proportional:\t%s\n"
                               "derivative:\t%s\n"
-                              "target:\t\t%s\n",
-                              dc->writeback_rate.rate,
-                              dc->writeback_rate_change,
-                              dirty, derivative, target);
+                              "change:\t\t%s/sec\n"
+                              "next io:\t%llims\n",
+                              rate, dirty, target, proportional,
+                              derivative, change, next_io);
        }
 
        sysfs_hprint(dirty_data,
@@ -189,6 +198,7 @@ STORE(__cached_dev)
        struct kobj_uevent_env *env;
 
 #define d_strtoul(var)         sysfs_strtoul(var, dc->var)
+#define d_strtoul_nonzero(var) sysfs_strtoul_clamp(var, dc->var, 1, INT_MAX)
 #define d_strtoi_h(var)                sysfs_hatoi(var, dc->var)
 
        sysfs_strtoul(data_csum,        dc->disk.data_csum);
@@ -197,16 +207,15 @@ STORE(__cached_dev)
        d_strtoul(writeback_metadata);
        d_strtoul(writeback_running);
        d_strtoul(writeback_delay);
-       sysfs_strtoul_clamp(writeback_rate,
-                           dc->writeback_rate.rate, 1, 1000000);
+
        sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent, 0, 40);
 
-       d_strtoul(writeback_rate_update_seconds);
+       sysfs_strtoul_clamp(writeback_rate,
+                           dc->writeback_rate.rate, 1, INT_MAX);
+
+       d_strtoul_nonzero(writeback_rate_update_seconds);
        d_strtoul(writeback_rate_d_term);
-       d_strtoul(writeback_rate_p_term_inverse);
-       sysfs_strtoul_clamp(writeback_rate_p_term_inverse,
-                           dc->writeback_rate_p_term_inverse, 1, INT_MAX);
-       d_strtoul(writeback_rate_d_smooth);
+       d_strtoul_nonzero(writeback_rate_p_term_inverse);
 
        d_strtoi_h(sequential_cutoff);
        d_strtoi_h(readahead);
@@ -313,7 +322,6 @@ static struct attribute *bch_cached_dev_files[] = {
        &sysfs_writeback_rate_update_seconds,
        &sysfs_writeback_rate_d_term,
        &sysfs_writeback_rate_p_term_inverse,
-       &sysfs_writeback_rate_d_smooth,
        &sysfs_writeback_rate_debug,
        &sysfs_dirty_data,
        &sysfs_stripe_size,
index 462214eeacbedbd9548e725be2e625723cda0d7e..bb37618e76648b7bc3caf99532e4f81b48666dfe 100644 (file)
@@ -209,7 +209,13 @@ uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done)
 {
        uint64_t now = local_clock();
 
-       d->next += div_u64(done, d->rate);
+       d->next += div_u64(done * NSEC_PER_SEC, d->rate);
+
+       if (time_before64(now + NSEC_PER_SEC, d->next))
+               d->next = now + NSEC_PER_SEC;
+
+       if (time_after64(now - NSEC_PER_SEC * 2, d->next))
+               d->next = now - NSEC_PER_SEC * 2;
 
        return time_after64(d->next, now)
                ? div_u64(d->next - now, NSEC_PER_SEC / HZ)
index 362c4b3f8b4a00e70d2e36af9ee7ec8cbe67e39e..1030c6020e986934e21c94628794e5e342271b49 100644 (file)
@@ -110,7 +110,7 @@ do {                                                                        \
        _r;                                                             \
 })
 
-#define heap_peek(h)   ((h)->size ? (h)->data[0] : NULL)
+#define heap_peek(h)   ((h)->used ? (h)->data[0] : NULL)
 
 #define heap_full(h)   ((h)->used == (h)->size)
 
index 99053b1251bea1049c627580f3614d1c18f89b60..6c44fe059c2769a4b2c317f25878596268726f0d 100644 (file)
@@ -30,38 +30,40 @@ static void __update_writeback_rate(struct cached_dev *dc)
 
        /* PD controller */
 
-       int change = 0;
-       int64_t error;
        int64_t dirty = bcache_dev_sectors_dirty(&dc->disk);
        int64_t derivative = dirty - dc->disk.sectors_dirty_last;
+       int64_t proportional = dirty - target;
+       int64_t change;
 
        dc->disk.sectors_dirty_last = dirty;
 
-       derivative *= dc->writeback_rate_d_term;
-       derivative = clamp(derivative, -dirty, dirty);
+       /* Scale to sectors per second */
 
-       derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative,
-                             dc->writeback_rate_d_smooth, 0);
+       proportional *= dc->writeback_rate_update_seconds;
+       proportional = div_s64(proportional, dc->writeback_rate_p_term_inverse);
 
-       /* Avoid divide by zero */
-       if (!target)
-               goto out;
+       derivative = div_s64(derivative, dc->writeback_rate_update_seconds);
 
-       error = div64_s64((dirty + derivative - target) << 8, target);
+       derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative,
+                             (dc->writeback_rate_d_term /
+                              dc->writeback_rate_update_seconds) ?: 1, 0);
+
+       derivative *= dc->writeback_rate_d_term;
+       derivative = div_s64(derivative, dc->writeback_rate_p_term_inverse);
 
-       change = div_s64((dc->writeback_rate.rate * error) >> 8,
-                        dc->writeback_rate_p_term_inverse);
+       change = proportional + derivative;
 
        /* Don't increase writeback rate if the device isn't keeping up */
        if (change > 0 &&
            time_after64(local_clock(),
-                        dc->writeback_rate.next + 10 * NSEC_PER_MSEC))
+                        dc->writeback_rate.next + NSEC_PER_MSEC))
                change = 0;
 
        dc->writeback_rate.rate =
-               clamp_t(int64_t, dc->writeback_rate.rate + change,
+               clamp_t(int64_t, (int64_t) dc->writeback_rate.rate + change,
                        1, NSEC_PER_MSEC);
-out:
+
+       dc->writeback_rate_proportional = proportional;
        dc->writeback_rate_derivative = derivative;
        dc->writeback_rate_change = change;
        dc->writeback_rate_target = target;
@@ -87,15 +89,11 @@ static void update_writeback_rate(struct work_struct *work)
 
 static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
 {
-       uint64_t ret;
-
        if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
            !dc->writeback_percent)
                return 0;
 
-       ret = bch_next_delay(&dc->writeback_rate, sectors * 10000000ULL);
-
-       return min_t(uint64_t, ret, HZ);
+       return bch_next_delay(&dc->writeback_rate, sectors);
 }
 
 struct dirty_io {
@@ -241,7 +239,7 @@ static void read_dirty(struct cached_dev *dc)
                if (KEY_START(&w->key) != dc->last_read ||
                    jiffies_to_msecs(delay) > 50)
                        while (!kthread_should_stop() && delay)
-                               delay = schedule_timeout_interruptible(delay);
+                               delay = schedule_timeout_uninterruptible(delay);
 
                dc->last_read   = KEY_OFFSET(&w->key);
 
@@ -438,7 +436,7 @@ static int bch_writeback_thread(void *arg)
                        while (delay &&
                               !kthread_should_stop() &&
                               !test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
-                               delay = schedule_timeout_interruptible(delay);
+                               delay = schedule_timeout_uninterruptible(delay);
                }
        }
 
@@ -476,6 +474,8 @@ void bch_sectors_dirty_init(struct cached_dev *dc)
 
        bch_btree_map_keys(&op.op, dc->disk.c, &KEY(op.inode, 0, 0),
                           sectors_dirty_init_fn, 0);
+
+       dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk);
 }
 
 int bch_cached_dev_writeback_init(struct cached_dev *dc)
@@ -490,18 +490,15 @@ int bch_cached_dev_writeback_init(struct cached_dev *dc)
        dc->writeback_delay             = 30;
        dc->writeback_rate.rate         = 1024;
 
-       dc->writeback_rate_update_seconds = 30;
-       dc->writeback_rate_d_term       = 16;
-       dc->writeback_rate_p_term_inverse = 64;
-       dc->writeback_rate_d_smooth     = 8;
+       dc->writeback_rate_update_seconds = 5;
+       dc->writeback_rate_d_term       = 30;
+       dc->writeback_rate_p_term_inverse = 6000;
 
        dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
                                              "bcache_writeback");
        if (IS_ERR(dc->writeback_thread))
                return PTR_ERR(dc->writeback_thread);
 
-       set_task_state(dc->writeback_thread, TASK_INTERRUPTIBLE);
-
        INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
        schedule_delayed_work(&dc->writeback_rate_update,
                              dc->writeback_rate_update_seconds * HZ);
index f91c80c0e9ec0899816ea177dc616e4aa2b2755d..8a86b3025637d69c33a91ed7c697f5ad261fedb1 100644 (file)
@@ -179,7 +179,7 @@ static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
        eth = eth_hdr(skb);
 
        if (*eth->h_dest & 1) {
-               if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
+               if(ether_addr_equal(eth->h_dest,dev->broadcast))
                        skb->pkt_type=PACKET_BROADCAST;
                else
                        skb->pkt_type=PACKET_MULTICAST;
@@ -674,11 +674,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                        if (priv->rx_mode != RX_MODE_PROMISC) {
                                                if (priv->ule_skb->data[0] & 0x01) {
                                                        /* multicast or broadcast */
-                                                       if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) {
+                                                       if (!ether_addr_equal(priv->ule_skb->data, bc_addr)) {
                                                                /* multicast */
                                                                if (priv->rx_mode == RX_MODE_MULTI) {
                                                                        int i;
-                                                                       for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++)
+                                                                       for(i = 0; i < priv->multi_num &&
+                                                                           !ether_addr_equal(priv->ule_skb->data,
+                                                                                             priv->multi_macs[i]); i++)
                                                                                ;
                                                                        if (i == priv->multi_num)
                                                                                drop = 1;
@@ -688,7 +690,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                                        }
                                                        /* else: broadcast */
                                                }
-                                               else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN))
+                                               else if (!ether_addr_equal(priv->ule_skb->data, dev->dev_addr))
                                                        drop = 1;
                                                /* else: destination address matches the MAC address of our receiver device */
                                        }
index 58c2249a3324168b8c03924ee18e0e7ff27b4703..cce1f1bf90b4324e6e2f20e5da6ef53a307bd296 100644 (file)
 #include "bonding.h"
 #include "bond_3ad.h"
 
-// General definitions
+/* General definitions */
 #define AD_SHORT_TIMEOUT           1
 #define AD_LONG_TIMEOUT            0
 #define AD_STANDBY                 0x2
 #define AD_MAX_TX_IN_SECOND        3
 #define AD_COLLECTOR_MAX_DELAY     0
 
-// Timer definitions(43.4.4 in the 802.3ad standard)
+/* Timer definitions (43.4.4 in the 802.3ad standard) */
 #define AD_FAST_PERIODIC_TIME      1
 #define AD_SLOW_PERIODIC_TIME      30
 #define AD_SHORT_TIMEOUT_TIME      (3*AD_FAST_PERIODIC_TIME)
@@ -49,7 +49,7 @@
 #define AD_CHURN_DETECTION_TIME    60
 #define AD_AGGREGATE_WAIT_TIME     2
 
-// Port state definitions(43.4.2.2 in the 802.3ad standard)
+/* Port state definitions (43.4.2.2 in the 802.3ad standard) */
 #define AD_STATE_LACP_ACTIVITY   0x1
 #define AD_STATE_LACP_TIMEOUT    0x2
 #define AD_STATE_AGGREGATION     0x4
@@ -59,7 +59,9 @@
 #define AD_STATE_DEFAULTED       0x40
 #define AD_STATE_EXPIRED         0x80
 
-// Port Variables definitions used by the State Machines(43.4.7 in the 802.3ad standard)
+/* Port Variables definitions used by the State Machines (43.4.7 in the
+ * 802.3ad standard)
+ */
 #define AD_PORT_BEGIN           0x1
 #define AD_PORT_LACP_ENABLED    0x2
 #define AD_PORT_ACTOR_CHURN     0x4
 #define AD_PORT_SELECTED        0x100
 #define AD_PORT_MOVED           0x200
 
-// Port Key definitions
-// key is determined according to the link speed, duplex and
-// user key(which is yet not supported)
-//              ------------------------------------------------------------
-// Port key :   | User key                       |      Speed       |Duplex|
-//              ------------------------------------------------------------
-//              16                               6               1 0
+/* Port Key definitions
+ * key is determined according to the link speed, duplex and
+ * user key (which is yet not supported)
+ * --------------------------------------------------------------
+ * Port key :  | User key      | Speed         | Duplex        |
+ * --------------------------------------------------------------
+ * 16            6               1               0
+ */
 #define  AD_DUPLEX_KEY_BITS    0x1
 #define  AD_SPEED_KEY_BITS     0x3E
 #define  AD_USER_KEY_BITS      0xFFC0
 
-//dalloun
 #define     AD_LINK_SPEED_BITMASK_1MBPS       0x1
 #define     AD_LINK_SPEED_BITMASK_10MBPS      0x2
 #define     AD_LINK_SPEED_BITMASK_100MBPS     0x4
 #define     AD_LINK_SPEED_BITMASK_1000MBPS    0x8
 #define     AD_LINK_SPEED_BITMASK_10000MBPS   0x10
-//endalloun
 
-// compare MAC addresses
-#define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN)
+/* compare MAC addresses */
+#define MAC_ADDRESS_EQUAL(A, B)        \
+       ether_addr_equal_64bits((const u8 *)A, (const u8 *)B)
 
 static struct mac_addr null_mac_addr = { { 0, 0, 0, 0, 0, 0 } };
 static u16 ad_ticks_per_sec;
@@ -99,7 +101,7 @@ static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
 
 static const u8 lacpdu_mcast_addr[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
 
-// ================= main 802.3ad protocol functions ==================
+/* ================= main 802.3ad protocol functions ================== */
 static int ad_lacpdu_send(struct port *port);
 static int ad_marker_send(struct port *port, struct bond_marker *marker);
 static void ad_mux_machine(struct port *port);
@@ -113,13 +115,13 @@ static void ad_initialize_agg(struct aggregator *aggregator);
 static void ad_initialize_port(struct port *port, int lacp_fast);
 static void ad_enable_collecting_distributing(struct port *port);
 static void ad_disable_collecting_distributing(struct port *port);
-static void ad_marker_info_received(struct bond_marker *marker_info, struct port *port);
-static void ad_marker_response_received(struct bond_marker *marker, struct port *port);
+static void ad_marker_info_received(struct bond_marker *marker_info,
+                                   struct port *port);
+static void ad_marker_response_received(struct bond_marker *marker,
+                                       struct port *port);
 
 
-/////////////////////////////////////////////////////////////////////////////////
-// ================= api to bonding and kernel code ==================
-/////////////////////////////////////////////////////////////////////////////////
+/* ================= api to bonding and kernel code ================== */
 
 /**
  * __get_bond_by_port - get the port's bonding struct
@@ -141,26 +143,32 @@ static inline struct bonding *__get_bond_by_port(struct port *port)
  *
  * Return the aggregator of the first slave in @bond, or %NULL if it can't be
  * found.
+ * The caller must hold RCU or RTNL lock.
  */
 static inline struct aggregator *__get_first_agg(struct port *port)
 {
        struct bonding *bond = __get_bond_by_port(port);
        struct slave *first_slave;
+       struct aggregator *agg;
 
        /* If there's no bond for this port, or bond has no slaves */
        if (bond == NULL)
                return NULL;
+
        rcu_read_lock();
        first_slave = bond_first_slave_rcu(bond);
+       agg = first_slave ? &(SLAVE_AD_INFO(first_slave).aggregator) : NULL;
        rcu_read_unlock();
-       return first_slave ? &(SLAVE_AD_INFO(first_slave).aggregator) : NULL;
+
+       return agg;
 }
 
-/*
- * __agg_has_partner
+/**
+ * __agg_has_partner - see if we have a partner
+ * @agg: the agregator we're looking at
  *
  * Return nonzero if aggregator has a partner (denoted by a non-zero ether
- * address for the partner).  Return 0 if not.
+ * address for the partner). Return 0 if not.
  */
 static inline int __agg_has_partner(struct aggregator *agg)
 {
@@ -170,7 +178,6 @@ static inline int __agg_has_partner(struct aggregator *agg)
 /**
  * __disable_port - disable the port's slave
  * @port: the port we're looking at
- *
  */
 static inline void __disable_port(struct port *port)
 {
@@ -180,7 +187,6 @@ static inline void __disable_port(struct port *port)
 /**
  * __enable_port - enable the port's slave, if it's up
  * @port: the port we're looking at
- *
  */
 static inline void __enable_port(struct port *port)
 {
@@ -193,7 +199,6 @@ static inline void __enable_port(struct port *port)
 /**
  * __port_is_enabled - check if the port's slave is in active state
  * @port: the port we're looking at
- *
  */
 static inline int __port_is_enabled(struct port *port)
 {
@@ -219,7 +224,6 @@ static inline u32 __get_agg_selection_mode(struct port *port)
 /**
  * __check_agg_selection_timer - check if the selection timer has expired
  * @port: the port we're looking at
- *
  */
 static inline int __check_agg_selection_timer(struct port *port)
 {
@@ -234,7 +238,6 @@ static inline int __check_agg_selection_timer(struct port *port)
 /**
  * __get_state_machine_lock - lock the port's state machines
  * @port: the port we're looking at
- *
  */
 static inline void __get_state_machine_lock(struct port *port)
 {
@@ -244,7 +247,6 @@ static inline void __get_state_machine_lock(struct port *port)
 /**
  * __release_state_machine_lock - unlock the port's state machines
  * @port: the port we're looking at
- *
  */
 static inline void __release_state_machine_lock(struct port *port)
 {
@@ -267,10 +269,11 @@ static u16 __get_link_speed(struct port *port)
        struct slave *slave = port->slave;
        u16 speed;
 
-       /* this if covers only a special case: when the configuration starts with
-        * link down, it sets the speed to 0.
-        * This is done in spite of the fact that the e100 driver reports 0 to be
-        * compatible with MVT in the future.*/
+       /* this if covers only a special case: when the configuration starts
+        * with link down, it sets the speed to 0.
+        * This is done in spite of the fact that the e100 driver reports 0
+        * to be compatible with MVT in the future.
+        */
        if (slave->link != BOND_LINK_UP)
                speed = 0;
        else {
@@ -292,7 +295,8 @@ static u16 __get_link_speed(struct port *port)
                        break;
 
                default:
-                       speed = 0; // unknown speed value from ethtool. shouldn't happen
+                       /* unknown speed value from ethtool. shouldn't happen */
+                       speed = 0;
                        break;
                }
        }
@@ -316,8 +320,9 @@ static u8 __get_duplex(struct port *port)
 
        u8 retval;
 
-       //  handling a special case: when the configuration starts with
-       // link down, it sets the duplex to 0.
+       /* handling a special case: when the configuration starts with
+        * link down, it sets the duplex to 0.
+        */
        if (slave->link != BOND_LINK_UP)
                retval = 0x0;
        else {
@@ -341,15 +346,14 @@ static u8 __get_duplex(struct port *port)
 /**
  * __initialize_port_locks - initialize a port's STATE machine spinlock
  * @port: the slave of the port we're looking at
- *
  */
 static inline void __initialize_port_locks(struct slave *slave)
 {
-       // make sure it isn't called twice
+       /* make sure it isn't called twice */
        spin_lock_init(&(SLAVE_AD_INFO(slave).state_machine_lock));
 }
 
-//conversions
+/* Conversions */
 
 /**
  * __ad_timer_to_ticks - convert a given timer type to AD module ticks
@@ -358,39 +362,38 @@ static inline void __initialize_port_locks(struct slave *slave)
  *
  * If @timer_type is %current_while_timer, @par indicates long/short timer.
  * If @timer_type is %periodic_timer, @par is one of %FAST_PERIODIC_TIME,
- *                                                 %SLOW_PERIODIC_TIME.
+ *                                                  %SLOW_PERIODIC_TIME.
  */
 static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
 {
        u16 retval = 0; /* to silence the compiler */
 
        switch (timer_type) {
-       case AD_CURRENT_WHILE_TIMER:   // for rx machine usage
+       case AD_CURRENT_WHILE_TIMER:    /* for rx machine usage */
                if (par)
-                       retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec); // short timeout
+                       retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec);
                else
-                       retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec); // long timeout
+                       retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec);
                break;
-       case AD_ACTOR_CHURN_TIMER:          // for local churn machine
+       case AD_ACTOR_CHURN_TIMER:      /* for local churn machine */
                retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
                break;
-       case AD_PERIODIC_TIMER:     // for periodic machine
-               retval = (par*ad_ticks_per_sec); // long timeout
+       case AD_PERIODIC_TIMER:         /* for periodic machine */
+               retval = (par*ad_ticks_per_sec); /* long timeout */
                break;
-       case AD_PARTNER_CHURN_TIMER:   // for remote churn machine
+       case AD_PARTNER_CHURN_TIMER:    /* for remote churn machine */
                retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
                break;
-       case AD_WAIT_WHILE_TIMER:           // for selection machine
+       case AD_WAIT_WHILE_TIMER:       /* for selection machine */
                retval = (AD_AGGREGATE_WAIT_TIME*ad_ticks_per_sec);
                break;
        }
+
        return retval;
 }
 
 
-/////////////////////////////////////////////////////////////////////////////////
-// ================= ad_rx_machine helper functions ==================
-/////////////////////////////////////////////////////////////////////////////////
+/* ================= ad_rx_machine helper functions ================== */
 
 /**
  * __choose_matched - update a port's matched variable from a received lacpdu
@@ -417,17 +420,18 @@ static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
  */
 static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
 {
-       // check if all parameters are alike
+       /* check if all parameters are alike
+        * or this is individual link(aggregation == FALSE)
+        * then update the state machine Matched variable.
+        */
        if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
             (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
-            !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
+            MAC_ADDRESS_EQUAL(&(lacpdu->partner_system), &(port->actor_system)) &&
             (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
             (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
             ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
-           // or this is individual link(aggregation == FALSE)
            ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
                ) {
-               // update the state machine Matched variable
                port->sm_vars |= AD_PORT_MATCHED;
        } else {
                port->sm_vars &= ~AD_PORT_MATCHED;
@@ -449,7 +453,9 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
                struct port_params *partner = &port->partner_oper;
 
                __choose_matched(lacpdu, port);
-               // record the new parameter values for the partner operational
+               /* record the new parameter values for the partner
+                * operational
+                */
                partner->port_number = ntohs(lacpdu->actor_port);
                partner->port_priority = ntohs(lacpdu->actor_port_priority);
                partner->system = lacpdu->actor_system;
@@ -457,10 +463,12 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
                partner->key = ntohs(lacpdu->actor_key);
                partner->port_state = lacpdu->actor_state;
 
-               // set actor_oper_port_state.defaulted to FALSE
+               /* set actor_oper_port_state.defaulted to FALSE */
                port->actor_oper_port_state &= ~AD_STATE_DEFAULTED;
 
-               // set the partner sync. to on if the partner is sync. and the port is matched
+               /* set the partner sync. to on if the partner is sync,
+                * and the port is matched
+                */
                if ((port->sm_vars & AD_PORT_MATCHED)
                    && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION))
                        partner->port_state |= AD_STATE_SYNCHRONIZATION;
@@ -480,11 +488,11 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
 static void __record_default(struct port *port)
 {
        if (port) {
-               // record the partner admin parameters
+               /* record the partner admin parameters */
                memcpy(&port->partner_oper, &port->partner_admin,
                       sizeof(struct port_params));
 
-               // set actor_oper_port_state.defaulted to true
+               /* set actor_oper_port_state.defaulted to true */
                port->actor_oper_port_state |= AD_STATE_DEFAULTED;
        }
 }
@@ -507,14 +515,15 @@ static void __update_selected(struct lacpdu *lacpdu, struct port *port)
        if (lacpdu && port) {
                const struct port_params *partner = &port->partner_oper;
 
-               // check if any parameter is different
+               /* check if any parameter is different then
+                * update the state machine selected variable.
+                */
                if (ntohs(lacpdu->actor_port) != partner->port_number ||
                    ntohs(lacpdu->actor_port_priority) != partner->port_priority ||
-                   MAC_ADDRESS_COMPARE(&lacpdu->actor_system, &partner->system) ||
+                   !MAC_ADDRESS_EQUAL(&lacpdu->actor_system, &partner->system) ||
                    ntohs(lacpdu->actor_system_priority) != partner->system_priority ||
                    ntohs(lacpdu->actor_key) != partner->key ||
                    (lacpdu->actor_state & AD_STATE_AGGREGATION) != (partner->port_state & AD_STATE_AGGREGATION)) {
-                       // update the state machine Selected variable
                        port->sm_vars &= ~AD_PORT_SELECTED;
                }
        }
@@ -538,15 +547,16 @@ static void __update_default_selected(struct port *port)
                const struct port_params *admin = &port->partner_admin;
                const struct port_params *oper = &port->partner_oper;
 
-               // check if any parameter is different
+               /* check if any parameter is different then
+                * update the state machine selected variable.
+                */
                if (admin->port_number != oper->port_number ||
                    admin->port_priority != oper->port_priority ||
-                   MAC_ADDRESS_COMPARE(&admin->system, &oper->system) ||
+                   !MAC_ADDRESS_EQUAL(&admin->system, &oper->system) ||
                    admin->system_priority != oper->system_priority ||
                    admin->key != oper->key ||
                    (admin->port_state & AD_STATE_AGGREGATION)
                        != (oper->port_state & AD_STATE_AGGREGATION)) {
-                       // update the state machine Selected variable
                        port->sm_vars &= ~AD_PORT_SELECTED;
                }
        }
@@ -566,12 +576,14 @@ static void __update_default_selected(struct port *port)
  */
 static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
 {
-       // validate lacpdu and port
+       /* validate lacpdu and port */
        if (lacpdu && port) {
-               // check if any parameter is different
+               /* check if any parameter is different then
+                * update the port->ntt.
+                */
                if ((ntohs(lacpdu->partner_port) != port->actor_port_number) ||
                    (ntohs(lacpdu->partner_port_priority) != port->actor_port_priority) ||
-                   MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) ||
+                   !MAC_ADDRESS_EQUAL(&(lacpdu->partner_system), &(port->actor_system)) ||
                    (ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) ||
                    (ntohs(lacpdu->partner_key) != port->actor_oper_port_key) ||
                    ((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
@@ -579,42 +591,11 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
                    ((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) ||
                    ((lacpdu->partner_state & AD_STATE_AGGREGATION) != (port->actor_oper_port_state & AD_STATE_AGGREGATION))
                   ) {
-
                        port->ntt = true;
                }
        }
 }
 
-/**
- * __attach_bond_to_agg
- * @port: the port we're looking at
- *
- * Handle the attaching of the port's control parser/multiplexer and the
- * aggregator. This function does nothing since the parser/multiplexer of the
- * receive and the parser/multiplexer of the aggregator are already combined.
- */
-static void __attach_bond_to_agg(struct port *port)
-{
-       port = NULL; /* just to satisfy the compiler */
-       // This function does nothing since the parser/multiplexer of the receive
-       // and the parser/multiplexer of the aggregator are already combined
-}
-
-/**
- * __detach_bond_from_agg
- * @port: the port we're looking at
- *
- * Handle the detaching of the port's control parser/multiplexer from the
- * aggregator. This function does nothing since the parser/multiplexer of the
- * receive and the parser/multiplexer of the aggregator are already combined.
- */
-static void __detach_bond_from_agg(struct port *port)
-{
-       port = NULL; /* just to satisfy the compiler */
-       // This function does nothing since the parser/multiplexer of the receive
-       // and the parser/multiplexer of the aggregator are already combined
-}
-
 /**
  * __agg_ports_are_ready - check if all ports in an aggregator are ready
  * @aggregator: the aggregator we're looking at
@@ -626,7 +607,9 @@ static int __agg_ports_are_ready(struct aggregator *aggregator)
        int retval = 1;
 
        if (aggregator) {
-               // scan all ports in this aggregator to verfy if they are all ready
+               /* scan all ports in this aggregator to verfy if they are
+                * all ready.
+                */
                for (port = aggregator->lag_ports;
                     port;
                     port = port->next_port_in_aggregator) {
@@ -686,7 +669,7 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
                        bandwidth = aggregator->num_of_ports * 10000;
                        break;
                default:
-                       bandwidth = 0; /*to silence the compiler ....*/
+                       bandwidth = 0; /* to silence the compiler */
                }
        }
        return bandwidth;
@@ -696,6 +679,7 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
  * __get_active_agg - get the current active aggregator
  * @aggregator: the aggregator we're looking at
  *
+ * Caller must hold RCU lock.
  */
 static struct aggregator *__get_active_agg(struct aggregator *aggregator)
 {
@@ -703,13 +687,9 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator)
        struct list_head *iter;
        struct slave *slave;
 
-       rcu_read_lock();
        bond_for_each_slave_rcu(bond, slave, iter)
-               if (SLAVE_AD_INFO(slave).aggregator.is_active) {
-                       rcu_read_unlock();
+               if (SLAVE_AD_INFO(slave).aggregator.is_active)
                        return &(SLAVE_AD_INFO(slave).aggregator);
-               }
-       rcu_read_unlock();
 
        return NULL;
 }
@@ -717,15 +697,14 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator)
 /**
  * __update_lacpdu_from_port - update a port's lacpdu fields
  * @port: the port we're looking at
- *
  */
 static inline void __update_lacpdu_from_port(struct port *port)
 {
        struct lacpdu *lacpdu = &port->lacpdu;
        const struct port_params *partner = &port->partner_oper;
 
-       /* update current actual Actor parameters */
-       /* lacpdu->subtype                   initialized
+       /* update current actual Actor parameters
+        * lacpdu->subtype                   initialized
         * lacpdu->version_number            initialized
         * lacpdu->tlv_type_actor_info       initialized
         * lacpdu->actor_information_length  initialized
@@ -761,9 +740,7 @@ static inline void __update_lacpdu_from_port(struct port *port)
         */
 }
 
-//////////////////////////////////////////////////////////////////////////////////////
-// ================= main 802.3ad protocol code ======================================
-//////////////////////////////////////////////////////////////////////////////////////
+/* ================= main 802.3ad protocol code ========================= */
 
 /**
  * ad_lacpdu_send - send out a lacpdu packet on a given port
@@ -793,11 +770,12 @@ static int ad_lacpdu_send(struct port *port)
 
        memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
        /* Note: source address is set to be the member's PERMANENT address,
-          because we use it to identify loopback lacpdus in receive. */
+        * because we use it to identify loopback lacpdus in receive.
+        */
        memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
        lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU;
 
-       lacpdu_header->lacpdu = port->lacpdu; // struct copy
+       lacpdu_header->lacpdu = port->lacpdu;
 
        dev_queue_xmit(skb);
 
@@ -834,11 +812,12 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
 
        memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
        /* Note: source address is set to be the member's PERMANENT address,
-          because we use it to identify loopback MARKERs in receive. */
+        * because we use it to identify loopback MARKERs in receive.
+        */
        memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
        marker_header->hdr.h_proto = PKT_TYPE_LACPDU;
 
-       marker_header->marker = *marker; // struct copy
+       marker_header->marker = *marker;
 
        dev_queue_xmit(skb);
 
@@ -848,72 +827,90 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
 /**
  * ad_mux_machine - handle a port's mux state machine
  * @port: the port we're looking at
- *
  */
 static void ad_mux_machine(struct port *port)
 {
        mux_states_t last_state;
 
-       // keep current State Machine state to compare later if it was changed
+       /* keep current State Machine state to compare later if it was
+        * changed
+        */
        last_state = port->sm_mux_state;
 
        if (port->sm_vars & AD_PORT_BEGIN) {
-               port->sm_mux_state = AD_MUX_DETACHED;            // next state
+               port->sm_mux_state = AD_MUX_DETACHED;
        } else {
                switch (port->sm_mux_state) {
                case AD_MUX_DETACHED:
                        if ((port->sm_vars & AD_PORT_SELECTED)
                            || (port->sm_vars & AD_PORT_STANDBY))
                                /* if SELECTED or STANDBY */
-                               port->sm_mux_state = AD_MUX_WAITING; // next state
+                               port->sm_mux_state = AD_MUX_WAITING;
                        break;
                case AD_MUX_WAITING:
-                       // if SELECTED == FALSE return to DETACH state
-                       if (!(port->sm_vars & AD_PORT_SELECTED)) { // if UNSELECTED
+                       /* if SELECTED == FALSE return to DETACH state */
+                       if (!(port->sm_vars & AD_PORT_SELECTED)) {
                                port->sm_vars &= ~AD_PORT_READY_N;
-                               // in order to withhold the Selection Logic to check all ports READY_N value
-                               // every callback cycle to update ready variable, we check READY_N and update READY here
+                               /* in order to withhold the Selection Logic to
+                                * check all ports READY_N value every callback
+                                * cycle to update ready variable, we check
+                                * READY_N and update READY here
+                                */
                                __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
-                               port->sm_mux_state = AD_MUX_DETACHED;    // next state
+                               port->sm_mux_state = AD_MUX_DETACHED;
                                break;
                        }
 
-                       // check if the wait_while_timer expired
+                       /* check if the wait_while_timer expired */
                        if (port->sm_mux_timer_counter
                            && !(--port->sm_mux_timer_counter))
                                port->sm_vars |= AD_PORT_READY_N;
 
-                       // in order to withhold the selection logic to check all ports READY_N value
-                       // every callback cycle to update ready variable, we check READY_N and update READY here
+                       /* in order to withhold the selection logic to check
+                        * all ports READY_N value every callback cycle to
+                        * update ready variable, we check READY_N and update
+                        * READY here
+                        */
                        __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
 
-                       // if the wait_while_timer expired, and the port is in READY state, move to ATTACHED state
+                       /* if the wait_while_timer expired, and the port is
+                        * in READY state, move to ATTACHED state
+                        */
                        if ((port->sm_vars & AD_PORT_READY)
                            && !port->sm_mux_timer_counter)
-                               port->sm_mux_state = AD_MUX_ATTACHED;    // next state
+                               port->sm_mux_state = AD_MUX_ATTACHED;
                        break;
                case AD_MUX_ATTACHED:
-                       // check also if agg_select_timer expired(so the edable port will take place only after this timer)
-                       if ((port->sm_vars & AD_PORT_SELECTED) && (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) && !__check_agg_selection_timer(port)) {
-                               port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;// next state
-                       } else if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) {    // if UNSELECTED or STANDBY
+                       /* check also if agg_select_timer expired (so the
+                        * edable port will take place only after this timer)
+                        */
+                       if ((port->sm_vars & AD_PORT_SELECTED) &&
+                           (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) &&
+                           !__check_agg_selection_timer(port)) {
+                               port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;
+                       } else if (!(port->sm_vars & AD_PORT_SELECTED) ||
+                                  (port->sm_vars & AD_PORT_STANDBY)) {
+                               /* if UNSELECTED or STANDBY */
                                port->sm_vars &= ~AD_PORT_READY_N;
-                               // in order to withhold the selection logic to check all ports READY_N value
-                               // every callback cycle to update ready variable, we check READY_N and update READY here
+                               /* in order to withhold the selection logic to
+                                * check all ports READY_N value every callback
+                                * cycle to update ready variable, we check
+                                * READY_N and update READY here
+                                */
                                __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
-                               port->sm_mux_state = AD_MUX_DETACHED;// next state
+                               port->sm_mux_state = AD_MUX_DETACHED;
                        }
                        break;
                case AD_MUX_COLLECTING_DISTRIBUTING:
-                       if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY) ||
-                           !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION)
-                          ) {
-                               port->sm_mux_state = AD_MUX_ATTACHED;// next state
-
+                       if (!(port->sm_vars & AD_PORT_SELECTED) ||
+                           (port->sm_vars & AD_PORT_STANDBY) ||
+                           !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION)) {
+                               port->sm_mux_state = AD_MUX_ATTACHED;
                        } else {
-                               // if port state hasn't changed make
-                               // sure that a collecting distributing
-                               // port in an active aggregator is enabled
+                               /* if port state hasn't changed make
+                                * sure that a collecting distributing
+                                * port in an active aggregator is enabled
+                                */
                                if (port->aggregator &&
                                    port->aggregator->is_active &&
                                    !__port_is_enabled(port)) {
@@ -922,19 +919,18 @@ static void ad_mux_machine(struct port *port)
                                }
                        }
                        break;
-               default:    //to silence the compiler
+               default:
                        break;
                }
        }
 
-       // check if the state machine was changed
+       /* check if the state machine was changed */
        if (port->sm_mux_state != last_state) {
                pr_debug("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n",
                         port->actor_port_number, last_state,
                         port->sm_mux_state);
                switch (port->sm_mux_state) {
                case AD_MUX_DETACHED:
-                       __detach_bond_from_agg(port);
                        port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
                        ad_disable_collecting_distributing(port);
                        port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
@@ -945,7 +941,6 @@ static void ad_mux_machine(struct port *port)
                        port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0);
                        break;
                case AD_MUX_ATTACHED:
-                       __attach_bond_to_agg(port);
                        port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION;
                        port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
                        port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
@@ -958,7 +953,7 @@ static void ad_mux_machine(struct port *port)
                        ad_enable_collecting_distributing(port);
                        port->ntt = true;
                        break;
-               default:    //to silence the compiler
+               default:
                        break;
                }
        }
@@ -977,59 +972,63 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
 {
        rx_states_t last_state;
 
-       // keep current State Machine state to compare later if it was changed
+       /* keep current State Machine state to compare later if it was
+        * changed
+        */
        last_state = port->sm_rx_state;
 
-       // check if state machine should change state
-       // first, check if port was reinitialized
+       /* check if state machine should change state */
+
+       /* first, check if port was reinitialized */
        if (port->sm_vars & AD_PORT_BEGIN)
-               /* next state */
                port->sm_rx_state = AD_RX_INITIALIZE;
-       // check if port is not enabled
+       /* check if port is not enabled */
        else if (!(port->sm_vars & AD_PORT_BEGIN)
                 && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED))
-               /* next state */
                port->sm_rx_state = AD_RX_PORT_DISABLED;
-       // check if new lacpdu arrived
-       else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT))) {
-               port->sm_rx_timer_counter = 0; // zero timer
+       /* check if new lacpdu arrived */
+       else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) ||
+                (port->sm_rx_state == AD_RX_DEFAULTED) ||
+                (port->sm_rx_state == AD_RX_CURRENT))) {
+               port->sm_rx_timer_counter = 0;
                port->sm_rx_state = AD_RX_CURRENT;
        } else {
-               // if timer is on, and if it is expired
-               if (port->sm_rx_timer_counter && !(--port->sm_rx_timer_counter)) {
+               /* if timer is on, and if it is expired */
+               if (port->sm_rx_timer_counter &&
+                   !(--port->sm_rx_timer_counter)) {
                        switch (port->sm_rx_state) {
                        case AD_RX_EXPIRED:
-                               port->sm_rx_state = AD_RX_DEFAULTED;            // next state
+                               port->sm_rx_state = AD_RX_DEFAULTED;
                                break;
                        case AD_RX_CURRENT:
-                               port->sm_rx_state = AD_RX_EXPIRED;          // next state
+                               port->sm_rx_state = AD_RX_EXPIRED;
                                break;
-                       default:    //to silence the compiler
+                       default:
                                break;
                        }
                } else {
-                       // if no lacpdu arrived and no timer is on
+                       /* if no lacpdu arrived and no timer is on */
                        switch (port->sm_rx_state) {
                        case AD_RX_PORT_DISABLED:
                                if (port->sm_vars & AD_PORT_MOVED)
-                                       port->sm_rx_state = AD_RX_INITIALIZE;       // next state
+                                       port->sm_rx_state = AD_RX_INITIALIZE;
                                else if (port->is_enabled
                                         && (port->sm_vars
                                             & AD_PORT_LACP_ENABLED))
-                                       port->sm_rx_state = AD_RX_EXPIRED;      // next state
+                                       port->sm_rx_state = AD_RX_EXPIRED;
                                else if (port->is_enabled
                                         && ((port->sm_vars
                                              & AD_PORT_LACP_ENABLED) == 0))
-                                       port->sm_rx_state = AD_RX_LACP_DISABLED;    // next state
+                                       port->sm_rx_state = AD_RX_LACP_DISABLED;
                                break;
-                       default:    //to silence the compiler
+                       default:
                                break;
 
                        }
                }
        }
 
-       // check if the State machine was changed or new lacpdu arrived
+       /* check if the State machine was changed or new lacpdu arrived */
        if ((port->sm_rx_state != last_state) || (lacpdu)) {
                pr_debug("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n",
                         port->actor_port_number, last_state,
@@ -1044,10 +1043,9 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
                        __record_default(port);
                        port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
                        port->sm_vars &= ~AD_PORT_MOVED;
-                       port->sm_rx_state = AD_RX_PORT_DISABLED;        // next state
-
-                       /*- Fall Through -*/
+                       port->sm_rx_state = AD_RX_PORT_DISABLED;
 
+                       /* Fall Through */
                case AD_RX_PORT_DISABLED:
                        port->sm_vars &= ~AD_PORT_MATCHED;
                        break;
@@ -1059,13 +1057,15 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
                        port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
                        break;
                case AD_RX_EXPIRED:
-                       //Reset of the Synchronization flag. (Standard 43.4.12)
-                       //This reset cause to disable this port in the COLLECTING_DISTRIBUTING state of the
-                       //mux machine in case of EXPIRED even if LINK_DOWN didn't arrive for the port.
+                       /* Reset of the Synchronization flag (Standard 43.4.12)
+                        * This reset cause to disable this port in the
+                        * COLLECTING_DISTRIBUTING state of the mux machine in
+                        * case of EXPIRED even if LINK_DOWN didn't arrive for
+                        * the port.
+                        */
                        port->partner_oper.port_state &= ~AD_STATE_SYNCHRONIZATION;
                        port->sm_vars &= ~AD_PORT_MATCHED;
-                       port->partner_oper.port_state |=
-                               AD_STATE_LACP_ACTIVITY;
+                       port->partner_oper.port_state |= AD_STATE_LACP_ACTIVITY;
                        port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
                        port->actor_oper_port_state |= AD_STATE_EXPIRED;
                        break;
@@ -1076,12 +1076,12 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
                        port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
                        break;
                case AD_RX_CURRENT:
-                       // detect loopback situation
-                       if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
-                               // INFO_RECEIVED_LOOPBACK_FRAMES
-                               pr_err("%s: An illegal loopback occurred on adapter (%s).\n"
-                                      "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
-                                      port->slave->bond->dev->name, port->slave->dev->name);
+                       /* detect loopback situation */
+                       if (MAC_ADDRESS_EQUAL(&(lacpdu->actor_system),
+                                             &(port->actor_system))) {
+                               pr_err("%s: An illegal loopback occurred on adapter (%s).\nCheck the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
+                                      port->slave->bond->dev->name,
+                                      port->slave->dev->name);
                                return;
                        }
                        __update_selected(lacpdu, port);
@@ -1090,7 +1090,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
                        port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT));
                        port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
                        break;
-               default:    //to silence the compiler
+               default:
                        break;
                }
        }
@@ -1099,13 +1099,14 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
 /**
  * ad_tx_machine - handle a port's tx state machine
  * @port: the port we're looking at
- *
  */
 static void ad_tx_machine(struct port *port)
 {
-       // check if tx timer expired, to verify that we do not send more than 3 packets per second
+       /* check if tx timer expired, to verify that we do not send more than
+        * 3 packets per second
+        */
        if (port->sm_tx_timer_counter && !(--port->sm_tx_timer_counter)) {
-               // check if there is something to send
+               /* check if there is something to send */
                if (port->ntt && (port->sm_vars & AD_PORT_LACP_ENABLED)) {
                        __update_lacpdu_from_port(port);
 
@@ -1113,14 +1114,16 @@ static void ad_tx_machine(struct port *port)
                                pr_debug("Sent LACPDU on port %d\n",
                                         port->actor_port_number);
 
-                               /* mark ntt as false, so it will not be sent again until
-                                  demanded */
+                               /* mark ntt as false, so it will not be sent
+                                * again until demanded
+                                */
                                port->ntt = false;
                        }
                }
-               // restart tx timer(to verify that we will not exceed AD_MAX_TX_IN_SECOND
-               port->sm_tx_timer_counter =
-                       ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
+               /* restart tx timer(to verify that we will not exceed
+                * AD_MAX_TX_IN_SECOND
+                */
+               port->sm_tx_timer_counter = ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
        }
 }
 
@@ -1134,76 +1137,79 @@ static void ad_periodic_machine(struct port *port)
 {
        periodic_states_t last_state;
 
-       // keep current state machine state to compare later if it was changed
+       /* keep current state machine state to compare later if it was changed */
        last_state = port->sm_periodic_state;
 
-       // check if port was reinitialized
+       /* check if port was reinitialized */
        if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
            (!(port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & AD_STATE_LACP_ACTIVITY))
           ) {
-               port->sm_periodic_state = AD_NO_PERIODIC;            // next state
+               port->sm_periodic_state = AD_NO_PERIODIC;
        }
-       // check if state machine should change state
+       /* check if state machine should change state */
        else if (port->sm_periodic_timer_counter) {
-               // check if periodic state machine expired
+               /* check if periodic state machine expired */
                if (!(--port->sm_periodic_timer_counter)) {
-                       // if expired then do tx
-                       port->sm_periodic_state = AD_PERIODIC_TX;    // next state
+                       /* if expired then do tx */
+                       port->sm_periodic_state = AD_PERIODIC_TX;
                } else {
-                       // If not expired, check if there is some new timeout parameter from the partner state
+                       /* If not expired, check if there is some new timeout
+                        * parameter from the partner state
+                        */
                        switch (port->sm_periodic_state) {
                        case AD_FAST_PERIODIC:
                                if (!(port->partner_oper.port_state
                                      & AD_STATE_LACP_TIMEOUT))
-                                       port->sm_periodic_state = AD_SLOW_PERIODIC;  // next state
+                                       port->sm_periodic_state = AD_SLOW_PERIODIC;
                                break;
                        case AD_SLOW_PERIODIC:
                                if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
-                                       // stop current timer
                                        port->sm_periodic_timer_counter = 0;
-                                       port->sm_periodic_state = AD_PERIODIC_TX;        // next state
+                                       port->sm_periodic_state = AD_PERIODIC_TX;
                                }
                                break;
-                       default:    //to silence the compiler
+                       default:
                                break;
                        }
                }
        } else {
                switch (port->sm_periodic_state) {
                case AD_NO_PERIODIC:
-                       port->sm_periodic_state = AD_FAST_PERIODIC;      // next state
+                       port->sm_periodic_state = AD_FAST_PERIODIC;
                        break;
                case AD_PERIODIC_TX:
-                       if (!(port->partner_oper.port_state
-                             & AD_STATE_LACP_TIMEOUT))
-                               port->sm_periodic_state = AD_SLOW_PERIODIC;  // next state
+                       if (!(port->partner_oper.port_state &
+                           AD_STATE_LACP_TIMEOUT))
+                               port->sm_periodic_state = AD_SLOW_PERIODIC;
                        else
-                               port->sm_periodic_state = AD_FAST_PERIODIC;  // next state
+                               port->sm_periodic_state = AD_FAST_PERIODIC;
                        break;
-               default:    //to silence the compiler
+               default:
                        break;
                }
        }
 
-       // check if the state machine was changed
+       /* check if the state machine was changed */
        if (port->sm_periodic_state != last_state) {
                pr_debug("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n",
                         port->actor_port_number, last_state,
                         port->sm_periodic_state);
                switch (port->sm_periodic_state) {
                case AD_NO_PERIODIC:
-                       port->sm_periodic_timer_counter = 0;       // zero timer
+                       port->sm_periodic_timer_counter = 0;
                        break;
                case AD_FAST_PERIODIC:
-                       port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_FAST_PERIODIC_TIME))-1; // decrement 1 tick we lost in the PERIODIC_TX cycle
+                       /* decrement 1 tick we lost in the PERIODIC_TX cycle */
+                       port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_FAST_PERIODIC_TIME))-1;
                        break;
                case AD_SLOW_PERIODIC:
-                       port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_SLOW_PERIODIC_TIME))-1; // decrement 1 tick we lost in the PERIODIC_TX cycle
+                       /* decrement 1 tick we lost in the PERIODIC_TX cycle */
+                       port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_SLOW_PERIODIC_TIME))-1;
                        break;
                case AD_PERIODIC_TX:
                        port->ntt = true;
                        break;
-               default:    //to silence the compiler
+               default:
                        break;
                }
        }
@@ -1226,30 +1232,38 @@ static void ad_port_selection_logic(struct port *port)
        struct slave *slave;
        int found = 0;
 
-       // if the port is already Selected, do nothing
+       /* if the port is already Selected, do nothing */
        if (port->sm_vars & AD_PORT_SELECTED)
                return;
 
        bond = __get_bond_by_port(port);
 
-       // if the port is connected to other aggregator, detach it
+       /* if the port is connected to other aggregator, detach it */
        if (port->aggregator) {
-               // detach the port from its former aggregator
+               /* detach the port from its former aggregator */
                temp_aggregator = port->aggregator;
                for (curr_port = temp_aggregator->lag_ports; curr_port;
                     last_port = curr_port,
-                            curr_port = curr_port->next_port_in_aggregator) {
+                    curr_port = curr_port->next_port_in_aggregator) {
                        if (curr_port == port) {
                                temp_aggregator->num_of_ports--;
-                               if (!last_port) {// if it is the first port attached to the aggregator
+                               /* if it is the first port attached to the
+                                * aggregator
+                                */
+                               if (!last_port) {
                                        temp_aggregator->lag_ports =
                                                port->next_port_in_aggregator;
-                               } else {// not the first port attached to the aggregator
+                               } else {
+                                       /* not the first port attached to the
+                                        * aggregator
+                                        */
                                        last_port->next_port_in_aggregator =
                                                port->next_port_in_aggregator;
                                }
 
-                               // clear the port's relations to this aggregator
+                               /* clear the port's relations to this
+                                * aggregator
+                                */
                                port->aggregator = NULL;
                                port->next_port_in_aggregator = NULL;
                                port->actor_port_aggregator_identifier = 0;
@@ -1257,41 +1271,46 @@ static void ad_port_selection_logic(struct port *port)
                                pr_debug("Port %d left LAG %d\n",
                                         port->actor_port_number,
                                         temp_aggregator->aggregator_identifier);
-                               // if the aggregator is empty, clear its parameters, and set it ready to be attached
+                               /* if the aggregator is empty, clear its
+                                * parameters, and set it ready to be attached
+                                */
                                if (!temp_aggregator->lag_ports)
                                        ad_clear_agg(temp_aggregator);
                                break;
                        }
                }
-               if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
-                       pr_warning("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
-                                  port->slave->bond->dev->name,
-                                  port->actor_port_number,
-                                  port->slave->dev->name,
-                                  port->aggregator->aggregator_identifier);
+               if (!curr_port) {
+                       /* meaning: the port was related to an aggregator
+                        * but was not on the aggregator port list
+                        */
+                       pr_warn("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
+                               port->slave->bond->dev->name,
+                               port->actor_port_number,
+                               port->slave->dev->name,
+                               port->aggregator->aggregator_identifier);
                }
        }
-       // search on all aggregators for a suitable aggregator for this port
+       /* search on all aggregators for a suitable aggregator for this port */
        bond_for_each_slave(bond, slave, iter) {
                aggregator = &(SLAVE_AD_INFO(slave).aggregator);
 
-               // keep a free aggregator for later use(if needed)
+               /* keep a free aggregator for later use(if needed) */
                if (!aggregator->lag_ports) {
                        if (!free_aggregator)
                                free_aggregator = aggregator;
                        continue;
                }
-               // check if current aggregator suits us
-               if (((aggregator->actor_oper_aggregator_key == port->actor_oper_port_key) && // if all parameters match AND
-                    !MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(port->partner_oper.system)) &&
+               /* check if current aggregator suits us */
+               if (((aggregator->actor_oper_aggregator_key == port->actor_oper_port_key) && /* if all parameters match AND */
+                    MAC_ADDRESS_EQUAL(&(aggregator->partner_system), &(port->partner_oper.system)) &&
                     (aggregator->partner_system_priority == port->partner_oper.system_priority) &&
                     (aggregator->partner_oper_aggregator_key == port->partner_oper.key)
                    ) &&
-                   ((MAC_ADDRESS_COMPARE(&(port->partner_oper.system), &(null_mac_addr)) && // partner answers
-                     !aggregator->is_individual)  // but is not individual OR
+                   ((!MAC_ADDRESS_EQUAL(&(port->partner_oper.system), &(null_mac_addr)) && /* partner answers */
+                     !aggregator->is_individual)  /* but is not individual OR */
                    )
                   ) {
-                       // attach to the founded aggregator
+                       /* attach to the founded aggregator */
                        port->aggregator = aggregator;
                        port->actor_port_aggregator_identifier =
                                port->aggregator->aggregator_identifier;
@@ -1302,23 +1321,26 @@ static void ad_port_selection_logic(struct port *port)
                                 port->actor_port_number,
                                 port->aggregator->aggregator_identifier);
 
-                       // mark this port as selected
+                       /* mark this port as selected */
                        port->sm_vars |= AD_PORT_SELECTED;
                        found = 1;
                        break;
                }
        }
 
-       // the port couldn't find an aggregator - attach it to a new aggregator
+       /* the port couldn't find an aggregator - attach it to a new
+        * aggregator
+        */
        if (!found) {
                if (free_aggregator) {
-                       // assign port a new aggregator
+                       /* assign port a new aggregator */
                        port->aggregator = free_aggregator;
                        port->actor_port_aggregator_identifier =
                                port->aggregator->aggregator_identifier;
 
-                       // update the new aggregator's parameters
-                       // if port was responsed from the end-user
+                       /* update the new aggregator's parameters
+                        * if port was responsed from the end-user
+                        */
                        if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)
                                /* if port is full duplex */
                                port->aggregator->is_individual = false;
@@ -1337,7 +1359,7 @@ static void ad_port_selection_logic(struct port *port)
                        port->aggregator->lag_ports = port;
                        port->aggregator->num_of_ports++;
 
-                       // mark this port as selected
+                       /* mark this port as selected */
                        port->sm_vars |= AD_PORT_SELECTED;
 
                        pr_debug("Port %d joined LAG %d(new LAG)\n",
@@ -1349,23 +1371,24 @@ static void ad_port_selection_logic(struct port *port)
                               port->actor_port_number, port->slave->dev->name);
                }
        }
-       // if all aggregator's ports are READY_N == TRUE, set ready=TRUE in all aggregator's ports
-       // else set ready=FALSE in all aggregator's ports
-       __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
+       /* if all aggregator's ports are READY_N == TRUE, set ready=TRUE
+        * in all aggregator's ports, else set ready=FALSE in all
+        * aggregator's ports
+        */
+       __set_agg_ports_ready(port->aggregator,
+                             __agg_ports_are_ready(port->aggregator));
 
        aggregator = __get_first_agg(port);
        ad_agg_selection_logic(aggregator);
 }
 
-/*
- * Decide if "agg" is a better choice for the new active aggregator that
+/* Decide if "agg" is a better choice for the new active aggregator that
  * the current best, according to the ad_select policy.
  */
 static struct aggregator *ad_agg_selection_test(struct aggregator *best,
                                                struct aggregator *curr)
 {
-       /*
-        * 0. If no best, select current.
+       /* 0. If no best, select current.
         *
         * 1. If the current agg is not individual, and the best is
         *    individual, select current.
@@ -1421,9 +1444,9 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best,
                break;
 
        default:
-               pr_warning("%s: Impossible agg select mode %d\n",
-                          curr->slave->bond->dev->name,
-                          __get_agg_selection_mode(curr->lag_ports));
+               pr_warn("%s: Impossible agg select mode %d\n",
+                       curr->slave->bond->dev->name,
+                       __get_agg_selection_mode(curr->lag_ports));
                break;
        }
 
@@ -1433,10 +1456,12 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best,
 static int agg_device_up(const struct aggregator *agg)
 {
        struct port *port = agg->lag_ports;
+
        if (!port)
                return 0;
-       return (netif_running(port->slave->dev) &&
-               netif_carrier_ok(port->slave->dev));
+
+       return netif_running(port->slave->dev) &&
+              netif_carrier_ok(port->slave->dev);
 }
 
 /**
@@ -1472,11 +1497,11 @@ static void ad_agg_selection_logic(struct aggregator *agg)
        struct slave *slave;
        struct port *port;
 
+       rcu_read_lock();
        origin = agg;
        active = __get_active_agg(agg);
        best = (active && agg_device_up(active)) ? active : NULL;
 
-       rcu_read_lock();
        bond_for_each_slave_rcu(bond, slave, iter) {
                agg = &(SLAVE_AD_INFO(slave).aggregator);
 
@@ -1488,8 +1513,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
 
        if (best &&
            __get_agg_selection_mode(best->lag_ports) == BOND_AD_STABLE) {
-               /*
-                * For the STABLE policy, don't replace the old active
+               /* For the STABLE policy, don't replace the old active
                 * aggregator if it's still active (it has an answering
                 * partner) or if both the best and active don't have an
                 * answering partner.
@@ -1497,7 +1521,8 @@ static void ad_agg_selection_logic(struct aggregator *agg)
                if (active && active->lag_ports &&
                    active->lag_ports->is_enabled &&
                    (__agg_has_partner(active) ||
-                    (!__agg_has_partner(active) && !__agg_has_partner(best)))) {
+                    (!__agg_has_partner(active) &&
+                    !__agg_has_partner(best)))) {
                        if (!(!active->actor_oper_aggregator_key &&
                              best->actor_oper_aggregator_key)) {
                                best = NULL;
@@ -1534,7 +1559,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
 
                /* check if any partner replys */
                if (best->is_individual) {
-                       pr_warning("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
+                       pr_warn("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
                                best->slave ?
                                best->slave->bond->dev->name : "NULL");
                }
@@ -1548,7 +1573,9 @@ static void ad_agg_selection_logic(struct aggregator *agg)
                         best->partner_oper_aggregator_key,
                         best->is_individual, best->is_active);
 
-               /* disable the ports that were related to the former active_aggregator */
+               /* disable the ports that were related to the former
+                * active_aggregator
+                */
                if (active) {
                        for (port = active->lag_ports; port;
                             port = port->next_port_in_aggregator) {
@@ -1557,8 +1584,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
                }
        }
 
-       /*
-        * if the selected aggregator is of join individuals
+       /* if the selected aggregator is of join individuals
         * (partner_system is NULL), enable their ports
         */
        active = __get_active_agg(origin);
@@ -1580,7 +1606,6 @@ static void ad_agg_selection_logic(struct aggregator *agg)
 /**
  * ad_clear_agg - clear a given aggregator's parameters
  * @aggregator: the aggregator we're looking at
- *
  */
 static void ad_clear_agg(struct aggregator *aggregator)
 {
@@ -1604,7 +1629,6 @@ static void ad_clear_agg(struct aggregator *aggregator)
 /**
  * ad_initialize_agg - initialize a given aggregator's parameters
  * @aggregator: the aggregator we're looking at
- *
  */
 static void ad_initialize_agg(struct aggregator *aggregator)
 {
@@ -1621,7 +1645,6 @@ static void ad_initialize_agg(struct aggregator *aggregator)
  * ad_initialize_port - initialize a given port's parameters
  * @aggregator: the aggregator we're looking at
  * @lacp_fast: boolean. whether fast periodic should be used
- *
  */
 static void ad_initialize_port(struct port *port, int lacp_fast)
 {
@@ -1653,8 +1676,10 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
                port->ntt = false;
                port->actor_admin_port_key = 1;
                port->actor_oper_port_key  = 1;
-               port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
-               port->actor_oper_port_state  = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
+               port->actor_admin_port_state = AD_STATE_AGGREGATION |
+                                              AD_STATE_LACP_ACTIVITY;
+               port->actor_oper_port_state  = AD_STATE_AGGREGATION |
+                                              AD_STATE_LACP_ACTIVITY;
 
                if (lacp_fast)
                        port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
@@ -1663,7 +1688,7 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
                memcpy(&port->partner_oper, &tmpl, sizeof(tmpl));
 
                port->is_enabled = true;
-               // ****** private parameters ******
+               /* private parameters */
                port->sm_vars = 0x3;
                port->sm_rx_state = 0;
                port->sm_rx_timer_counter = 0;
@@ -1701,11 +1726,12 @@ static void ad_enable_collecting_distributing(struct port *port)
 /**
  * ad_disable_collecting_distributing - disable a port's transmit/receive
  * @port: the port we're looking at
- *
  */
 static void ad_disable_collecting_distributing(struct port *port)
 {
-       if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
+       if (port->aggregator &&
+           !MAC_ADDRESS_EQUAL(&(port->aggregator->partner_system),
+                              &(null_mac_addr))) {
                pr_debug("Disabling port %d(LAG %d)\n",
                         port->actor_port_number,
                         port->aggregator->aggregator_identifier);
@@ -1713,66 +1739,22 @@ static void ad_disable_collecting_distributing(struct port *port)
        }
 }
 
-#if 0
-/**
- * ad_marker_info_send - send a marker information frame
- * @port: the port we're looking at
- *
- * This function does nothing since we decided not to implement send and handle
- * response for marker PDU's, in this stage, but only to respond to marker
- * information.
- */
-static void ad_marker_info_send(struct port *port)
-{
-       struct bond_marker marker;
-       u16 index;
-
-       // fill the marker PDU with the appropriate values
-       marker.subtype = 0x02;
-       marker.version_number = 0x01;
-       marker.tlv_type = AD_MARKER_INFORMATION_SUBTYPE;
-       marker.marker_length = 0x16;
-       // convert requester_port to Big Endian
-       marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |((u16)(port->actor_port_number & 0xFF00) >> 8));
-       marker.requester_system = port->actor_system;
-       // convert requester_port(u32) to Big Endian
-       marker.requester_transaction_id =
-               (((++port->transaction_id & 0xFF) << 24)
-                | ((port->transaction_id & 0xFF00) << 8)
-                | ((port->transaction_id & 0xFF0000) >> 8)
-                | ((port->transaction_id & 0xFF000000) >> 24));
-       marker.pad = 0;
-       marker.tlv_type_terminator = 0x00;
-       marker.terminator_length = 0x00;
-       for (index = 0; index < 90; index++)
-               marker.reserved_90[index] = 0;
-
-       // send the marker information
-       if (ad_marker_send(port, &marker) >= 0) {
-               pr_debug("Sent Marker Information on port %d\n",
-                        port->actor_port_number);
-       }
-}
-#endif
-
 /**
  * ad_marker_info_received - handle receive of a Marker information frame
  * @marker_info: Marker info received
  * @port: the port we're looking at
- *
  */
 static void ad_marker_info_received(struct bond_marker *marker_info,
        struct port *port)
 {
        struct bond_marker marker;
 
-       // copy the received marker data to the response marker
-       //marker = *marker_info;
+       /* copy the received marker data to the response marker */
        memcpy(&marker, marker_info, sizeof(struct bond_marker));
-       // change the marker subtype to marker response
+       /* change the marker subtype to marker response */
        marker.tlv_type = AD_MARKER_RESPONSE_SUBTYPE;
-       // send the marker response
 
+       /* send the marker response */
        if (ad_marker_send(port, &marker) >= 0) {
                pr_debug("Sent Marker Response on port %d\n",
                         port->actor_port_number);
@@ -1789,22 +1771,21 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
  * information.
  */
 static void ad_marker_response_received(struct bond_marker *marker,
-       struct port *port)
+                                       struct port *port)
 {
-       marker = NULL; /* just to satisfy the compiler */
-       port = NULL;  /* just to satisfy the compiler */
-       // DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW
+       marker = NULL;
+       port = NULL;
+       /* DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW */
 }
 
-//////////////////////////////////////////////////////////////////////////////////////
-// ================= AD exported functions to the main bonding code ==================
-//////////////////////////////////////////////////////////////////////////////////////
+/* ========= AD exported functions to the main bonding code ========= */
 
-// Check aggregators status in team every T seconds
+/* Check aggregators status in team every T seconds */
 #define AD_AGGREGATOR_SELECTION_TIMER  8
 
-/*
- * bond_3ad_initiate_agg_selection(struct bonding *bond)
+/**
+ * bond_3ad_initiate_agg_selection - initate aggregator selection
+ * @bond: bonding struct
  *
  * Set the aggregation selection timer, to initiate an agg selection in
  * the very near future.  Called during first initialization, and during
@@ -1826,8 +1807,8 @@ static u16 aggregator_identifier;
  */
 void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
 {
-       // check that the bond is not initialized yet
-       if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr),
+       /* check that the bond is not initialized yet */
+       if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr),
                                bond->dev->dev_addr)) {
 
                aggregator_identifier = 0;
@@ -1835,7 +1816,9 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
                BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
                BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
 
-               // initialize how many times this module is called in one second(should be about every 100ms)
+               /* initialize how many times this module is called in one
+                * second (should be about every 100ms)
+                */
                ad_ticks_per_sec = tick_resolution;
 
                bond_3ad_initiate_agg_selection(bond,
@@ -1851,22 +1834,16 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
  * Returns:   0 on success
  *          < 0 on error
  */
-int bond_3ad_bind_slave(struct slave *slave)
+void bond_3ad_bind_slave(struct slave *slave)
 {
        struct bonding *bond = bond_get_bond_by_slave(slave);
        struct port *port;
        struct aggregator *aggregator;
 
-       if (bond == NULL) {
-               pr_err("%s: The slave %s is not attached to its bond\n",
-                      slave->bond->dev->name, slave->dev->name);
-               return -1;
-       }
-
-       //check that the slave has not been initialized yet.
+       /* check that the slave has not been initialized yet. */
        if (SLAVE_AD_INFO(slave).port.slave != slave) {
 
-               // port initialization
+               /* port initialization */
                port = &(SLAVE_AD_INFO(slave).port);
 
                ad_initialize_port(port, bond->params.lacp_fast);
@@ -1874,28 +1851,30 @@ int bond_3ad_bind_slave(struct slave *slave)
                __initialize_port_locks(slave);
                port->slave = slave;
                port->actor_port_number = SLAVE_AD_INFO(slave).id;
-               // key is determined according to the link speed, duplex and user key(which is yet not supported)
-               //              ------------------------------------------------------------
-               // Port key :   | User key                       |      Speed       |Duplex|
-               //              ------------------------------------------------------------
-               //              16                               6               1 0
-               port->actor_admin_port_key = 0; // initialize this parameter
+               /* key is determined according to the link speed, duplex and user key(which
+                * is yet not supported)
+                */
+               port->actor_admin_port_key = 0;
                port->actor_admin_port_key |= __get_duplex(port);
                port->actor_admin_port_key |= (__get_link_speed(port) << 1);
                port->actor_oper_port_key = port->actor_admin_port_key;
-               // if the port is not full duplex, then the port should be not lacp Enabled
+               /* if the port is not full duplex, then the port should be not
+                * lacp Enabled
+                */
                if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
                        port->sm_vars &= ~AD_PORT_LACP_ENABLED;
-               // actor system is the bond's system
+               /* actor system is the bond's system */
                port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
-               // tx timer(to verify that no more than MAX_TX_IN_SECOND lacpdu's are sent in one second)
+               /* tx timer(to verify that no more than MAX_TX_IN_SECOND
+                * lacpdu's are sent in one second)
+                */
                port->sm_tx_timer_counter = ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
                port->aggregator = NULL;
                port->next_port_in_aggregator = NULL;
 
                __disable_port(port);
 
-               // aggregator initialization
+               /* aggregator initialization */
                aggregator = &(SLAVE_AD_INFO(slave).aggregator);
 
                ad_initialize_agg(aggregator);
@@ -1906,8 +1885,6 @@ int bond_3ad_bind_slave(struct slave *slave)
                aggregator->is_active = 0;
                aggregator->num_of_ports = 0;
        }
-
-       return 0;
 }
 
 /**
@@ -1927,16 +1904,13 @@ void bond_3ad_unbind_slave(struct slave *slave)
        struct slave *slave_iter;
        struct list_head *iter;
 
-       // find the aggregator related to this slave
        aggregator = &(SLAVE_AD_INFO(slave).aggregator);
-
-       // find the port related to this slave
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
-               pr_warning("Warning: %s: Trying to unbind an uninitialized port on %s\n",
-                          slave->bond->dev->name, slave->dev->name);
+               pr_warn("Warning: %s: Trying to unbind an uninitialized port on %s\n",
+                       slave->bond->dev->name, slave->dev->name);
                return;
        }
 
@@ -1948,34 +1922,42 @@ void bond_3ad_unbind_slave(struct slave *slave)
        __update_lacpdu_from_port(port);
        ad_lacpdu_send(port);
 
-       // check if this aggregator is occupied
+       /* check if this aggregator is occupied */
        if (aggregator->lag_ports) {
-               // check if there are other ports related to this aggregator except
-               // the port related to this slave(thats ensure us that there is a
-               // reason to search for new aggregator, and that we will find one
-               if ((aggregator->lag_ports != port) || (aggregator->lag_ports->next_port_in_aggregator)) {
-                       // find new aggregator for the related port(s)
+               /* check if there are other ports related to this aggregator
+                * except the port related to this slave(thats ensure us that
+                * there is a reason to search for new aggregator, and that we
+                * will find one
+                */
+               if ((aggregator->lag_ports != port) ||
+                   (aggregator->lag_ports->next_port_in_aggregator)) {
+                       /* find new aggregator for the related port(s) */
                        bond_for_each_slave(bond, slave_iter, iter) {
                                new_aggregator = &(SLAVE_AD_INFO(slave_iter).aggregator);
-                               // if the new aggregator is empty, or it is connected to our port only
-                               if (!new_aggregator->lag_ports
-                                   || ((new_aggregator->lag_ports == port)
-                                       && !new_aggregator->lag_ports->next_port_in_aggregator))
+                               /* if the new aggregator is empty, or it is
+                                * connected to our port only
+                                */
+                               if (!new_aggregator->lag_ports ||
+                                   ((new_aggregator->lag_ports == port) &&
+                                    !new_aggregator->lag_ports->next_port_in_aggregator))
                                        break;
                        }
                        if (!slave_iter)
                                new_aggregator = NULL;
-                       // if new aggregator found, copy the aggregator's parameters
-                       // and connect the related lag_ports to the new aggregator
+
+                       /* if new aggregator found, copy the aggregator's
+                        * parameters and connect the related lag_ports to the
+                        * new aggregator
+                        */
                        if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
                                pr_debug("Some port(s) related to LAG %d - replaceing with LAG %d\n",
                                         aggregator->aggregator_identifier,
                                         new_aggregator->aggregator_identifier);
 
-                               if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
+                               if ((new_aggregator->lag_ports == port) &&
+                                   new_aggregator->is_active) {
                                        pr_info("%s: Removing an active aggregator\n",
                                                aggregator->slave->bond->dev->name);
-                                       // select new active aggregator
                                         select_new_active_agg = 1;
                                }
 
@@ -1991,30 +1973,33 @@ void bond_3ad_unbind_slave(struct slave *slave)
                                new_aggregator->is_active = aggregator->is_active;
                                new_aggregator->num_of_ports = aggregator->num_of_ports;
 
-                               // update the information that is written on the ports about the aggregator
+                               /* update the information that is written on
+                                * the ports about the aggregator
+                                */
                                for (temp_port = aggregator->lag_ports; temp_port;
                                     temp_port = temp_port->next_port_in_aggregator) {
                                        temp_port->aggregator = new_aggregator;
                                        temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier;
                                }
 
-                               // clear the aggregator
                                ad_clear_agg(aggregator);
 
                                if (select_new_active_agg)
                                        ad_agg_selection_logic(__get_first_agg(port));
                        } else {
-                               pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
-                                          slave->bond->dev->name);
+                               pr_warn("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
+                                       slave->bond->dev->name);
                        }
-               } else { // in case that the only port related to this aggregator is the one we want to remove
+               } else {
+                       /* in case that the only port related to this
+                        * aggregator is the one we want to remove
+                        */
                        select_new_active_agg = aggregator->is_active;
-                       // clear the aggregator
                        ad_clear_agg(aggregator);
                        if (select_new_active_agg) {
                                pr_info("%s: Removing an active aggregator\n",
                                        slave->bond->dev->name);
-                               // select new active aggregator
+                               /* select new active aggregator */
                                temp_aggregator = __get_first_agg(port);
                                if (temp_aggregator)
                                        ad_agg_selection_logic(temp_aggregator);
@@ -2023,15 +2008,19 @@ void bond_3ad_unbind_slave(struct slave *slave)
        }
 
        pr_debug("Unbinding port %d\n", port->actor_port_number);
-       // find the aggregator that this port is connected to
+
+       /* find the aggregator that this port is connected to */
        bond_for_each_slave(bond, slave_iter, iter) {
                temp_aggregator = &(SLAVE_AD_INFO(slave_iter).aggregator);
                prev_port = NULL;
-               // search the port in the aggregator's related ports
+               /* search the port in the aggregator's related ports */
                for (temp_port = temp_aggregator->lag_ports; temp_port;
                     prev_port = temp_port,
-                            temp_port = temp_port->next_port_in_aggregator) {
-                       if (temp_port == port) { // the aggregator found - detach the port from this aggregator
+                    temp_port = temp_port->next_port_in_aggregator) {
+                       if (temp_port == port) {
+                               /* the aggregator found - detach the port from
+                                * this aggregator
+                                */
                                if (prev_port)
                                        prev_port->next_port_in_aggregator = temp_port->next_port_in_aggregator;
                                else
@@ -2039,12 +2028,11 @@ void bond_3ad_unbind_slave(struct slave *slave)
                                temp_aggregator->num_of_ports--;
                                if (temp_aggregator->num_of_ports == 0) {
                                        select_new_active_agg = temp_aggregator->is_active;
-                                       // clear the aggregator
                                        ad_clear_agg(temp_aggregator);
                                        if (select_new_active_agg) {
                                                pr_info("%s: Removing an active aggregator\n",
                                                        slave->bond->dev->name);
-                                               // select new active aggregator
+                                               /* select new active aggregator */
                                                ad_agg_selection_logic(__get_first_agg(port));
                                        }
                                }
@@ -2085,15 +2073,16 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
                goto re_arm;
 
        /* check if agg_select_timer timer after initialize is timed out */
-       if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) {
+       if (BOND_AD_INFO(bond).agg_select_timer &&
+           !(--BOND_AD_INFO(bond).agg_select_timer)) {
                slave = bond_first_slave_rcu(bond);
                port = slave ? &(SLAVE_AD_INFO(slave).port) : NULL;
 
                /* select the active aggregator for the bond */
                if (port) {
                        if (!port->slave) {
-                               pr_warning("%s: Warning: bond's first port is uninitialized\n",
-                                          bond->dev->name);
+                               pr_warn("%s: Warning: bond's first port is uninitialized\n",
+                                       bond->dev->name);
                                goto re_arm;
                        }
 
@@ -2107,8 +2096,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
        bond_for_each_slave_rcu(bond, slave, iter) {
                port = &(SLAVE_AD_INFO(slave).port);
                if (!port->slave) {
-                       pr_warning("%s: Warning: Found an uninitialized port\n",
-                                  bond->dev->name);
+                       pr_warn("%s: Warning: Found an uninitialized port\n",
+                               bond->dev->name);
                        goto re_arm;
                }
 
@@ -2147,7 +2136,8 @@ re_arm:
  * received frames (loopback). Since only the payload is given to this
  * function, it check for loopback.
  */
-static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
+static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
+                                 u16 length)
 {
        struct port *port;
        int ret = RX_HANDLER_ANOTHER;
@@ -2157,8 +2147,8 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u1
                port = &(SLAVE_AD_INFO(slave).port);
 
                if (!port->slave) {
-                       pr_warning("%s: Warning: port of slave %s is uninitialized\n",
-                                  slave->dev->name, slave->bond->dev->name);
+                       pr_warn("%s: Warning: port of slave %s is uninitialized\n",
+                               slave->dev->name, slave->bond->dev->name);
                        return ret;
                }
 
@@ -2175,7 +2165,9 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u1
 
                case AD_TYPE_MARKER:
                        ret = RX_HANDLER_CONSUMED;
-                       // No need to convert fields to Little Endian since we don't use the marker's fields.
+                       /* No need to convert fields to Little Endian since we
+                        * don't use the marker's fields.
+                        */
 
                        switch (((struct bond_marker *)lacpdu)->tlv_type) {
                        case AD_MARKER_INFORMATION_SUBTYPE:
@@ -2211,20 +2203,25 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
-               pr_warning("Warning: %s: speed changed for uninitialized port on %s\n",
-                          slave->bond->dev->name, slave->dev->name);
+               pr_warn("Warning: %s: speed changed for uninitialized port on %s\n",
+                       slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                (__get_link_speed(port) << 1);
        pr_debug("Port %d changed speed\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2239,20 +2236,25 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
-               pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n",
-                          slave->bond->dev->name, slave->dev->name);
+               pr_warn("%s: Warning: duplex changed for uninitialized port on %s\n",
+                       slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                __get_duplex(port);
        pr_debug("Port %d changed duplex\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2268,15 +2270,21 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
-               pr_warning("Warning: %s: link status changed for uninitialized port on %s\n",
-                          slave->bond->dev->name, slave->dev->name);
+               pr_warn("Warning: %s: link status changed for uninitialized port on %s\n",
+                       slave->bond->dev->name, slave->dev->name);
                return;
        }
 
-       // on link down we are zeroing duplex and speed since some of the adaptors(ce1000.lan) report full duplex/speed instead of N/A(duplex) / 0(speed)
-       // on link up we are forcing recheck on the duplex and speed since some of he adaptors(ce1000.lan) report
+       __get_state_machine_lock(port);
+       /* on link down we are zeroing duplex and speed since
+        * some of the adaptors(ce1000.lan) report full duplex/speed
+        * instead of N/A(duplex) / 0(speed).
+        *
+        * on link up we are forcing recheck on the duplex and speed since
+        * some of he adaptors(ce1000.lan) report.
+        */
        if (link == BOND_LINK_UP) {
                port->is_enabled = true;
                port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
@@ -2292,16 +2300,24 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
                port->actor_oper_port_key = (port->actor_admin_port_key &=
                                             ~AD_SPEED_KEY_BITS);
        }
-       //BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       pr_debug("Port %d changed link status to %s",
+               port->actor_port_number,
+               (link == BOND_LINK_UP) ? "UP" : "DOWN");
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
-/*
- * set link state for bonding master: if we have an active
- * aggregator, we're up, if not, we're down.  Presumes that we cannot
- * have an active aggregator if there are no slaves with link up.
+/**
+ * bond_3ad_set_carrier - set link state for bonding master
+ * @bond - bonding structure
+ *
+ * if we have an active aggregator, we're up, if not, we're down.
+ * Presumes that we cannot have an active aggregator if there are
+ * no slaves with link up.
  *
  * This behavior complies with IEEE 802.3 section 43.3.9.
  *
@@ -2312,32 +2328,32 @@ int bond_3ad_set_carrier(struct bonding *bond)
 {
        struct aggregator *active;
        struct slave *first_slave;
+       int ret = 1;
 
        rcu_read_lock();
        first_slave = bond_first_slave_rcu(bond);
-       rcu_read_unlock();
-       if (!first_slave)
-               return 0;
+       if (!first_slave) {
+               ret = 0;
+               goto out;
+       }
        active = __get_active_agg(&(SLAVE_AD_INFO(first_slave).aggregator));
        if (active) {
                /* are enough slaves available to consider link up? */
                if (active->num_of_ports < bond->params.min_links) {
                        if (netif_carrier_ok(bond->dev)) {
                                netif_carrier_off(bond->dev);
-                               return 1;
+                               goto out;
                        }
                } else if (!netif_carrier_ok(bond->dev)) {
                        netif_carrier_on(bond->dev);
-                       return 1;
+                       goto out;
                }
-               return 0;
-       }
-
-       if (netif_carrier_ok(bond->dev)) {
+       } else if (netif_carrier_ok(bond->dev)) {
                netif_carrier_off(bond->dev);
-               return 1;
        }
-       return 0;
+out:
+       rcu_read_unlock();
+       return ret;
 }
 
 /**
@@ -2369,7 +2385,8 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond,
                ad_info->ports = aggregator->num_of_ports;
                ad_info->actor_key = aggregator->actor_oper_aggregator_key;
                ad_info->partner_key = aggregator->partner_oper_aggregator_key;
-               memcpy(ad_info->partner_system, aggregator->partner_system.mac_addr_value, ETH_ALEN);
+               memcpy(ad_info->partner_system,
+                      aggregator->partner_system.mac_addr_value, ETH_ALEN);
                return 0;
        }
 
@@ -2397,13 +2414,12 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
        struct list_head *iter;
        int slaves_in_agg;
        int slave_agg_no;
-       int res = 1;
        int agg_id;
 
        if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
                pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n",
                         dev->name);
-               goto out;
+               goto err_free;
        }
 
        slaves_in_agg = ad_info.ports;
@@ -2411,7 +2427,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 
        if (slaves_in_agg == 0) {
                pr_debug("%s: Error: active aggregator is empty\n", dev->name);
-               goto out;
+               goto err_free;
        }
 
        slave_agg_no = bond_xmit_hash(bond, skb, slaves_in_agg);
@@ -2430,7 +2446,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
                }
 
                if (SLAVE_IS_OK(slave)) {
-                       res = bond_dev_queue_xmit(bond, skb, slave->dev);
+                       bond_dev_queue_xmit(bond, skb, slave->dev);
                        goto out;
                }
        }
@@ -2438,21 +2454,23 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
        if (slave_agg_no >= 0) {
                pr_err("%s: Error: Couldn't find a slave to tx on for aggregator ID %d\n",
                       dev->name, agg_id);
-               goto out;
+               goto err_free;
        }
 
        /* we couldn't find any suitable slave after the agg_no, so use the
-        * first suitable found, if found. */
+        * first suitable found, if found.
+        */
        if (first_ok_slave)
-               res = bond_dev_queue_xmit(bond, skb, first_ok_slave->dev);
+               bond_dev_queue_xmit(bond, skb, first_ok_slave->dev);
+       else
+               goto err_free;
 
 out:
-       if (res) {
-               /* no suitable interface, frame not sent */
-               kfree_skb(skb);
-       }
-
        return NETDEV_TX_OK;
+err_free:
+       /* no suitable interface, frame not sent */
+       kfree_skb(skb);
+       goto out;
 }
 
 int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
@@ -2474,7 +2492,10 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
        return ret;
 }
 
-/*
+/**
+ * bond_3ad_update_lacp_rate - change the lacp rate
+ * @bond - bonding struct
+ *
  * When modify lacp_rate parameter via sysfs,
  * update actor_oper_port_state of each port.
  *
index 5d91ad0cc04142df9e73a52a62d06e5ab4d3898e..13dc9d3c5e3460e2e0e4f01e2ab1df2a962d60e2 100644 (file)
@@ -265,7 +265,7 @@ struct ad_slave_info {
 
 // ================= AD Exported functions to the main bonding code ==================
 void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
-int  bond_3ad_bind_slave(struct slave *slave);
+void  bond_3ad_bind_slave(struct slave *slave);
 void bond_3ad_unbind_slave(struct slave *slave);
 void bond_3ad_state_machine_handler(struct work_struct *);
 void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
index 759ddeebe39028e1d4b5e4adcf7c322b64cdfd52..a2c47476804dc388406e05b4c425c4be59089add 100644 (file)
@@ -1371,7 +1371,6 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
        int do_tx_balance = 1;
        u32 hash_index = 0;
        const u8 *hash_start = NULL;
-       int res = 1;
        struct ipv6hdr *ip6hdr;
 
        skb_reset_mac_header(skb);
@@ -1469,7 +1468,8 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
                               ETH_ALEN);
                }
 
-               res = bond_dev_queue_xmit(bond, skb, tx_slave->dev);
+               bond_dev_queue_xmit(bond, skb, tx_slave->dev);
+               goto out;
        } else {
                if (tx_slave) {
                        _lock_tx_hashtbl(bond);
@@ -1478,11 +1478,9 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
                }
        }
 
-       if (res) {
-               /* no suitable interface, frame not sent */
-               kfree_skb(skb);
-       }
-
+       /* no suitable interface, frame not sent */
+       kfree_skb(skb);
+out:
        return NETDEV_TX_OK;
 }
 
index c0456cc8661047045b2ab5cb0df47377388d4e5a..e06c4453eabb99e3c22347335d65853d84b2b4d4 100644 (file)
@@ -113,6 +113,7 @@ static int all_slaves_active;
 static struct bond_params bonding_defaults;
 static int resend_igmp = BOND_DEFAULT_RESEND_IGMP;
 static int packets_per_slave = 1;
+static int lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL;
 
 module_param(max_bonds, int, 0);
 MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -189,6 +190,10 @@ module_param(packets_per_slave, int, 0);
 MODULE_PARM_DESC(packets_per_slave, "Packets to send per slave in balance-rr "
                                    "mode; 0 for a random slave, 1 packet per "
                                    "slave (default), >1 packets per slave.");
+module_param(lp_interval, uint, 0);
+MODULE_PARM_DESC(lp_interval, "The number of seconds between instances where "
+                             "the bonding driver sends learning packets to "
+                             "each slaves peer switch. The default is 1.");
 
 /*----------------------------- Global variables ----------------------------*/
 
@@ -299,7 +304,7 @@ const char *bond_mode_name(int mode)
  * @skb: hw accel VLAN tagged skb to transmit
  * @slave_dev: slave that is supposed to xmit this skbuff
  */
-int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
+void bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
                        struct net_device *slave_dev)
 {
        skb->dev = slave_dev;
@@ -312,8 +317,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
                bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb);
        else
                dev_queue_xmit(skb);
-
-       return 0;
 }
 
 /*
@@ -1634,7 +1637,7 @@ err_free:
 err_undo_flags:
        /* Enslave of first slave has failed and we need to fix master's mac */
        if (!bond_has_slaves(bond) &&
-           ether_addr_equal(bond_dev->dev_addr, slave_dev->dev_addr))
+           ether_addr_equal_64bits(bond_dev->dev_addr, slave_dev->dev_addr))
                eth_hw_addr_random(bond_dev);
 
        return res;
@@ -1707,7 +1710,7 @@ static int __bond_release_one(struct net_device *bond_dev,
        bond->current_arp_slave = NULL;
 
        if (!all && !bond->params.fail_over_mac) {
-               if (ether_addr_equal(bond_dev->dev_addr, slave->perm_hwaddr) &&
+               if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) &&
                    bond_has_slaves(bond))
                        pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
                                   bond_dev->name, slave_dev->name,
@@ -2085,7 +2088,7 @@ do_failover:
  * an acquisition of appropriate locks followed by a commit phase to
  * implement whatever link state changes are indicated.
  */
-void bond_mii_monitor(struct work_struct *work)
+static void bond_mii_monitor(struct work_struct *work)
 {
        struct bonding *bond = container_of(work, struct bonding,
                                            mii_work.work);
@@ -2374,7 +2377,7 @@ static bool bond_time_in_interval(struct bonding *bond, unsigned long last_act,
  * arp is transmitted to generate traffic. see activebackup_arp_monitor for
  * arp monitoring in active backup mode.
  */
-void bond_loadbalance_arp_mon(struct work_struct *work)
+static void bond_loadbalance_arp_mon(struct work_struct *work)
 {
        struct bonding *bond = container_of(work, struct bonding,
                                            arp_work.work);
@@ -2711,7 +2714,7 @@ static void bond_ab_arp_probe(struct bonding *bond)
        rcu_assign_pointer(bond->current_arp_slave, new_slave);
 }
 
-void bond_activebackup_arp_mon(struct work_struct *work)
+static void bond_activebackup_arp_mon(struct work_struct *work)
 {
        struct bonding *bond = container_of(work, struct bonding,
                                            arp_work.work);
@@ -3511,7 +3514,7 @@ unwind:
  * it fails, it tries to find the first available slave for transmission.
  * The skb is consumed in all cases, thus the function is void.
  */
-void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id)
+static void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id)
 {
        struct list_head *iter;
        struct slave *slave;
@@ -3668,28 +3671,24 @@ static inline int bond_slave_override(struct bonding *bond,
                                      struct sk_buff *skb)
 {
        struct slave *slave = NULL;
-       struct slave *check_slave;
        struct list_head *iter;
-       int res = 1;
 
        if (!skb->queue_mapping)
                return 1;
 
        /* Find out if any slaves have the same mapping as this skb. */
-       bond_for_each_slave_rcu(bond, check_slave, iter) {
-               if (check_slave->queue_id == skb->queue_mapping) {
-                       slave = check_slave;
+       bond_for_each_slave_rcu(bond, slave, iter) {
+               if (slave->queue_id == skb->queue_mapping) {
+                       if (slave_can_tx(slave)) {
+                               bond_dev_queue_xmit(bond, skb, slave->dev);
+                               return 0;
+                       }
+                       /* If the slave isn't UP, use default transmit policy. */
                        break;
                }
        }
 
-       /* If the slave isn't UP, use default transmit policy. */
-       if (slave && slave->queue_id && IS_UP(slave->dev) &&
-           (slave->link == BOND_LINK_UP)) {
-               res = bond_dev_queue_xmit(bond, skb, slave->dev);
-       }
-
-       return res;
+       return 1;
 }
 
 
@@ -3934,6 +3933,29 @@ static void bond_uninit(struct net_device *bond_dev)
 
 /*------------------------- Module initialization ---------------------------*/
 
+int bond_parm_tbl_lookup(int mode, const struct bond_parm_tbl *tbl)
+{
+       int i;
+
+       for (i = 0; tbl[i].modename; i++)
+               if (mode == tbl[i].mode)
+                       return tbl[i].mode;
+
+       return -1;
+}
+
+static int bond_parm_tbl_lookup_name(const char *modename,
+                                    const struct bond_parm_tbl *tbl)
+{
+       int i;
+
+       for (i = 0; tbl[i].modename; i++)
+               if (strcmp(modename, tbl[i].modename) == 0)
+                       return tbl[i].mode;
+
+       return -1;
+}
+
 /*
  * Convert string input module parms.  Accept either the
  * number of the mode or its string name.  A bit complicated because
@@ -3942,27 +3964,17 @@ static void bond_uninit(struct net_device *bond_dev)
  */
 int bond_parse_parm(const char *buf, const struct bond_parm_tbl *tbl)
 {
-       int modeint = -1, i, rv;
-       char *p, modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, };
+       int modeint;
+       char *p, modestr[BOND_MAX_MODENAME_LEN + 1];
 
        for (p = (char *)buf; *p; p++)
                if (!(isdigit(*p) || isspace(*p)))
                        break;
 
-       if (*p)
-               rv = sscanf(buf, "%20s", modestr);
-       else
-               rv = sscanf(buf, "%d", &modeint);
-
-       if (!rv)
-               return -1;
-
-       for (i = 0; tbl[i].modename; i++) {
-               if (modeint == tbl[i].mode)
-                       return tbl[i].mode;
-               if (strcmp(modestr, tbl[i].modename) == 0)
-                       return tbl[i].mode;
-       }
+       if (*p && sscanf(buf, "%20s", modestr) != 0)
+               return bond_parm_tbl_lookup_name(modestr, tbl);
+       else if (sscanf(buf, "%d", &modeint) != 0)
+               return bond_parm_tbl_lookup(modeint, tbl);
 
        return -1;
 }
@@ -4066,8 +4078,8 @@ static int bond_check_params(struct bond_params *params)
                num_peer_notif = 1;
        }
 
-       /* reset values for 802.3ad */
-       if (bond_mode == BOND_MODE_8023AD) {
+       /* reset values for 802.3ad/TLB/ALB */
+       if (BOND_NO_USES_ARP(bond_mode)) {
                if (!miimon) {
                        pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n");
                        pr_warning("Forcing miimon to 100msec\n");
@@ -4102,16 +4114,6 @@ static int bond_check_params(struct bond_params *params)
                packets_per_slave = 1;
        }
 
-       /* reset values for TLB/ALB */
-       if ((bond_mode == BOND_MODE_TLB) ||
-           (bond_mode == BOND_MODE_ALB)) {
-               if (!miimon) {
-                       pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure and link speed which are essential for TLB/ALB load balancing\n");
-                       pr_warning("Forcing miimon to 100msec\n");
-                       miimon = BOND_DEFAULT_MIIMON;
-               }
-       }
-
        if (bond_mode == BOND_MODE_ALB) {
                pr_notice("In ALB mode you might experience client disconnections upon reconnection of a link if the bonding module updelay parameter (%d msec) is incompatible with the forwarding delay time of the switch\n",
                          updelay);
@@ -4271,6 +4273,12 @@ static int bond_check_params(struct bond_params *params)
                fail_over_mac_value = BOND_FOM_NONE;
        }
 
+       if (lp_interval == 0) {
+               pr_warning("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n",
+                          INT_MAX, BOND_ALB_DEFAULT_LP_INTERVAL);
+               lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL;
+       }
+
        /* fill params struct with the proper values */
        params->mode = bond_mode;
        params->xmit_policy = xmit_hashtype;
@@ -4290,7 +4298,7 @@ static int bond_check_params(struct bond_params *params)
        params->all_slaves_active = all_slaves_active;
        params->resend_igmp = resend_igmp;
        params->min_links = min_links;
-       params->lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL;
+       params->lp_interval = lp_interval;
        if (packets_per_slave > 1)
                params->packets_per_slave = reciprocal_value(packets_per_slave);
        else
index 84acd144d0756965ec28305456ec11f2d985997e..555c7837d8e6a9df01c56c7ad72e8cf307e2b441 100644 (file)
@@ -43,6 +43,9 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
        [IFLA_BOND_MIN_LINKS]           = { .type = NLA_U32 },
        [IFLA_BOND_LP_INTERVAL]         = { .type = NLA_U32 },
        [IFLA_BOND_PACKETS_PER_SLAVE]   = { .type = NLA_U32 },
+       [IFLA_BOND_AD_LACP_RATE]        = { .type = NLA_U8 },
+       [IFLA_BOND_AD_SELECT]           = { .type = NLA_U8 },
+       [IFLA_BOND_AD_INFO]             = { .type = NLA_NESTED },
 };
 
 static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -252,6 +255,22 @@ static int bond_changelink(struct net_device *bond_dev,
                if (err)
                        return err;
        }
+       if (data[IFLA_BOND_AD_LACP_RATE]) {
+               int lacp_rate =
+                       nla_get_u8(data[IFLA_BOND_AD_LACP_RATE]);
+
+               err = bond_option_lacp_rate_set(bond, lacp_rate);
+               if (err)
+                       return err;
+       }
+       if (data[IFLA_BOND_AD_SELECT]) {
+               int ad_select =
+                       nla_get_u8(data[IFLA_BOND_AD_SELECT]);
+
+               err = bond_option_ad_select_set(bond, ad_select);
+               if (err)
+                       return err;
+       }
        return 0;
 }
 
@@ -277,6 +296,7 @@ static size_t bond_get_size(const struct net_device *bond_dev)
                nla_total_size(sizeof(u8)) +    /* IFLA_BOND_USE_CARRIER */
                nla_total_size(sizeof(u32)) +   /* IFLA_BOND_ARP_INTERVAL */
                                                /* IFLA_BOND_ARP_IP_TARGET */
+               nla_total_size(sizeof(struct nlattr)) +
                nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS +
                nla_total_size(sizeof(u32)) +   /* IFLA_BOND_ARP_VALIDATE */
                nla_total_size(sizeof(u32)) +   /* IFLA_BOND_ARP_ALL_TARGETS */
@@ -290,6 +310,14 @@ static size_t bond_get_size(const struct net_device *bond_dev)
                nla_total_size(sizeof(u32)) +   /* IFLA_BOND_MIN_LINKS */
                nla_total_size(sizeof(u32)) +   /* IFLA_BOND_LP_INTERVAL */
                nla_total_size(sizeof(u32)) +  /* IFLA_BOND_PACKETS_PER_SLAVE */
+               nla_total_size(sizeof(u8)) +    /* IFLA_BOND_AD_LACP_RATE */
+               nla_total_size(sizeof(u8)) +    /* IFLA_BOND_AD_SELECT */
+               nla_total_size(sizeof(struct nlattr)) + /* IFLA_BOND_AD_INFO */
+               nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_AGGREGATOR */
+               nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_NUM_PORTS */
+               nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_ACTOR_KEY */
+               nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_PARTNER_KEY*/
+               nla_total_size(ETH_ALEN) +    /* IFLA_BOND_AD_INFO_PARTNER_MAC*/
                0;
 }
 
@@ -395,6 +423,45 @@ static int bond_fill_info(struct sk_buff *skb,
                        packets_per_slave))
                goto nla_put_failure;
 
+       if (nla_put_u8(skb, IFLA_BOND_AD_LACP_RATE,
+                      bond->params.lacp_fast))
+               goto nla_put_failure;
+
+       if (nla_put_u8(skb, IFLA_BOND_AD_SELECT,
+                      bond->params.ad_select))
+               goto nla_put_failure;
+
+       if (bond->params.mode == BOND_MODE_8023AD) {
+               struct ad_info info;
+
+               if (!bond_3ad_get_active_agg_info(bond, &info)) {
+                       struct nlattr *nest;
+
+                       nest = nla_nest_start(skb, IFLA_BOND_AD_INFO);
+                       if (!nest)
+                               goto nla_put_failure;
+
+                       if (nla_put_u16(skb, IFLA_BOND_AD_INFO_AGGREGATOR,
+                                       info.aggregator_id))
+                               goto nla_put_failure;
+                       if (nla_put_u16(skb, IFLA_BOND_AD_INFO_NUM_PORTS,
+                                       info.ports))
+                               goto nla_put_failure;
+                       if (nla_put_u16(skb, IFLA_BOND_AD_INFO_ACTOR_KEY,
+                                       info.actor_key))
+                               goto nla_put_failure;
+                       if (nla_put_u16(skb, IFLA_BOND_AD_INFO_PARTNER_KEY,
+                                       info.partner_key))
+                               goto nla_put_failure;
+                       if (nla_put(skb, IFLA_BOND_AD_INFO_PARTNER_MAC,
+                                   sizeof(info.partner_system),
+                                   &info.partner_system))
+                               goto nla_put_failure;
+
+                       nla_nest_end(skb, nest);
+               }
+       }
+
        return 0;
 
 nla_put_failure:
index f8a2cd8c7b570886198a4b825302f514a5018d45..945a6668da8376ad125356a300b9d34a72ea4166 100644 (file)
 #include <linux/reciprocal_div.h>
 #include "bonding.h"
 
-static bool bond_mode_is_valid(int mode)
-{
-       int i;
-
-       for (i = 0; bond_mode_tbl[i].modename; i++);
-
-       return mode >= 0 && mode < i;
-}
-
 int bond_option_mode_set(struct bonding *bond, int mode)
 {
-       if (!bond_mode_is_valid(mode)) {
-               pr_err("invalid mode value %d.\n", mode);
+       if (bond_parm_tbl_lookup(mode, bond_mode_tbl) < 0) {
+               pr_err("%s: Ignoring invalid mode value %d.\n",
+                      bond->dev->name, mode);
                return -EINVAL;
        }
 
@@ -438,11 +430,18 @@ int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets,
 
 int bond_option_arp_validate_set(struct bonding *bond, int arp_validate)
 {
+       if (bond_parm_tbl_lookup(arp_validate, arp_validate_tbl) < 0) {
+               pr_err("%s: Ignoring invalid arp_validate value %d.\n",
+                      bond->dev->name, arp_validate);
+               return -EINVAL;
+       }
+
        if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
                pr_err("%s: arp_validate only supported in active-backup mode.\n",
                       bond->dev->name);
                return -EINVAL;
        }
+
        pr_info("%s: setting arp_validate to %s (%d).\n",
                bond->dev->name, arp_validate_tbl[arp_validate].modename,
                arp_validate);
@@ -460,6 +459,12 @@ int bond_option_arp_validate_set(struct bonding *bond, int arp_validate)
 
 int bond_option_arp_all_targets_set(struct bonding *bond, int arp_all_targets)
 {
+       if (bond_parm_tbl_lookup(arp_all_targets, arp_all_targets_tbl) < 0) {
+               pr_err("%s: Ignoring invalid arp_all_targets value %d.\n",
+                      bond->dev->name, arp_all_targets);
+               return -EINVAL;
+       }
+
        pr_info("%s: setting arp_all_targets to %s (%d).\n",
                bond->dev->name, arp_all_targets_tbl[arp_all_targets].modename,
                arp_all_targets);
@@ -523,6 +528,12 @@ out:
 
 int bond_option_primary_reselect_set(struct bonding *bond, int primary_reselect)
 {
+       if (bond_parm_tbl_lookup(primary_reselect, pri_reselect_tbl) < 0) {
+               pr_err("%s: Ignoring invalid primary_reselect value %d.\n",
+                      bond->dev->name, primary_reselect);
+               return -EINVAL;
+       }
+
        bond->params.primary_reselect = primary_reselect;
        pr_info("%s: setting primary_reselect to %s (%d).\n",
                bond->dev->name, pri_reselect_tbl[primary_reselect].modename,
@@ -539,6 +550,12 @@ int bond_option_primary_reselect_set(struct bonding *bond, int primary_reselect)
 
 int bond_option_fail_over_mac_set(struct bonding *bond, int fail_over_mac)
 {
+       if (bond_parm_tbl_lookup(fail_over_mac, fail_over_mac_tbl) < 0) {
+               pr_err("%s: Ignoring invalid fail_over_mac value %d.\n",
+                      bond->dev->name, fail_over_mac);
+               return -EINVAL;
+       }
+
        if (bond_has_slaves(bond)) {
                pr_err("%s: Can't alter fail_over_mac with slaves in bond.\n",
                       bond->dev->name);
@@ -555,6 +572,12 @@ int bond_option_fail_over_mac_set(struct bonding *bond, int fail_over_mac)
 
 int bond_option_xmit_hash_policy_set(struct bonding *bond, int xmit_hash_policy)
 {
+       if (bond_parm_tbl_lookup(xmit_hash_policy, xmit_hashtype_tbl) < 0) {
+               pr_err("%s: Ignoring invalid xmit_hash_policy value %d.\n",
+                      bond->dev->name, xmit_hash_policy);
+               return -EINVAL;
+       }
+
        bond->params.xmit_policy = xmit_hash_policy;
        pr_info("%s: setting xmit hash policy to %s (%d).\n",
                bond->dev->name,
@@ -656,3 +679,54 @@ int bond_option_packets_per_slave_set(struct bonding *bond,
 
        return 0;
 }
+
+int bond_option_lacp_rate_set(struct bonding *bond, int lacp_rate)
+{
+       if (bond_parm_tbl_lookup(lacp_rate, bond_lacp_tbl) < 0) {
+               pr_err("%s: Ignoring invalid LACP rate value %d.\n",
+                      bond->dev->name, lacp_rate);
+               return -EINVAL;
+       }
+
+       if (bond->dev->flags & IFF_UP) {
+               pr_err("%s: Unable to update LACP rate because interface is up.\n",
+                      bond->dev->name);
+               return -EPERM;
+       }
+
+       if (bond->params.mode != BOND_MODE_8023AD) {
+               pr_err("%s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
+                      bond->dev->name);
+               return -EPERM;
+       }
+
+       bond->params.lacp_fast = lacp_rate;
+       bond_3ad_update_lacp_rate(bond);
+       pr_info("%s: Setting LACP rate to %s (%d).\n",
+               bond->dev->name, bond_lacp_tbl[lacp_rate].modename,
+               lacp_rate);
+
+       return 0;
+}
+
+int bond_option_ad_select_set(struct bonding *bond, int ad_select)
+{
+       if (bond_parm_tbl_lookup(ad_select, ad_select_tbl) < 0) {
+               pr_err("%s: Ignoring invalid ad_select value %d.\n",
+                      bond->dev->name, ad_select);
+               return -EINVAL;
+       }
+
+       if (bond->dev->flags & IFF_UP) {
+               pr_err("%s: Unable to update ad_select because interface is up.\n",
+                      bond->dev->name);
+               return -EPERM;
+       }
+
+       bond->params.ad_select = ad_select;
+       pr_info("%s: Setting ad_select to %s (%d).\n",
+               bond->dev->name, ad_select_tbl[ad_select].modename,
+               ad_select);
+
+       return 0;
+}
index a0a3476fadba41707cc8162e6b6513c71797412f..011f163c2c6771a9cbd335a507dfb390b081eca2 100644 (file)
@@ -658,41 +658,23 @@ static ssize_t bonding_store_lacp(struct device *d,
                                  const char *buf, size_t count)
 {
        struct bonding *bond = to_bond(d);
-       int new_value, ret = count;
-
-       if (!rtnl_trylock())
-               return restart_syscall();
-
-       if (bond->dev->flags & IFF_UP) {
-               pr_err("%s: Unable to update LACP rate because interface is up.\n",
-                      bond->dev->name);
-               ret = -EPERM;
-               goto out;
-       }
-
-       if (bond->params.mode != BOND_MODE_8023AD) {
-               pr_err("%s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
-                      bond->dev->name);
-               ret = -EPERM;
-               goto out;
-       }
+       int new_value, ret;
 
        new_value = bond_parse_parm(buf, bond_lacp_tbl);
-
-       if ((new_value == 1) || (new_value == 0)) {
-               bond->params.lacp_fast = new_value;
-               bond_3ad_update_lacp_rate(bond);
-               pr_info("%s: Setting LACP rate to %s (%d).\n",
-                       bond->dev->name, bond_lacp_tbl[new_value].modename,
-                       new_value);
-       } else {
+       if (new_value < 0) {
                pr_err("%s: Ignoring invalid LACP rate value %.*s.\n",
                       bond->dev->name, (int)strlen(buf) - 1, buf);
-               ret = -EINVAL;
+               return -EINVAL;
        }
-out:
-       rtnl_unlock();
 
+       if (!rtnl_trylock())
+               return restart_syscall();
+
+       ret = bond_option_lacp_rate_set(bond, new_value);
+       if (!ret)
+               ret = count;
+
+       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR,
@@ -751,29 +733,24 @@ static ssize_t bonding_store_ad_select(struct device *d,
                                       struct device_attribute *attr,
                                       const char *buf, size_t count)
 {
-       int new_value, ret = count;
+       int new_value, ret;
        struct bonding *bond = to_bond(d);
 
-       if (bond->dev->flags & IFF_UP) {
-               pr_err("%s: Unable to update ad_select because interface is up.\n",
-                      bond->dev->name);
-               ret = -EPERM;
-               goto out;
-       }
-
        new_value = bond_parse_parm(buf, ad_select_tbl);
-
-       if (new_value != -1) {
-               bond->params.ad_select = new_value;
-               pr_info("%s: Setting ad_select to %s (%d).\n",
-                       bond->dev->name, ad_select_tbl[new_value].modename,
-                       new_value);
-       } else {
+       if (new_value < 0) {
                pr_err("%s: Ignoring invalid ad_select value %.*s.\n",
                       bond->dev->name, (int)strlen(buf) - 1, buf);
-               ret = -EINVAL;
+               return -EINVAL;
        }
-out:
+
+       if (!rtnl_trylock())
+               return restart_syscall();
+
+       ret = bond_option_ad_select_set(bond, new_value);
+       if (!ret)
+               ret = count;
+
+       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR,
@@ -799,7 +776,7 @@ static ssize_t bonding_store_num_peer_notif(struct device *d,
        int ret;
 
        ret = kstrtou8(buf, 10, &new_value);
-       if (!ret) {
+       if (ret) {
                pr_err("%s: invalid value %s specified.\n",
                       bond->dev->name, buf);
                return ret;
index 5886f07dc1f316425d6b2ee10148dabdea923662..955dc4839f1d3b03559c69551e4b847571af9c15 100644 (file)
@@ -416,19 +416,16 @@ static inline bool slave_can_tx(struct slave *slave)
 struct bond_net;
 
 int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave);
-int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
-void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id);
+void bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
 int bond_create(struct net *net, const char *name);
 int bond_create_sysfs(struct bond_net *net);
 void bond_destroy_sysfs(struct bond_net *net);
 void bond_prepare_sysfs_group(struct bonding *bond);
 int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
 int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
-void bond_mii_monitor(struct work_struct *);
-void bond_loadbalance_arp_mon(struct work_struct *);
-void bond_activebackup_arp_mon(struct work_struct *);
 int bond_xmit_hash(struct bonding *bond, struct sk_buff *skb, int count);
 int bond_parse_parm(const char *mode_arg, const struct bond_parm_tbl *tbl);
+int bond_parm_tbl_lookup(int mode, const struct bond_parm_tbl *tbl);
 void bond_select_active_slave(struct bonding *bond);
 void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
 void bond_create_debugfs(void);
@@ -468,6 +465,8 @@ int bond_option_min_links_set(struct bonding *bond, int min_links);
 int bond_option_lp_interval_set(struct bonding *bond, int min_links);
 int bond_option_packets_per_slave_set(struct bonding *bond,
                                      int packets_per_slave);
+int bond_option_lacp_rate_set(struct bonding *bond, int lacp_rate);
+int bond_option_ad_select_set(struct bonding *bond, int ad_select);
 struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
 struct net_device *bond_option_active_slave_get(struct bonding *bond);
 
index 3c069472eb8b6ddfc4f134209ccf92b51ac0ee84..9e7d95dae2c7038478d6efadddba81e2778f47a9 100644 (file)
@@ -71,7 +71,7 @@ config CAN_AT91
          and AT91SAM9X5 processors.
 
 config CAN_TI_HECC
-       depends on ARCH_OMAP3
+       depends on ARM
        tristate "TI High End CAN Controller"
        ---help---
          Driver for TI HECC (High End CAN Controller) module found on many
index 88d3877b62770702419ffba079b118b8124459b7..cdb9808d12dbc9883250ccceb5ac156be6a4c84d 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/can/dev.h>
 #include <linux/can/led.h>
 #include <linux/can/platform/mcp251x.h>
+#include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -68,6 +69,8 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
@@ -263,6 +266,7 @@ struct mcp251x_priv {
        int restart_tx;
        struct regulator *power;
        struct regulator *transceiver;
+       struct clk *clk;
 };
 
 #define MCP251X_IS(_model) \
@@ -994,22 +998,65 @@ static const struct net_device_ops mcp251x_netdev_ops = {
        .ndo_start_xmit = mcp251x_hard_start_xmit,
 };
 
+static const struct of_device_id mcp251x_of_match[] = {
+       {
+               .compatible     = "microchip,mcp2510",
+               .data           = (void *)CAN_MCP251X_MCP2510,
+       },
+       {
+               .compatible     = "microchip,mcp2515",
+               .data           = (void *)CAN_MCP251X_MCP2515,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mcp251x_of_match);
+
+static const struct spi_device_id mcp251x_id_table[] = {
+       {
+               .name           = "mcp2510",
+               .driver_data    = (kernel_ulong_t)CAN_MCP251X_MCP2510,
+       },
+       {
+               .name           = "mcp2515",
+               .driver_data    = (kernel_ulong_t)CAN_MCP251X_MCP2515,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
+
 static int mcp251x_can_probe(struct spi_device *spi)
 {
+       const struct of_device_id *of_id = of_match_device(mcp251x_of_match,
+                                                          &spi->dev);
+       struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev);
        struct net_device *net;
        struct mcp251x_priv *priv;
-       struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev);
-       int ret = -ENODEV;
+       int freq, ret = -ENODEV;
+       struct clk *clk;
+
+       clk = devm_clk_get(&spi->dev, NULL);
+       if (IS_ERR(clk)) {
+               if (pdata)
+                       freq = pdata->oscillator_frequency;
+               else
+                       return PTR_ERR(clk);
+       } else {
+               freq = clk_get_rate(clk);
+       }
 
-       if (!pdata)
-               /* Platform data is required for osc freq */
-               goto error_out;
+       /* Sanity check */
+       if (freq < 1000000 || freq > 25000000)
+               return -ERANGE;
 
        /* Allocate can/net device */
        net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
-       if (!net) {
-               ret = -ENOMEM;
-               goto error_alloc;
+       if (!net)
+               return -ENOMEM;
+
+       if (!IS_ERR(clk)) {
+               ret = clk_prepare_enable(clk);
+               if (ret)
+                       goto out_free;
        }
 
        net->netdev_ops = &mcp251x_netdev_ops;
@@ -1018,23 +1065,27 @@ static int mcp251x_can_probe(struct spi_device *spi)
        priv = netdev_priv(net);
        priv->can.bittiming_const = &mcp251x_bittiming_const;
        priv->can.do_set_mode = mcp251x_do_set_mode;
-       priv->can.clock.freq = pdata->oscillator_frequency / 2;
+       priv->can.clock.freq = freq / 2;
        priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
                CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
-       priv->model = spi_get_device_id(spi)->driver_data;
+       if (of_id)
+               priv->model = (enum mcp251x_model)of_id->data;
+       else
+               priv->model = spi_get_device_id(spi)->driver_data;
        priv->net = net;
+       priv->clk = clk;
 
        priv->power = devm_regulator_get(&spi->dev, "vdd");
        priv->transceiver = devm_regulator_get(&spi->dev, "xceiver");
        if ((PTR_ERR(priv->power) == -EPROBE_DEFER) ||
            (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) {
                ret = -EPROBE_DEFER;
-               goto error_power;
+               goto out_clk;
        }
 
        ret = mcp251x_power_enable(priv->power, 1);
        if (ret)
-               goto error_power;
+               goto out_clk;
 
        spi_set_drvdata(spi, priv);
 
@@ -1113,11 +1164,14 @@ error_probe:
                dma_free_coherent(&spi->dev, PAGE_SIZE,
                                  priv->spi_tx_buf, priv->spi_tx_dma);
        mcp251x_power_enable(priv->power, 0);
-error_power:
+
+out_clk:
+       if (!IS_ERR(clk))
+               clk_disable_unprepare(clk);
+
+out_free:
        free_candev(net);
-error_alloc:
-       dev_err(&spi->dev, "probe failed\n");
-error_out:
+
        return ret;
 }
 
@@ -1135,6 +1189,9 @@ static int mcp251x_can_remove(struct spi_device *spi)
 
        mcp251x_power_enable(priv->power, 0);
 
+       if (!IS_ERR(priv->clk))
+               clk_disable_unprepare(priv->clk);
+
        free_candev(net);
 
        return 0;
@@ -1197,21 +1254,13 @@ static int mcp251x_can_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,
        mcp251x_can_resume);
 
-static const struct spi_device_id mcp251x_id_table[] = {
-       { "mcp2510",    CAN_MCP251X_MCP2510 },
-       { "mcp2515",    CAN_MCP251X_MCP2515 },
-       { },
-};
-
-MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
-
 static struct spi_driver mcp251x_can_driver = {
        .driver = {
                .name = DEVICE_NAME,
                .owner = THIS_MODULE,
+               .of_match_table = mcp251x_of_match,
                .pm = &mcp251x_can_pm_ops,
        },
-
        .id_table = mcp251x_id_table,
        .probe = mcp251x_can_probe,
        .remove = mcp251x_can_remove,
index ede8daa68275dfdefc4976e6261e29a01e93e93a..9142b473175c8bef4ae342d736c954b82b6de429 100644 (file)
@@ -252,8 +252,7 @@ static int el3_isa_id_sequence(__be16 *phys_addr)
                for (i = 0; i < el3_cards; i++) {
                        struct el3_private *lp = netdev_priv(el3_devs[i]);
                        if (lp->type == EL3_PNP &&
-                           !memcmp(phys_addr, el3_devs[i]->dev_addr,
-                                   ETH_ALEN)) {
+                           ether_addr_equal(phys_addr, el3_devs[i]->dev_addr)) {
                                if (el3_debug > 3)
                                        pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
                                                phys_addr[0] & 0xff, phys_addr[0] >> 8,
index 65926a956575acfc42a49428a9653c539199ec20..72cfff7d23a576f184bd6a0decf7dfa385b7fb4e 100644 (file)
@@ -42,9 +42,9 @@
 
 #include "7990.h"
 
-#define WRITERAP(lp,x) out_be16(lp->base + LANCE_RAP, (x))
-#define WRITERDP(lp,x) out_be16(lp->base + LANCE_RDP, (x))
-#define READRDP(lp) in_be16(lp->base + LANCE_RDP)
+#define WRITERAP(lp, x)        out_be16(lp->base + LANCE_RAP, (x))
+#define WRITERDP(lp, x)        out_be16(lp->base + LANCE_RDP, (x))
+#define READRDP(lp)    in_be16(lp->base + LANCE_RDP)
 
 #if defined(CONFIG_HPLANCE) || defined(CONFIG_HPLANCE_MODULE)
 #include "hplance.h"
@@ -56,9 +56,9 @@
 #if defined(CONFIG_MVME147_NET) || defined(CONFIG_MVME147_NET_MODULE)
 
 /* Lossage Factor Nine, Mr Sulu. */
-#define WRITERAP(lp,x) (lp->writerap(lp,x))
-#define WRITERDP(lp,x) (lp->writerdp(lp,x))
-#define READRDP(lp) (lp->readrdp(lp))
+#define WRITERAP(lp, x)        (lp->writerap(lp, x))
+#define WRITERDP(lp, x)        (lp->writerdp(lp, x))
+#define READRDP(lp)    (lp->readrdp(lp))
 
 #else
 
@@ -94,428 +94,436 @@ static inline __u16 READRDP(struct lance_private *lp)
 #ifdef UNDEF
 #define PRINT_RINGS() \
 do { \
-        int t; \
-        for (t=0; t < RX_RING_SIZE; t++) { \
-                printk("R%d: @(%02X %04X) len %04X, mblen %04X, bits %02X\n",\
-                       t, ib->brx_ring[t].rmd1_hadr, ib->brx_ring[t].rmd0,\
-                       ib->brx_ring[t].length,\
-                       ib->brx_ring[t].mblength, ib->brx_ring[t].rmd1_bits);\
-        }\
-        for (t=0; t < TX_RING_SIZE; t++) { \
-                printk("T%d: @(%02X %04X) len %04X, misc %04X, bits %02X\n",\
-                       t, ib->btx_ring[t].tmd1_hadr, ib->btx_ring[t].tmd0,\
-                       ib->btx_ring[t].length,\
-                       ib->btx_ring[t].misc, ib->btx_ring[t].tmd1_bits);\
-        }\
+       int t; \
+       for (t = 0; t < RX_RING_SIZE; t++) { \
+               printk("R%d: @(%02X %04X) len %04X, mblen %04X, bits %02X\n", \
+                      t, ib->brx_ring[t].rmd1_hadr, ib->brx_ring[t].rmd0, \
+                      ib->brx_ring[t].length, \
+                      ib->brx_ring[t].mblength, ib->brx_ring[t].rmd1_bits); \
+       \
+       for (t = 0; t < TX_RING_SIZE; t++) { \
+               printk("T%d: @(%02X %04X) len %04X, misc %04X, bits %02X\n", \
+                      t, ib->btx_ring[t].tmd1_hadr, ib->btx_ring[t].tmd0, \
+                      ib->btx_ring[t].length, \
+                      ib->btx_ring[t].misc, ib->btx_ring[t].tmd1_bits); \
+       \
 } while (0)
 #else
 #define PRINT_RINGS()
 #endif
 
 /* Load the CSR registers. The LANCE has to be STOPped when we do this! */
-static void load_csrs (struct lance_private *lp)
+static void load_csrs(struct lance_private *lp)
 {
-        volatile struct lance_init_block *aib = lp->lance_init_block;
-        int leptr;
+       volatile struct lance_init_block *aib = lp->lance_init_block;
+       int leptr;
 
-        leptr = LANCE_ADDR (aib);
+       leptr = LANCE_ADDR(aib);
 
-        WRITERAP(lp, LE_CSR1);                    /* load address of init block */
-        WRITERDP(lp, leptr & 0xFFFF);
-        WRITERAP(lp, LE_CSR2);
-        WRITERDP(lp, leptr >> 16);
-        WRITERAP(lp, LE_CSR3);
-        WRITERDP(lp, lp->busmaster_regval);       /* set byteswap/ALEctrl/byte ctrl */
+       WRITERAP(lp, LE_CSR1);                    /* load address of init block */
+       WRITERDP(lp, leptr & 0xFFFF);
+       WRITERAP(lp, LE_CSR2);
+       WRITERDP(lp, leptr >> 16);
+       WRITERAP(lp, LE_CSR3);
+       WRITERDP(lp, lp->busmaster_regval);       /* set byteswap/ALEctrl/byte ctrl */
 
-        /* Point back to csr0 */
-        WRITERAP(lp, LE_CSR0);
+       /* Point back to csr0 */
+       WRITERAP(lp, LE_CSR0);
 }
 
 /* #define to 0 or 1 appropriately */
 #define DEBUG_IRING 0
 /* Set up the Lance Rx and Tx rings and the init block */
-static void lance_init_ring (struct net_device *dev)
+static void lance_init_ring(struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */
-        int leptr;
-        int i;
-
-        aib = lp->lance_init_block;
-
-        lp->rx_new = lp->tx_new = 0;
-        lp->rx_old = lp->tx_old = 0;
-
-        ib->mode = LE_MO_PROM;                             /* normal, enable Tx & Rx */
-
-        /* Copy the ethernet address to the lance init block
-         * Notice that we do a byteswap if we're big endian.
-         * [I think this is the right criterion; at least, sunlance,
-         * a2065 and atarilance do the byteswap and lance.c (PC) doesn't.
-         * However, the datasheet says that the BSWAP bit doesn't affect
-         * the init block, so surely it should be low byte first for
-         * everybody? Um.]
-         * We could define the ib->physaddr as three 16bit values and
-         * use (addr[1] << 8) | addr[0] & co, but this is more efficient.
-         */
+       struct lance_private *lp = netdev_priv(dev);
+       volatile struct lance_init_block *ib = lp->init_block;
+       volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */
+       int leptr;
+       int i;
+
+       aib = lp->lance_init_block;
+
+       lp->rx_new = lp->tx_new = 0;
+       lp->rx_old = lp->tx_old = 0;
+
+       ib->mode = LE_MO_PROM;                             /* normal, enable Tx & Rx */
+
+       /* Copy the ethernet address to the lance init block
+        * Notice that we do a byteswap if we're big endian.
+        * [I think this is the right criterion; at least, sunlance,
+        * a2065 and atarilance do the byteswap and lance.c (PC) doesn't.
+        * However, the datasheet says that the BSWAP bit doesn't affect
+        * the init block, so surely it should be low byte first for
+        * everybody? Um.]
+        * We could define the ib->physaddr as three 16bit values and
+        * use (addr[1] << 8) | addr[0] & co, but this is more efficient.
+        */
 #ifdef __BIG_ENDIAN
-        ib->phys_addr [0] = dev->dev_addr [1];
-        ib->phys_addr [1] = dev->dev_addr [0];
-        ib->phys_addr [2] = dev->dev_addr [3];
-        ib->phys_addr [3] = dev->dev_addr [2];
-        ib->phys_addr [4] = dev->dev_addr [5];
-        ib->phys_addr [5] = dev->dev_addr [4];
+       ib->phys_addr[0] = dev->dev_addr[1];
+       ib->phys_addr[1] = dev->dev_addr[0];
+       ib->phys_addr[2] = dev->dev_addr[3];
+       ib->phys_addr[3] = dev->dev_addr[2];
+       ib->phys_addr[4] = dev->dev_addr[5];
+       ib->phys_addr[5] = dev->dev_addr[4];
 #else
-        for (i=0; i<6; i++)
-           ib->phys_addr[i] = dev->dev_addr[i];
+       for (i = 0; i < 6; i++)
+              ib->phys_addr[i] = dev->dev_addr[i];
 #endif
 
-        if (DEBUG_IRING)
-                printk ("TX rings:\n");
+       if (DEBUG_IRING)
+               printk("TX rings:\n");
 
        lp->tx_full = 0;
-        /* Setup the Tx ring entries */
-        for (i = 0; i < (1<<lp->lance_log_tx_bufs); i++) {
-                leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
-                ib->btx_ring [i].tmd0      = leptr;
-                ib->btx_ring [i].tmd1_hadr = leptr >> 16;
-                ib->btx_ring [i].tmd1_bits = 0;
-                ib->btx_ring [i].length    = 0xf000; /* The ones required by tmd2 */
-                ib->btx_ring [i].misc      = 0;
-                if (DEBUG_IRING)
-                   printk ("%d: 0x%8.8x\n", i, leptr);
-        }
-
-        /* Setup the Rx ring entries */
-        if (DEBUG_IRING)
-                printk ("RX rings:\n");
-        for (i = 0; i < (1<<lp->lance_log_rx_bufs); i++) {
-                leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
-
-                ib->brx_ring [i].rmd0      = leptr;
-                ib->brx_ring [i].rmd1_hadr = leptr >> 16;
-                ib->brx_ring [i].rmd1_bits = LE_R1_OWN;
-                /* 0xf000 == bits that must be one (reserved, presumably) */
-                ib->brx_ring [i].length    = -RX_BUFF_SIZE | 0xf000;
-                ib->brx_ring [i].mblength  = 0;
-                if (DEBUG_IRING)
-                        printk ("%d: 0x%8.8x\n", i, leptr);
-        }
-
-        /* Setup the initialization block */
-
-        /* Setup rx descriptor pointer */
-        leptr = LANCE_ADDR(&aib->brx_ring);
-        ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
-        ib->rx_ptr = leptr;
-        if (DEBUG_IRING)
-                printk ("RX ptr: %8.8x\n", leptr);
-
-        /* Setup tx descriptor pointer */
-        leptr = LANCE_ADDR(&aib->btx_ring);
-        ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
-        ib->tx_ptr = leptr;
-        if (DEBUG_IRING)
-                printk ("TX ptr: %8.8x\n", leptr);
-
-        /* Clear the multicast filter */
-        ib->filter [0] = 0;
-        ib->filter [1] = 0;
-        PRINT_RINGS();
+       /* Setup the Tx ring entries */
+       for (i = 0; i < (1 << lp->lance_log_tx_bufs); i++) {
+               leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
+               ib->btx_ring[i].tmd0      = leptr;
+               ib->btx_ring[i].tmd1_hadr = leptr >> 16;
+               ib->btx_ring[i].tmd1_bits = 0;
+               ib->btx_ring[i].length    = 0xf000; /* The ones required by tmd2 */
+               ib->btx_ring[i].misc      = 0;
+               if (DEBUG_IRING)
+                       printk("%d: 0x%8.8x\n", i, leptr);
+       }
+
+       /* Setup the Rx ring entries */
+       if (DEBUG_IRING)
+               printk("RX rings:\n");
+       for (i = 0; i < (1 << lp->lance_log_rx_bufs); i++) {
+               leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
+
+               ib->brx_ring[i].rmd0      = leptr;
+               ib->brx_ring[i].rmd1_hadr = leptr >> 16;
+               ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
+               /* 0xf000 == bits that must be one (reserved, presumably) */
+               ib->brx_ring[i].length    = -RX_BUFF_SIZE | 0xf000;
+               ib->brx_ring[i].mblength  = 0;
+               if (DEBUG_IRING)
+                       printk("%d: 0x%8.8x\n", i, leptr);
+       }
+
+       /* Setup the initialization block */
+
+       /* Setup rx descriptor pointer */
+       leptr = LANCE_ADDR(&aib->brx_ring);
+       ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
+       ib->rx_ptr = leptr;
+       if (DEBUG_IRING)
+               printk("RX ptr: %8.8x\n", leptr);
+
+       /* Setup tx descriptor pointer */
+       leptr = LANCE_ADDR(&aib->btx_ring);
+       ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
+       ib->tx_ptr = leptr;
+       if (DEBUG_IRING)
+               printk("TX ptr: %8.8x\n", leptr);
+
+       /* Clear the multicast filter */
+       ib->filter[0] = 0;
+       ib->filter[1] = 0;
+       PRINT_RINGS();
 }
 
 /* LANCE must be STOPped before we do this, too... */
-static int init_restart_lance (struct lance_private *lp)
+static int init_restart_lance(struct lance_private *lp)
 {
-        int i;
+       int i;
 
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_INIT);
+       WRITERAP(lp, LE_CSR0);
+       WRITERDP(lp, LE_C0_INIT);
 
-        /* Need a hook here for sunlance ledma stuff */
+       /* Need a hook here for sunlance ledma stuff */
 
-        /* Wait for the lance to complete initialization */
-        for (i = 0; (i < 100) && !(READRDP(lp) & (LE_C0_ERR | LE_C0_IDON)); i++)
-                barrier();
-        if ((i == 100) || (READRDP(lp) & LE_C0_ERR)) {
-                printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, READRDP(lp));
-                return -1;
-        }
+       /* Wait for the lance to complete initialization */
+       for (i = 0; (i < 100) && !(READRDP(lp) & (LE_C0_ERR | LE_C0_IDON)); i++)
+               barrier();
+       if ((i == 100) || (READRDP(lp) & LE_C0_ERR)) {
+               printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, READRDP(lp));
+               return -1;
+       }
 
-        /* Clear IDON by writing a "1", enable interrupts and start lance */
-        WRITERDP(lp, LE_C0_IDON);
-        WRITERDP(lp, LE_C0_INEA | LE_C0_STRT);
+       /* Clear IDON by writing a "1", enable interrupts and start lance */
+       WRITERDP(lp, LE_C0_IDON);
+       WRITERDP(lp, LE_C0_INEA | LE_C0_STRT);
 
-        return 0;
+       return 0;
 }
 
-static int lance_reset (struct net_device *dev)
+static int lance_reset(struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
-        int status;
+       struct lance_private *lp = netdev_priv(dev);
+       int status;
 
-        /* Stop the lance */
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_STOP);
+       /* Stop the lance */
+       WRITERAP(lp, LE_CSR0);
+       WRITERDP(lp, LE_C0_STOP);
 
-        load_csrs (lp);
-        lance_init_ring (dev);
-        dev->trans_start = jiffies; /* prevent tx timeout */
-        status = init_restart_lance (lp);
+       load_csrs(lp);
+       lance_init_ring(dev);
+       dev->trans_start = jiffies; /* prevent tx timeout */
+       status = init_restart_lance(lp);
 #ifdef DEBUG_DRIVER
-        printk ("Lance restart=%d\n", status);
+       printk("Lance restart=%d\n", status);
 #endif
-        return status;
+       return status;
 }
 
-static int lance_rx (struct net_device *dev)
+static int lance_rx(struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        volatile struct lance_rx_desc *rd;
-        unsigned char bits;
+       struct lance_private *lp = netdev_priv(dev);
+       volatile struct lance_init_block *ib = lp->init_block;
+       volatile struct lance_rx_desc *rd;
+       unsigned char bits;
 #ifdef TEST_HITS
-        int i;
+       int i;
 #endif
 
 #ifdef TEST_HITS
-        printk ("[");
-        for (i = 0; i < RX_RING_SIZE; i++) {
-                if (i == lp->rx_new)
-                        printk ("%s",
-                                ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X");
-                else
-                        printk ("%s",
-                                ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1");
-        }
-        printk ("]");
+       printk("[");
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               if (i == lp->rx_new)
+                       printk("%s",
+                              ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "_" : "X");
+               else
+                       printk("%s",
+                             ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "." : "1");
+       }
+       printk("]");
 #endif
 #ifdef CONFIG_HP300
        blinken_leds(0x40, 0);
 #endif
-        WRITERDP(lp, LE_C0_RINT | LE_C0_INEA);     /* ack Rx int, reenable ints */
-        for (rd = &ib->brx_ring [lp->rx_new];     /* For each Rx ring we own... */
-             !((bits = rd->rmd1_bits) & LE_R1_OWN);
-             rd = &ib->brx_ring [lp->rx_new]) {
-
-                /* We got an incomplete frame? */
-                if ((bits & LE_R1_POK) != LE_R1_POK) {
-                        dev->stats.rx_over_errors++;
-                        dev->stats.rx_errors++;
-                        continue;
-                } else if (bits & LE_R1_ERR) {
-                        /* Count only the end frame as a rx error,
-                         * not the beginning
-                         */
-                        if (bits & LE_R1_BUF) dev->stats.rx_fifo_errors++;
-                        if (bits & LE_R1_CRC) dev->stats.rx_crc_errors++;
-                        if (bits & LE_R1_OFL) dev->stats.rx_over_errors++;
-                        if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
-                        if (bits & LE_R1_EOP) dev->stats.rx_errors++;
-                } else {
+       WRITERDP(lp, LE_C0_RINT | LE_C0_INEA);     /* ack Rx int, reenable ints */
+       for (rd = &ib->brx_ring[lp->rx_new];     /* For each Rx ring we own... */
+            !((bits = rd->rmd1_bits) & LE_R1_OWN);
+            rd = &ib->brx_ring[lp->rx_new]) {
+
+               /* We got an incomplete frame? */
+               if ((bits & LE_R1_POK) != LE_R1_POK) {
+                       dev->stats.rx_over_errors++;
+                       dev->stats.rx_errors++;
+                       continue;
+               } else if (bits & LE_R1_ERR) {
+                       /* Count only the end frame as a rx error,
+                        * not the beginning
+                        */
+                       if (bits & LE_R1_BUF)
+                               dev->stats.rx_fifo_errors++;
+                       if (bits & LE_R1_CRC)
+                               dev->stats.rx_crc_errors++;
+                       if (bits & LE_R1_OFL)
+                               dev->stats.rx_over_errors++;
+                       if (bits & LE_R1_FRA)
+                               dev->stats.rx_frame_errors++;
+                       if (bits & LE_R1_EOP)
+                               dev->stats.rx_errors++;
+               } else {
                        int len = (rd->mblength & 0xfff) - 4;
                        struct sk_buff *skb = netdev_alloc_skb(dev, len + 2);
 
-                        if (!skb) {
-                                dev->stats.rx_dropped++;
-                                rd->mblength = 0;
-                                rd->rmd1_bits = LE_R1_OWN;
-                                lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
-                                return 0;
-                        }
-
-                        skb_reserve (skb, 2);           /* 16 byte align */
-                        skb_put (skb, len);             /* make room */
-                        skb_copy_to_linear_data(skb,
-                                         (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
-                                         len);
-                        skb->protocol = eth_type_trans (skb, dev);
-                       netif_rx (skb);
+                       if (!skb) {
+                               dev->stats.rx_dropped++;
+                               rd->mblength = 0;
+                               rd->rmd1_bits = LE_R1_OWN;
+                               lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
+                               return 0;
+                       }
+
+                       skb_reserve(skb, 2);           /* 16 byte align */
+                       skb_put(skb, len);             /* make room */
+                       skb_copy_to_linear_data(skb,
+                                        (unsigned char *)&(ib->rx_buf[lp->rx_new][0]),
+                                        len);
+                       skb->protocol = eth_type_trans(skb, dev);
+                       netif_rx(skb);
                        dev->stats.rx_packets++;
                        dev->stats.rx_bytes += len;
-                }
-
-                /* Return the packet to the pool */
-                rd->mblength = 0;
-                rd->rmd1_bits = LE_R1_OWN;
-                lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
-        }
-        return 0;
+               }
+
+               /* Return the packet to the pool */
+               rd->mblength = 0;
+               rd->rmd1_bits = LE_R1_OWN;
+               lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
+       }
+       return 0;
 }
 
-static int lance_tx (struct net_device *dev)
+static int lance_tx(struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        volatile struct lance_tx_desc *td;
-        int i, j;
-        int status;
+       struct lance_private *lp = netdev_priv(dev);
+       volatile struct lance_init_block *ib = lp->init_block;
+       volatile struct lance_tx_desc *td;
+       int i, j;
+       int status;
 
 #ifdef CONFIG_HP300
        blinken_leds(0x80, 0);
 #endif
-        /* csr0 is 2f3 */
-        WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
-        /* csr0 is 73 */
-
-        j = lp->tx_old;
-        for (i = j; i != lp->tx_new; i = j) {
-                td = &ib->btx_ring [i];
-
-                /* If we hit a packet not owned by us, stop */
-                if (td->tmd1_bits & LE_T1_OWN)
-                        break;
-
-                if (td->tmd1_bits & LE_T1_ERR) {
-                        status = td->misc;
-
-                        dev->stats.tx_errors++;
-                        if (status & LE_T3_RTY)  dev->stats.tx_aborted_errors++;
-                        if (status & LE_T3_LCOL) dev->stats.tx_window_errors++;
-
-                        if (status & LE_T3_CLOS) {
-                                dev->stats.tx_carrier_errors++;
-                                if (lp->auto_select) {
-                                        lp->tpe = 1 - lp->tpe;
-                                        printk("%s: Carrier Lost, trying %s\n",
-                                               dev->name, lp->tpe?"TPE":"AUI");
-                                        /* Stop the lance */
-                                        WRITERAP(lp, LE_CSR0);
-                                        WRITERDP(lp, LE_C0_STOP);
-                                        lance_init_ring (dev);
-                                        load_csrs (lp);
-                                        init_restart_lance (lp);
-                                        return 0;
-                                }
-                        }
-
-                        /* buffer errors and underflows turn off the transmitter */
-                        /* Restart the adapter */
-                        if (status & (LE_T3_BUF|LE_T3_UFL)) {
-                                dev->stats.tx_fifo_errors++;
-
-                                printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
-                                        dev->name);
-                                /* Stop the lance */
-                                WRITERAP(lp, LE_CSR0);
-                                WRITERDP(lp, LE_C0_STOP);
-                                lance_init_ring (dev);
-                                load_csrs (lp);
-                                init_restart_lance (lp);
-                                return 0;
-                        }
-                } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
-                        /*
-                         * So we don't count the packet more than once.
-                         */
-                        td->tmd1_bits &= ~(LE_T1_POK);
-
-                        /* One collision before packet was sent. */
-                        if (td->tmd1_bits & LE_T1_EONE)
-                                dev->stats.collisions++;
-
-                        /* More than one collision, be optimistic. */
-                        if (td->tmd1_bits & LE_T1_EMORE)
-                                dev->stats.collisions += 2;
-
-                        dev->stats.tx_packets++;
-                }
-
-                j = (j + 1) & lp->tx_ring_mod_mask;
-        }
-        lp->tx_old = j;
-        WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
-        return 0;
+       /* csr0 is 2f3 */
+       WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
+       /* csr0 is 73 */
+
+       j = lp->tx_old;
+       for (i = j; i != lp->tx_new; i = j) {
+               td = &ib->btx_ring[i];
+
+               /* If we hit a packet not owned by us, stop */
+               if (td->tmd1_bits & LE_T1_OWN)
+                       break;
+
+               if (td->tmd1_bits & LE_T1_ERR) {
+                       status = td->misc;
+
+                       dev->stats.tx_errors++;
+                       if (status & LE_T3_RTY)
+                               dev->stats.tx_aborted_errors++;
+                       if (status & LE_T3_LCOL)
+                               dev->stats.tx_window_errors++;
+
+                       if (status & LE_T3_CLOS) {
+                               dev->stats.tx_carrier_errors++;
+                               if (lp->auto_select) {
+                                       lp->tpe = 1 - lp->tpe;
+                                       printk("%s: Carrier Lost, trying %s\n",
+                                              dev->name,
+                                              lp->tpe ? "TPE" : "AUI");
+                                       /* Stop the lance */
+                                       WRITERAP(lp, LE_CSR0);
+                                       WRITERDP(lp, LE_C0_STOP);
+                                       lance_init_ring(dev);
+                                       load_csrs(lp);
+                                       init_restart_lance(lp);
+                                       return 0;
+                               }
+                       }
+
+                       /* buffer errors and underflows turn off the transmitter */
+                       /* Restart the adapter */
+                       if (status & (LE_T3_BUF|LE_T3_UFL)) {
+                               dev->stats.tx_fifo_errors++;
+
+                               printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
+                                      dev->name);
+                               /* Stop the lance */
+                               WRITERAP(lp, LE_CSR0);
+                               WRITERDP(lp, LE_C0_STOP);
+                               lance_init_ring(dev);
+                               load_csrs(lp);
+                               init_restart_lance(lp);
+                               return 0;
+                       }
+               } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
+                       /*
+                        * So we don't count the packet more than once.
+                        */
+                       td->tmd1_bits &= ~(LE_T1_POK);
+
+                       /* One collision before packet was sent. */
+                       if (td->tmd1_bits & LE_T1_EONE)
+                               dev->stats.collisions++;
+
+                       /* More than one collision, be optimistic. */
+                       if (td->tmd1_bits & LE_T1_EMORE)
+                               dev->stats.collisions += 2;
+
+                       dev->stats.tx_packets++;
+               }
+
+               j = (j + 1) & lp->tx_ring_mod_mask;
+       }
+       lp->tx_old = j;
+       WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
+       return 0;
 }
 
 static irqreturn_t
-lance_interrupt (int irq, void *dev_id)
+lance_interrupt(int irq, void *dev_id)
 {
-        struct net_device *dev = (struct net_device *)dev_id;
-        struct lance_private *lp = netdev_priv(dev);
-        int csr0;
+       struct net_device *dev = (struct net_device *)dev_id;
+       struct lance_private *lp = netdev_priv(dev);
+       int csr0;
 
-       spin_lock (&lp->devlock);
+       spin_lock(&lp->devlock);
 
-        WRITERAP(lp, LE_CSR0);              /* LANCE Controller Status */
-        csr0 = READRDP(lp);
+       WRITERAP(lp, LE_CSR0);              /* LANCE Controller Status */
+       csr0 = READRDP(lp);
 
-        PRINT_RINGS();
+       PRINT_RINGS();
 
-        if (!(csr0 & LE_C0_INTR)) {     /* Check if any interrupt has */
-               spin_unlock (&lp->devlock);
-                return IRQ_NONE;        /* been generated by the Lance. */
+       if (!(csr0 & LE_C0_INTR)) {     /* Check if any interrupt has */
+               spin_unlock(&lp->devlock);
+               return IRQ_NONE;        /* been generated by the Lance. */
        }
 
-        /* Acknowledge all the interrupt sources ASAP */
-        WRITERDP(lp, csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT));
-
-        if ((csr0 & LE_C0_ERR)) {
-                /* Clear the error condition */
-                WRITERDP(lp, LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA);
-        }
-
-        if (csr0 & LE_C0_RINT)
-                lance_rx (dev);
-
-        if (csr0 & LE_C0_TINT)
-                lance_tx (dev);
-
-        /* Log misc errors. */
-        if (csr0 & LE_C0_BABL)
-                dev->stats.tx_errors++;       /* Tx babble. */
-        if (csr0 & LE_C0_MISS)
-                dev->stats.rx_errors++;       /* Missed a Rx frame. */
-        if (csr0 & LE_C0_MERR) {
-                printk("%s: Bus master arbitration failure, status %4.4x.\n",
-                       dev->name, csr0);
-                /* Restart the chip. */
-                WRITERDP(lp, LE_C0_STRT);
-        }
-
-        if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) {
+       /* Acknowledge all the interrupt sources ASAP */
+       WRITERDP(lp, csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT));
+
+       if ((csr0 & LE_C0_ERR)) {
+               /* Clear the error condition */
+               WRITERDP(lp, LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA);
+       }
+
+       if (csr0 & LE_C0_RINT)
+               lance_rx(dev);
+
+       if (csr0 & LE_C0_TINT)
+               lance_tx(dev);
+
+       /* Log misc errors. */
+       if (csr0 & LE_C0_BABL)
+               dev->stats.tx_errors++;       /* Tx babble. */
+       if (csr0 & LE_C0_MISS)
+               dev->stats.rx_errors++;       /* Missed a Rx frame. */
+       if (csr0 & LE_C0_MERR) {
+               printk("%s: Bus master arbitration failure, status %4.4x.\n",
+                      dev->name, csr0);
+               /* Restart the chip. */
+               WRITERDP(lp, LE_C0_STRT);
+       }
+
+       if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) {
                lp->tx_full = 0;
-               netif_wake_queue (dev);
-        }
+               netif_wake_queue(dev);
+       }
 
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA);
+       WRITERAP(lp, LE_CSR0);
+       WRITERDP(lp, LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA);
 
-       spin_unlock (&lp->devlock);
+       spin_unlock(&lp->devlock);
        return IRQ_HANDLED;
 }
 
-int lance_open (struct net_device *dev)
+int lance_open(struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
+       struct lance_private *lp = netdev_priv(dev);
        int res;
 
-        /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
-        if (request_irq(lp->irq, lance_interrupt, IRQF_SHARED, lp->name, dev))
-                return -EAGAIN;
+       /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
+       if (request_irq(lp->irq, lance_interrupt, IRQF_SHARED, lp->name, dev))
+               return -EAGAIN;
 
-        res = lance_reset(dev);
+       res = lance_reset(dev);
        spin_lock_init(&lp->devlock);
-       netif_start_queue (dev);
+       netif_start_queue(dev);
 
        return res;
 }
 EXPORT_SYMBOL_GPL(lance_open);
 
-int lance_close (struct net_device *dev)
+int lance_close(struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
+       struct lance_private *lp = netdev_priv(dev);
 
-       netif_stop_queue (dev);
+       netif_stop_queue(dev);
 
-        /* Stop the LANCE */
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_STOP);
+       /* Stop the LANCE */
+       WRITERAP(lp, LE_CSR0);
+       WRITERDP(lp, LE_C0_STOP);
 
-        free_irq(lp->irq, dev);
+       free_irq(lp->irq, dev);
 
-        return 0;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(lance_close);
 
@@ -524,122 +532,122 @@ void lance_tx_timeout(struct net_device *dev)
        printk("lance_tx_timeout\n");
        lance_reset(dev);
        dev->trans_start = jiffies; /* prevent tx timeout */
-       netif_wake_queue (dev);
+       netif_wake_queue(dev);
 }
 EXPORT_SYMBOL_GPL(lance_tx_timeout);
 
-int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
+int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        int entry, skblen, len;
-        static int outs;
+       struct lance_private *lp = netdev_priv(dev);
+       volatile struct lance_init_block *ib = lp->init_block;
+       int entry, skblen, len;
+       static int outs;
        unsigned long flags;
 
-        if (!TX_BUFFS_AVAIL)
-                return NETDEV_TX_LOCKED;
+       if (!TX_BUFFS_AVAIL)
+               return NETDEV_TX_LOCKED;
 
-       netif_stop_queue (dev);
+       netif_stop_queue(dev);
 
-        skblen = skb->len;
+       skblen = skb->len;
 
 #ifdef DEBUG_DRIVER
-        /* dump the packet */
-        {
-                int i;
-
-                for (i = 0; i < 64; i++) {
-                        if ((i % 16) == 0)
-                                printk ("\n");
-                        printk ("%2.2x ", skb->data [i]);
-                }
-        }
+       /* dump the packet */
+       {
+               int i;
+
+               for (i = 0; i < 64; i++) {
+                       if ((i % 16) == 0)
+                               printk("\n");
+                       printk("%2.2x ", skb->data[i]);
+               }
+       }
 #endif
-        len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
-        entry = lp->tx_new & lp->tx_ring_mod_mask;
-        ib->btx_ring [entry].length = (-len) | 0xf000;
-        ib->btx_ring [entry].misc = 0;
+       len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+       entry = lp->tx_new & lp->tx_ring_mod_mask;
+       ib->btx_ring[entry].length = (-len) | 0xf000;
+       ib->btx_ring[entry].misc = 0;
 
        if (skb->len < ETH_ZLEN)
                memset((void *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
-        skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
+       skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
 
-        /* Now, give the packet to the lance */
-        ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
-        lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
+       /* Now, give the packet to the lance */
+       ib->btx_ring[entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
+       lp->tx_new = (lp->tx_new + 1) & lp->tx_ring_mod_mask;
 
-        outs++;
-        /* Kick the lance: transmit now */
-        WRITERDP(lp, LE_C0_INEA | LE_C0_TDMD);
-        dev_kfree_skb (skb);
+       outs++;
+       /* Kick the lance: transmit now */
+       WRITERDP(lp, LE_C0_INEA | LE_C0_TDMD);
+       dev_kfree_skb(skb);
 
-       spin_lock_irqsave (&lp->devlock, flags);
-        if (TX_BUFFS_AVAIL)
-               netif_start_queue (dev);
+       spin_lock_irqsave(&lp->devlock, flags);
+       if (TX_BUFFS_AVAIL)
+               netif_start_queue(dev);
        else
                lp->tx_full = 1;
-       spin_unlock_irqrestore (&lp->devlock, flags);
+       spin_unlock_irqrestore(&lp->devlock, flags);
 
-        return NETDEV_TX_OK;
+       return NETDEV_TX_OK;
 }
 EXPORT_SYMBOL_GPL(lance_start_xmit);
 
 /* taken from the depca driver via a2065.c */
-static void lance_load_multicast (struct net_device *dev)
+static void lance_load_multicast(struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        volatile u16 *mcast_table = (u16 *)&ib->filter;
+       struct lance_private *lp = netdev_priv(dev);
+       volatile struct lance_init_block *ib = lp->init_block;
+       volatile u16 *mcast_table = (u16 *)&ib->filter;
        struct netdev_hw_addr *ha;
-        u32 crc;
-
-        /* set all multicast bits */
-        if (dev->flags & IFF_ALLMULTI){
-                ib->filter [0] = 0xffffffff;
-                ib->filter [1] = 0xffffffff;
-                return;
-        }
-        /* clear the multicast filter */
-        ib->filter [0] = 0;
-        ib->filter [1] = 0;
-
-        /* Add addresses */
+       u32 crc;
+
+       /* set all multicast bits */
+       if (dev->flags & IFF_ALLMULTI) {
+               ib->filter[0] = 0xffffffff;
+               ib->filter[1] = 0xffffffff;
+               return;
+       }
+       /* clear the multicast filter */
+       ib->filter[0] = 0;
+       ib->filter[1] = 0;
+
+       /* Add addresses */
        netdev_for_each_mc_addr(ha, dev) {
                crc = ether_crc_le(6, ha->addr);
-                crc = crc >> 26;
-                mcast_table [crc >> 4] |= 1 << (crc & 0xf);
-        }
+               crc = crc >> 26;
+               mcast_table[crc >> 4] |= 1 << (crc & 0xf);
+       }
 }
 
 
-void lance_set_multicast (struct net_device *dev)
+void lance_set_multicast(struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
+       struct lance_private *lp = netdev_priv(dev);
+       volatile struct lance_init_block *ib = lp->init_block;
        int stopped;
 
        stopped = netif_queue_stopped(dev);
        if (!stopped)
-               netif_stop_queue (dev);
-
-        while (lp->tx_old != lp->tx_new)
-                schedule();
+               netif_stop_queue(dev);
 
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_STOP);
-        lance_init_ring (dev);
+       while (lp->tx_old != lp->tx_new)
+               schedule();
 
-        if (dev->flags & IFF_PROMISC) {
-                ib->mode |= LE_MO_PROM;
-        } else {
-                ib->mode &= ~LE_MO_PROM;
-                lance_load_multicast (dev);
-        }
-        load_csrs (lp);
-        init_restart_lance (lp);
+       WRITERAP(lp, LE_CSR0);
+       WRITERDP(lp, LE_C0_STOP);
+       lance_init_ring(dev);
+
+       if (dev->flags & IFF_PROMISC) {
+               ib->mode |= LE_MO_PROM;
+       } else {
+               ib->mode &= ~LE_MO_PROM;
+               lance_load_multicast(dev);
+       }
+       load_csrs(lp);
+       init_restart_lance(lp);
 
        if (!stopped)
-               netif_start_queue (dev);
+               netif_start_queue(dev);
 }
 EXPORT_SYMBOL_GPL(lance_set_multicast);
 
@@ -648,10 +656,10 @@ void lance_poll(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
 
-       spin_lock (&lp->devlock);
+       spin_lock(&lp->devlock);
        WRITERAP(lp, LE_CSR0);
        WRITERDP(lp, LE_C0_STRT);
-       spin_unlock (&lp->devlock);
+       spin_unlock(&lp->devlock);
        lance_interrupt(dev->irq, dev);
 }
 #endif
index ae33a99bf47626695b239cdb78941ea09b723b02..e9e0be3138049d59f544d027cca11076cd8db3db 100644 (file)
 #define LANCE_LOG_RX_BUFFERS 3
 #endif
 
-#define TX_RING_SIZE (1<<LANCE_LOG_TX_BUFFERS)
-#define RX_RING_SIZE (1<<LANCE_LOG_RX_BUFFERS)
-#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
-#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
-#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
-#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
-#define PKT_BUFF_SIZE (1544)
-#define RX_BUFF_SIZE PKT_BUFF_SIZE
-#define TX_BUFF_SIZE PKT_BUFF_SIZE
+#define TX_RING_SIZE           (1 << LANCE_LOG_TX_BUFFERS)
+#define RX_RING_SIZE           (1 << LANCE_LOG_RX_BUFFERS)
+#define TX_RING_MOD_MASK       (TX_RING_SIZE - 1)
+#define RX_RING_MOD_MASK       (RX_RING_SIZE - 1)
+#define TX_RING_LEN_BITS       ((LANCE_LOG_TX_BUFFERS) << 29)
+#define RX_RING_LEN_BITS       ((LANCE_LOG_RX_BUFFERS) << 29)
+#define PKT_BUFF_SIZE          (1544)
+#define RX_BUFF_SIZE           PKT_BUFF_SIZE
+#define TX_BUFF_SIZE           PKT_BUFF_SIZE
 
 /* Each receive buffer is described by a receive message descriptor (RMD) */
 struct lance_rx_desc {
-       volatile unsigned short rmd0;        /* low address of packet */
-       volatile unsigned char  rmd1_bits;   /* descriptor bits */
-       volatile unsigned char  rmd1_hadr;   /* high address of packet */
-       volatile short    length;           /* This length is 2s complement (negative)!
-                                    * Buffer length
-                                    */
-       volatile unsigned short mblength;    /* Actual number of bytes received */
+       volatile unsigned short rmd0;       /* low address of packet */
+       volatile unsigned char  rmd1_bits;  /* descriptor bits */
+       volatile unsigned char  rmd1_hadr;  /* high address of packet */
+       volatile short    length;           /* This length is 2s complement (negative)!
+                                            * Buffer length */
+       volatile unsigned short mblength;   /* Actual number of bytes received */
 };
 
 /* Ditto for TMD: */
 struct lance_tx_desc {
-       volatile unsigned short tmd0;        /* low address of packet */
-       volatile unsigned char  tmd1_bits;   /* descriptor bits */
-       volatile unsigned char  tmd1_hadr;   /* high address of packet */
-       volatile short    length;                   /* Length is 2s complement (negative)! */
+       volatile unsigned short tmd0;       /* low address of packet */
+       volatile unsigned char  tmd1_bits;  /* descriptor bits */
+       volatile unsigned char  tmd1_hadr;  /* high address of packet */
+       volatile short    length;           /* Length is 2s complement (negative)! */
        volatile unsigned short misc;
 };
 
@@ -71,181 +70,178 @@ struct lance_tx_desc {
  * init block,the Tx and Rx rings and the buffers together in memory:
  */
 struct lance_init_block {
-        volatile unsigned short mode;            /* Pre-set mode (reg. 15) */
-        volatile unsigned char phys_addr[6];     /* Physical ethernet address */
-        volatile unsigned filter[2];             /* Multicast filter (64 bits) */
-
-        /* Receive and transmit ring base, along with extra bits. */
-        volatile unsigned short rx_ptr;          /* receive descriptor addr */
-        volatile unsigned short rx_len;          /* receive len and high addr */
-        volatile unsigned short tx_ptr;          /* transmit descriptor addr */
-        volatile unsigned short tx_len;          /* transmit len and high addr */
-
-        /* The Tx and Rx ring entries must be aligned on 8-byte boundaries.
-         * This will be true if this whole struct is 8-byte aligned.
-         */
-        volatile struct lance_tx_desc btx_ring[TX_RING_SIZE];
-        volatile struct lance_rx_desc brx_ring[RX_RING_SIZE];
-
-        volatile char   tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
-        volatile char   rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
-        /* we use this just to make the struct big enough that we can move its startaddr
-         * in order to force alignment to an eight byte boundary.
-         */
+       volatile unsigned short mode;           /* Pre-set mode (reg. 15) */
+       volatile unsigned char phys_addr[6];    /* Physical ethernet address */
+       volatile unsigned filter[2];            /* Multicast filter (64 bits) */
+
+       /* Receive and transmit ring base, along with extra bits. */
+       volatile unsigned short rx_ptr;         /* receive descriptor addr */
+       volatile unsigned short rx_len;         /* receive len and high addr */
+       volatile unsigned short tx_ptr;         /* transmit descriptor addr */
+       volatile unsigned short tx_len;         /* transmit len and high addr */
+
+       /* The Tx and Rx ring entries must be aligned on 8-byte boundaries.
+        * This will be true if this whole struct is 8-byte aligned.
+        */
+       volatile struct lance_tx_desc btx_ring[TX_RING_SIZE];
+       volatile struct lance_rx_desc brx_ring[RX_RING_SIZE];
+
+       volatile char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE];
+       volatile char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE];
+       /* we use this just to make the struct big enough that we can move its startaddr
+        * in order to force alignment to an eight byte boundary.
+        */
 };
 
 /* This is where we keep all the stuff the driver needs to know about.
  * I'm definitely unhappy about the mechanism for allowing specific
  * drivers to add things...
  */
-struct lance_private
-{
-        char *name;
+struct lance_private {
+       const char *name;
        unsigned long base;
-        volatile struct lance_init_block *init_block; /* CPU address of RAM */
-        volatile struct lance_init_block *lance_init_block; /* LANCE address of RAM */
+       volatile struct lance_init_block *init_block; /* CPU address of RAM */
+       volatile struct lance_init_block *lance_init_block; /* LANCE address of RAM */
 
-        int rx_new, tx_new;
-        int rx_old, tx_old;
+       int rx_new, tx_new;
+       int rx_old, tx_old;
 
-        int lance_log_rx_bufs, lance_log_tx_bufs;
-        int rx_ring_mod_mask, tx_ring_mod_mask;
+       int lance_log_rx_bufs, lance_log_tx_bufs;
+       int rx_ring_mod_mask, tx_ring_mod_mask;
 
-        int tpe;                                  /* TPE is selected */
-        int auto_select;                          /* cable-selection is by carrier */
-        unsigned short busmaster_regval;
+       int tpe;                        /* TPE is selected */
+       int auto_select;                /* cable-selection is by carrier */
+       unsigned short busmaster_regval;
 
-        unsigned int irq;                         /* IRQ to register */
+       unsigned int irq;               /* IRQ to register */
 
-        /* This is because the HP LANCE is disgusting and you have to check
-         * a DIO-specific register every time you read/write the LANCE regs :-<
-         * [could we get away with making these some sort of macro?]
-         */
-        void (*writerap)(void *, unsigned short);
-        void (*writerdp)(void *, unsigned short);
-        unsigned short (*readrdp)(void *);
+       /* This is because the HP LANCE is disgusting and you have to check
+        * a DIO-specific register every time you read/write the LANCE regs :-<
+        * [could we get away with making these some sort of macro?]
+        */
+       void (*writerap)(void *, unsigned short);
+       void (*writerdp)(void *, unsigned short);
+       unsigned short (*readrdp)(void *);
        spinlock_t devlock;
        char tx_full;
 };
 
 /*
- *              Am7990 Control and Status Registers
+ *             Am7990 Control and Status Registers
  */
-#define LE_CSR0         0x0000          /* LANCE Controller Status */
-#define LE_CSR1         0x0001          /* IADR[15:0] (bit0==0 ie word aligned) */
-#define LE_CSR2         0x0002          /* IADR[23:16] (high bits reserved) */
-#define LE_CSR3         0x0003          /* Misc */
+#define LE_CSR0                0x0000  /* LANCE Controller Status */
+#define LE_CSR1                0x0001  /* IADR[15:0] (bit0==0 ie word aligned) */
+#define LE_CSR2                0x0002  /* IADR[23:16] (high bits reserved) */
+#define LE_CSR3                0x0003  /* Misc */
 
 /*
  *             Bit definitions for CSR0 (LANCE Controller Status)
  */
-#define LE_C0_ERR      0x8000          /* Error = BABL | CERR | MISS | MERR */
-#define LE_C0_BABL     0x4000          /* Babble: Transmitted too many bits */
-#define LE_C0_CERR     0x2000          /* No Heartbeat (10BASE-T) */
-#define LE_C0_MISS     0x1000          /* Missed Frame (no rx buffer to put it in) */
-#define LE_C0_MERR     0x0800          /* Memory Error */
-#define LE_C0_RINT     0x0400          /* Receive Interrupt */
-#define LE_C0_TINT     0x0200          /* Transmit Interrupt */
-#define LE_C0_IDON     0x0100          /* Initialization Done */
-#define LE_C0_INTR     0x0080          /* Interrupt Flag
-                                         = BABL | MISS | MERR | RINT | TINT | IDON */
-#define LE_C0_INEA     0x0040          /* Interrupt Enable */
-#define LE_C0_RXON     0x0020          /* Receive On */
-#define LE_C0_TXON     0x0010          /* Transmit On */
-#define LE_C0_TDMD     0x0008          /* Transmit Demand */
-#define LE_C0_STOP     0x0004          /* Stop */
-#define LE_C0_STRT     0x0002          /* Start */
-#define LE_C0_INIT     0x0001          /* Initialize */
+#define LE_C0_ERR      0x8000  /* Error = BABL | CERR | MISS | MERR */
+#define LE_C0_BABL     0x4000  /* Babble: Transmitted too many bits */
+#define LE_C0_CERR     0x2000  /* No Heartbeat (10BASE-T) */
+#define LE_C0_MISS     0x1000  /* Missed Frame (no rx buffer to put it in) */
+#define LE_C0_MERR     0x0800  /* Memory Error */
+#define LE_C0_RINT     0x0400  /* Receive Interrupt */
+#define LE_C0_TINT     0x0200  /* Transmit Interrupt */
+#define LE_C0_IDON     0x0100  /* Initialization Done */
+#define LE_C0_INTR     0x0080  /* Interrupt Flag
+                                  = BABL | MISS | MERR | RINT | TINT | IDON */
+#define LE_C0_INEA     0x0040  /* Interrupt Enable */
+#define LE_C0_RXON     0x0020  /* Receive On */
+#define LE_C0_TXON     0x0010  /* Transmit On */
+#define LE_C0_TDMD     0x0008  /* Transmit Demand */
+#define LE_C0_STOP     0x0004  /* Stop */
+#define LE_C0_STRT     0x0002  /* Start */
+#define LE_C0_INIT     0x0001  /* Initialize */
 
 
 /*
  *             Bit definitions for CSR3
  */
-#define LE_C3_BSWP     0x0004          /* Byte Swap
-                                          (on for big endian byte order) */
-#define LE_C3_ACON     0x0002          /* ALE Control
-                                          (on for active low ALE) */
-#define LE_C3_BCON     0x0001          /* Byte Control */
+#define LE_C3_BSWP     0x0004  /* Byte Swap (on for big endian byte order) */
+#define LE_C3_ACON     0x0002  /* ALE Control (on for active low ALE) */
+#define LE_C3_BCON     0x0001  /* Byte Control */
 
 
 /*
  *             Mode Flags
  */
-#define LE_MO_PROM     0x8000          /* Promiscuous Mode */
+#define LE_MO_PROM     0x8000  /* Promiscuous Mode */
 /* these next ones 0x4000 -- 0x0080 are not available on the LANCE 7990,
  * but they are in NetBSD's am7990.h, presumably for backwards-compatible chips
  */
-#define LE_MO_DRCVBC  0x4000          /* disable receive broadcast */
-#define LE_MO_DRCVPA  0x2000          /* disable physical address detection */
-#define LE_MO_DLNKTST 0x1000          /* disable link status */
-#define LE_MO_DAPC    0x0800          /* disable automatic polarity correction */
-#define LE_MO_MENDECL 0x0400          /* MENDEC loopback mode */
-#define LE_MO_LRTTSEL 0x0200          /* lower RX threshold / TX mode selection */
-#define LE_MO_PSEL1   0x0100          /* port selection bit1 */
-#define LE_MO_PSEL0   0x0080          /* port selection bit0 */
+#define LE_MO_DRCVBC   0x4000  /* disable receive broadcast */
+#define LE_MO_DRCVPA   0x2000  /* disable physical address detection */
+#define LE_MO_DLNKTST  0x1000  /* disable link status */
+#define LE_MO_DAPC     0x0800  /* disable automatic polarity correction */
+#define LE_MO_MENDECL  0x0400  /* MENDEC loopback mode */
+#define LE_MO_LRTTSEL  0x0200  /* lower RX threshold / TX mode selection */
+#define LE_MO_PSEL1    0x0100  /* port selection bit1 */
+#define LE_MO_PSEL0    0x0080  /* port selection bit0 */
 /* and this one is from the C-LANCE data sheet... */
-#define LE_MO_EMBA      0x0080          /* Enable Modified Backoff Algorithm
-                                           (C-LANCE, not original LANCE) */
-#define LE_MO_INTL     0x0040          /* Internal Loopback */
-#define LE_MO_DRTY     0x0020          /* Disable Retry */
-#define LE_MO_FCOLL    0x0010          /* Force Collision */
-#define LE_MO_DXMTFCS  0x0008          /* Disable Transmit CRC */
-#define LE_MO_LOOP     0x0004          /* Loopback Enable */
-#define LE_MO_DTX      0x0002          /* Disable Transmitter */
-#define LE_MO_DRX      0x0001          /* Disable Receiver */
+#define LE_MO_EMBA     0x0080  /* Enable Modified Backoff Algorithm
+                                  (C-LANCE, not original LANCE) */
+#define LE_MO_INTL     0x0040  /* Internal Loopback */
+#define LE_MO_DRTY     0x0020  /* Disable Retry */
+#define LE_MO_FCOLL    0x0010  /* Force Collision */
+#define LE_MO_DXMTFCS  0x0008  /* Disable Transmit CRC */
+#define LE_MO_LOOP     0x0004  /* Loopback Enable */
+#define LE_MO_DTX      0x0002  /* Disable Transmitter */
+#define LE_MO_DRX      0x0001  /* Disable Receiver */
 
 
 /*
  *             Receive Flags
  */
-#define LE_R1_OWN      0x80            /* LANCE owns the descriptor */
-#define LE_R1_ERR      0x40            /* Error */
-#define LE_R1_FRA      0x20            /* Framing Error */
-#define LE_R1_OFL      0x10            /* Overflow Error */
-#define LE_R1_CRC      0x08            /* CRC Error */
-#define LE_R1_BUF      0x04            /* Buffer Error */
-#define LE_R1_SOP      0x02            /* Start of Packet */
-#define LE_R1_EOP      0x01            /* End of Packet */
-#define LE_R1_POK       0x03           /* Packet is complete: SOP + EOP */
+#define LE_R1_OWN      0x80    /* LANCE owns the descriptor */
+#define LE_R1_ERR      0x40    /* Error */
+#define LE_R1_FRA      0x20    /* Framing Error */
+#define LE_R1_OFL      0x10    /* Overflow Error */
+#define LE_R1_CRC      0x08    /* CRC Error */
+#define LE_R1_BUF      0x04    /* Buffer Error */
+#define LE_R1_SOP      0x02    /* Start of Packet */
+#define LE_R1_EOP      0x01    /* End of Packet */
+#define LE_R1_POK      0x03    /* Packet is complete: SOP + EOP */
 
 
 /*
  *             Transmit Flags
  */
-#define LE_T1_OWN      0x80            /* LANCE owns the descriptor */
-#define LE_T1_ERR      0x40            /* Error */
-#define LE_T1_RES      0x20            /* Reserved, LANCE writes this with a zero */
-#define LE_T1_EMORE    0x10            /* More than one retry needed */
-#define LE_T1_EONE     0x08            /* One retry needed */
-#define LE_T1_EDEF     0x04            /* Deferred */
-#define LE_T1_SOP      0x02            /* Start of Packet */
-#define LE_T1_EOP      0x01            /* End of Packet */
-#define LE_T1_POK      0x03            /* Packet is complete: SOP + EOP */
+#define LE_T1_OWN      0x80    /* LANCE owns the descriptor */
+#define LE_T1_ERR      0x40    /* Error */
+#define LE_T1_RES      0x20    /* Reserved, LANCE writes this with a zero */
+#define LE_T1_EMORE    0x10    /* More than one retry needed */
+#define LE_T1_EONE     0x08    /* One retry needed */
+#define LE_T1_EDEF     0x04    /* Deferred */
+#define LE_T1_SOP      0x02    /* Start of Packet */
+#define LE_T1_EOP      0x01    /* End of Packet */
+#define LE_T1_POK      0x03    /* Packet is complete: SOP + EOP */
 
 /*
  *             Error Flags
  */
-#define LE_T3_BUF      0x8000          /* Buffer Error */
-#define LE_T3_UFL      0x4000          /* Underflow Error */
-#define LE_T3_LCOL     0x1000          /* Late Collision */
-#define LE_T3_CLOS     0x0800          /* Loss of Carrier */
-#define LE_T3_RTY      0x0400          /* Retry Error */
-#define LE_T3_TDR      0x03ff          /* Time Domain Reflectometry */
+#define LE_T3_BUF      0x8000  /* Buffer Error */
+#define LE_T3_UFL      0x4000  /* Underflow Error */
+#define LE_T3_LCOL     0x1000  /* Late Collision */
+#define LE_T3_CLOS     0x0800  /* Loss of Carrier */
+#define LE_T3_RTY      0x0400  /* Retry Error */
+#define LE_T3_TDR      0x03ff  /* Time Domain Reflectometry */
 
 /* Miscellaneous useful macros */
 
-#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
-                        lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\
-                        lp->tx_old - lp->tx_new-1)
+#define TX_BUFFS_AVAIL ((lp->tx_old <= lp->tx_new) ? \
+                       lp->tx_old + lp->tx_ring_mod_mask - lp->tx_new : \
+                       lp->tx_old - lp->tx_new - 1)
 
 /* The LANCE only uses 24 bit addresses. This does the obvious thing. */
 #define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
 
 /* Now the prototypes we export */
 int lance_open(struct net_device *dev);
-int lance_close (struct net_device *dev);
-int lance_start_xmit (struct sk_buff *skb, struct net_device *dev);
-void lance_set_multicast (struct net_device *dev);
+int lance_close(struct net_device *dev);
+int lance_start_xmit(struct sk_buff *skb, struct net_device *dev);
+void lance_set_multicast(struct net_device *dev);
 void lance_tx_timeout(struct net_device *dev);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 void lance_poll(struct net_device *dev);
index 0c61fd50d8829f13789b7c3583000929de25084d..47ce57c2c8939fd458decbb74042d8179b31c558 100644 (file)
@@ -127,41 +127,41 @@ static void hplance_remove_one(struct dio_dev *d)
 /* Initialise a single lance board at the given DIO device */
 static void hplance_init(struct net_device *dev, struct dio_dev *d)
 {
-        unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
-        struct hplance_private *lp;
-        int i;
-
-        /* reset the board */
-        out_8(va+DIO_IDOFF, 0xff);
-        udelay(100);                              /* ariba! ariba! udelay! udelay! */
-
-        /* Fill the dev fields */
-        dev->base_addr = va;
-        dev->netdev_ops = &hplance_netdev_ops;
-        dev->dma = 0;
-
-        for (i=0; i<6; i++) {
-                /* The NVRAM holds our ethernet address, one nibble per byte,
-                 * at bytes NVRAMOFF+1,3,5,7,9...
-                 */
-                dev->dev_addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
-                        | (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
-        }
-
-        lp = netdev_priv(dev);
-        lp->lance.name = (char*)d->name;                /* discards const, shut up gcc */
-        lp->lance.base = va;
-        lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
-        lp->lance.lance_init_block = NULL;              /* LANCE addr of same RAM */
-        lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
-        lp->lance.irq = d->ipl;
-        lp->lance.writerap = hplance_writerap;
-        lp->lance.writerdp = hplance_writerdp;
-        lp->lance.readrdp = hplance_readrdp;
-        lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
-        lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
-        lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
-        lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
+       unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
+       struct hplance_private *lp;
+       int i;
+
+       /* reset the board */
+       out_8(va + DIO_IDOFF, 0xff);
+       udelay(100);                              /* ariba! ariba! udelay! udelay! */
+
+       /* Fill the dev fields */
+       dev->base_addr = va;
+       dev->netdev_ops = &hplance_netdev_ops;
+       dev->dma = 0;
+
+       for (i = 0; i < 6; i++) {
+               /* The NVRAM holds our ethernet address, one nibble per byte,
+                * at bytes NVRAMOFF+1,3,5,7,9...
+                */
+               dev->dev_addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
+                       | (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
+       }
+
+       lp = netdev_priv(dev);
+       lp->lance.name = d->name;
+       lp->lance.base = va;
+       lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
+       lp->lance.lance_init_block = NULL;              /* LANCE addr of same RAM */
+       lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
+       lp->lance.irq = d->ipl;
+       lp->lance.writerap = hplance_writerap;
+       lp->lance.writerdp = hplance_writerdp;
+       lp->lance.readrdp = hplance_readrdp;
+       lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
+       lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
+       lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
+       lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
 }
 
 /* This is disgusting. We have to check the DIO status register for ack every
@@ -195,25 +195,25 @@ static unsigned short hplance_readrdp(void *priv)
 
 static int hplance_open(struct net_device *dev)
 {
-        int status;
-        struct lance_private *lp = netdev_priv(dev);
+       int status;
+       struct lance_private *lp = netdev_priv(dev);
 
-        status = lance_open(dev);                 /* call generic lance open code */
-        if (status)
-                return status;
-        /* enable interrupts at board level. */
-        out_8(lp->base + HPLANCE_STATUS, LE_IE);
+       status = lance_open(dev);                 /* call generic lance open code */
+       if (status)
+               return status;
+       /* enable interrupts at board level. */
+       out_8(lp->base + HPLANCE_STATUS, LE_IE);
 
-        return 0;
+       return 0;
 }
 
 static int hplance_close(struct net_device *dev)
 {
-        struct lance_private *lp = netdev_priv(dev);
+       struct lance_private *lp = netdev_priv(dev);
 
-        out_8(lp->base + HPLANCE_STATUS, 0);   /* disable interrupts at boardlevel */
-        lance_close(dev);
-        return 0;
+       out_8(lp->base + HPLANCE_STATUS, 0);    /* disable interrupts at boardlevel */
+       lance_close(dev);
+       return 0;
 }
 
 static int __init hplance_init_module(void)
@@ -223,7 +223,7 @@ static int __init hplance_init_module(void)
 
 static void __exit hplance_cleanup_module(void)
 {
-        dio_unregister_driver(&hplance_driver);
+       dio_unregister_driver(&hplance_driver);
 }
 
 module_init(hplance_init_module);
index e108e911da05c8a32891a60b46489630823145be..0e8399dec0543736d8dc3ef732cb18817eca7892 100644 (file)
@@ -94,33 +94,31 @@ struct net_device * __init mvme147lance_probe(int unit)
        dev->netdev_ops = &lance_netdev_ops;
        dev->dma = 0;
 
-       addr=(u_long *)ETHERNET_ADDRESS;
+       addr = (u_long *)ETHERNET_ADDRESS;
        address = *addr;
-       dev->dev_addr[0]=0x08;
-       dev->dev_addr[1]=0x00;
-       dev->dev_addr[2]=0x3e;
-       address=address>>8;
-       dev->dev_addr[5]=address&0xff;
-       address=address>>8;
-       dev->dev_addr[4]=address&0xff;
-       address=address>>8;
-       dev->dev_addr[3]=address&0xff;
-
-       printk("%s: MVME147 at 0x%08lx, irq %d, "
-              "Hardware Address %pM\n",
+       dev->dev_addr[0] = 0x08;
+       dev->dev_addr[1] = 0x00;
+       dev->dev_addr[2] = 0x3e;
+       address = address >> 8;
+       dev->dev_addr[5] = address&0xff;
+       address = address >> 8;
+       dev->dev_addr[4] = address&0xff;
+       address = address >> 8;
+       dev->dev_addr[3] = address&0xff;
+
+       printk("%s: MVME147 at 0x%08lx, irq %d, Hardware Address %pM\n",
               dev->name, dev->base_addr, MVME147_LANCE_IRQ,
               dev->dev_addr);
 
        lp = netdev_priv(dev);
        lp->ram = __get_dma_pages(GFP_ATOMIC, 3);       /* 16K */
-       if (!lp->ram)
-       {
+       if (!lp->ram) {
                printk("%s: No memory for LANCE buffers\n", dev->name);
                free_netdev(dev);
                return ERR_PTR(-ENOMEM);
        }
 
-       lp->lance.name = (char*)name;                   /* discards const, shut up gcc */
+       lp->lance.name = name;
        lp->lance.base = dev->base_addr;
        lp->lance.init_block = (struct lance_init_block *)(lp->ram); /* CPU addr */
        lp->lance.lance_init_block = (struct lance_init_block *)(lp->ram);                 /* LANCE addr of same RAM */
@@ -167,8 +165,8 @@ static int m147lance_open(struct net_device *dev)
        if (status)
                return status;
        /* enable interrupts at board level. */
-       m147_pcc->lan_cntrl=0;       /* clear the interrupts (if any) */
-       m147_pcc->lan_cntrl=0x08 | 0x04;     /* Enable irq 4 */
+       m147_pcc->lan_cntrl = 0;       /* clear the interrupts (if any) */
+       m147_pcc->lan_cntrl = 0x08 | 0x04;     /* Enable irq 4 */
 
        return 0;
 }
@@ -176,7 +174,7 @@ static int m147lance_open(struct net_device *dev)
 static int m147lance_close(struct net_device *dev)
 {
        /* disable interrupts at boardlevel */
-       m147_pcc->lan_cntrl=0x0; /* disable interrupts */
+       m147_pcc->lan_cntrl = 0x0; /* disable interrupts */
        lance_close(dev);
        return 0;
 }
index 38492e0b704e3aab926ec5fd300b61028223d504..9339cccfe05a35977493a0fbaf766b91f49f8acb 100644 (file)
@@ -1668,7 +1668,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
        for (i = 0; i < ETH_ALEN; i++)
                promaddr[i] = inb(ioaddr + i);
 
-       if (memcmp(promaddr, dev->dev_addr, ETH_ALEN) ||
+       if (!ether_addr_equal(promaddr, dev->dev_addr) ||
            !is_valid_ether_addr(dev->dev_addr)) {
                if (is_valid_ether_addr(promaddr)) {
                        if (pcnet32_debug & NETIF_MSG_PROBE) {
index eedf2a5fc2be472084a3561b17ab4ecfd7134705..eeecc29cf5b7d2695739d819fe900e798bf38996 100644 (file)
@@ -555,6 +555,8 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
        /* Make sure pointer to data buffer is set */
        wmb();
 
+       skb_tx_timestamp(skb);
+
        *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len);
 
        /* Increment index to point to the next BD */
@@ -569,8 +571,6 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
 
        arc_reg_set(priv, R_STATUS, TXPL_MASK);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
index d71103dbf2cdf8a7328d5f1ca4b5216a38b73d78..8fc93c5f6abca337e01f6939678cadd24f36b0f1 100644 (file)
@@ -106,6 +106,9 @@ struct alx_priv {
        u16 msg_enable;
 
        bool msi;
+
+       /* protects hw.stats */
+       spinlock_t stats_lock;
 };
 
 extern const struct ethtool_ops alx_ethtool_ops;
index 45b36507abc16276dace4718526effecaca6986a..08e22df2a300ad1a5453e56f548f89bccd057cb6 100644 (file)
 #include "reg.h"
 #include "hw.h"
 
+/* The order of these strings must match the order of the fields in
+ * struct alx_hw_stats
+ * See hw.h
+ */
+static const char alx_gstrings_stats[][ETH_GSTRING_LEN] = {
+       "rx_packets",
+       "rx_bcast_packets",
+       "rx_mcast_packets",
+       "rx_pause_packets",
+       "rx_ctrl_packets",
+       "rx_fcs_errors",
+       "rx_length_errors",
+       "rx_bytes",
+       "rx_runt_packets",
+       "rx_fragments",
+       "rx_64B_or_less_packets",
+       "rx_65B_to_127B_packets",
+       "rx_128B_to_255B_packets",
+       "rx_256B_to_511B_packets",
+       "rx_512B_to_1023B_packets",
+       "rx_1024B_to_1518B_packets",
+       "rx_1519B_to_mtu_packets",
+       "rx_oversize_packets",
+       "rx_rxf_ov_drop_packets",
+       "rx_rrd_ov_drop_packets",
+       "rx_align_errors",
+       "rx_bcast_bytes",
+       "rx_mcast_bytes",
+       "rx_address_errors",
+       "tx_packets",
+       "tx_bcast_packets",
+       "tx_mcast_packets",
+       "tx_pause_packets",
+       "tx_exc_defer_packets",
+       "tx_ctrl_packets",
+       "tx_defer_packets",
+       "tx_bytes",
+       "tx_64B_or_less_packets",
+       "tx_65B_to_127B_packets",
+       "tx_128B_to_255B_packets",
+       "tx_256B_to_511B_packets",
+       "tx_512B_to_1023B_packets",
+       "tx_1024B_to_1518B_packets",
+       "tx_1519B_to_mtu_packets",
+       "tx_single_collision",
+       "tx_multiple_collisions",
+       "tx_late_collision",
+       "tx_abort_collision",
+       "tx_underrun",
+       "tx_trd_eop",
+       "tx_length_errors",
+       "tx_trunc_packets",
+       "tx_bcast_bytes",
+       "tx_mcast_bytes",
+       "tx_update",
+};
+
+#define ALX_NUM_STATS ARRAY_SIZE(alx_gstrings_stats)
+
+
 static u32 alx_get_supported_speeds(struct alx_hw *hw)
 {
        u32 supported = SUPPORTED_10baseT_Half |
@@ -201,6 +261,44 @@ static void alx_set_msglevel(struct net_device *netdev, u32 data)
        alx->msg_enable = data;
 }
 
+static void alx_get_ethtool_stats(struct net_device *netdev,
+                                 struct ethtool_stats *estats, u64 *data)
+{
+       struct alx_priv *alx = netdev_priv(netdev);
+       struct alx_hw *hw = &alx->hw;
+
+       spin_lock(&alx->stats_lock);
+
+       alx_update_hw_stats(hw);
+       BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) <
+                    ALX_NUM_STATS * sizeof(u64));
+       memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64));
+
+       spin_unlock(&alx->stats_lock);
+}
+
+static void alx_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
+{
+       switch (stringset) {
+       case ETH_SS_STATS:
+               memcpy(buf, &alx_gstrings_stats, sizeof(alx_gstrings_stats));
+               break;
+       default:
+               WARN_ON(1);
+               break;
+       }
+}
+
+static int alx_get_sset_count(struct net_device *netdev, int sset)
+{
+       switch (sset) {
+       case ETH_SS_STATS:
+               return ALX_NUM_STATS;
+       default:
+               return -EINVAL;
+       }
+}
+
 const struct ethtool_ops alx_ethtool_ops = {
        .get_settings   = alx_get_settings,
        .set_settings   = alx_set_settings,
@@ -209,4 +307,7 @@ const struct ethtool_ops alx_ethtool_ops = {
        .get_msglevel   = alx_get_msglevel,
        .set_msglevel   = alx_set_msglevel,
        .get_link       = ethtool_op_get_link,
+       .get_strings    = alx_get_strings,
+       .get_sset_count = alx_get_sset_count,
+       .get_ethtool_stats      = alx_get_ethtool_stats,
 };
index 1e8c24a3cb4eb6d872124cd7111771e32dfe4e15..7712f068f6d4fdd81efee882fd0093d4df412f43 100644 (file)
@@ -1050,3 +1050,61 @@ bool alx_get_phy_info(struct alx_hw *hw)
 
        return true;
 }
+
+void alx_update_hw_stats(struct alx_hw *hw)
+{
+       /* RX stats */
+       hw->stats.rx_ok          += alx_read_mem32(hw, ALX_MIB_RX_OK);
+       hw->stats.rx_bcast       += alx_read_mem32(hw, ALX_MIB_RX_BCAST);
+       hw->stats.rx_mcast       += alx_read_mem32(hw, ALX_MIB_RX_MCAST);
+       hw->stats.rx_pause       += alx_read_mem32(hw, ALX_MIB_RX_PAUSE);
+       hw->stats.rx_ctrl        += alx_read_mem32(hw, ALX_MIB_RX_CTRL);
+       hw->stats.rx_fcs_err     += alx_read_mem32(hw, ALX_MIB_RX_FCS_ERR);
+       hw->stats.rx_len_err     += alx_read_mem32(hw, ALX_MIB_RX_LEN_ERR);
+       hw->stats.rx_byte_cnt    += alx_read_mem32(hw, ALX_MIB_RX_BYTE_CNT);
+       hw->stats.rx_runt        += alx_read_mem32(hw, ALX_MIB_RX_RUNT);
+       hw->stats.rx_frag        += alx_read_mem32(hw, ALX_MIB_RX_FRAG);
+       hw->stats.rx_sz_64B      += alx_read_mem32(hw, ALX_MIB_RX_SZ_64B);
+       hw->stats.rx_sz_127B     += alx_read_mem32(hw, ALX_MIB_RX_SZ_127B);
+       hw->stats.rx_sz_255B     += alx_read_mem32(hw, ALX_MIB_RX_SZ_255B);
+       hw->stats.rx_sz_511B     += alx_read_mem32(hw, ALX_MIB_RX_SZ_511B);
+       hw->stats.rx_sz_1023B    += alx_read_mem32(hw, ALX_MIB_RX_SZ_1023B);
+       hw->stats.rx_sz_1518B    += alx_read_mem32(hw, ALX_MIB_RX_SZ_1518B);
+       hw->stats.rx_sz_max      += alx_read_mem32(hw, ALX_MIB_RX_SZ_MAX);
+       hw->stats.rx_ov_sz       += alx_read_mem32(hw, ALX_MIB_RX_OV_SZ);
+       hw->stats.rx_ov_rxf      += alx_read_mem32(hw, ALX_MIB_RX_OV_RXF);
+       hw->stats.rx_ov_rrd      += alx_read_mem32(hw, ALX_MIB_RX_OV_RRD);
+       hw->stats.rx_align_err   += alx_read_mem32(hw, ALX_MIB_RX_ALIGN_ERR);
+       hw->stats.rx_bc_byte_cnt += alx_read_mem32(hw, ALX_MIB_RX_BCCNT);
+       hw->stats.rx_mc_byte_cnt += alx_read_mem32(hw, ALX_MIB_RX_MCCNT);
+       hw->stats.rx_err_addr    += alx_read_mem32(hw, ALX_MIB_RX_ERRADDR);
+
+       /* TX stats */
+       hw->stats.tx_ok          += alx_read_mem32(hw, ALX_MIB_TX_OK);
+       hw->stats.tx_bcast       += alx_read_mem32(hw, ALX_MIB_TX_BCAST);
+       hw->stats.tx_mcast       += alx_read_mem32(hw, ALX_MIB_TX_MCAST);
+       hw->stats.tx_pause       += alx_read_mem32(hw, ALX_MIB_TX_PAUSE);
+       hw->stats.tx_exc_defer   += alx_read_mem32(hw, ALX_MIB_TX_EXC_DEFER);
+       hw->stats.tx_ctrl        += alx_read_mem32(hw, ALX_MIB_TX_CTRL);
+       hw->stats.tx_defer       += alx_read_mem32(hw, ALX_MIB_TX_DEFER);
+       hw->stats.tx_byte_cnt    += alx_read_mem32(hw, ALX_MIB_TX_BYTE_CNT);
+       hw->stats.tx_sz_64B      += alx_read_mem32(hw, ALX_MIB_TX_SZ_64B);
+       hw->stats.tx_sz_127B     += alx_read_mem32(hw, ALX_MIB_TX_SZ_127B);
+       hw->stats.tx_sz_255B     += alx_read_mem32(hw, ALX_MIB_TX_SZ_255B);
+       hw->stats.tx_sz_511B     += alx_read_mem32(hw, ALX_MIB_TX_SZ_511B);
+       hw->stats.tx_sz_1023B    += alx_read_mem32(hw, ALX_MIB_TX_SZ_1023B);
+       hw->stats.tx_sz_1518B    += alx_read_mem32(hw, ALX_MIB_TX_SZ_1518B);
+       hw->stats.tx_sz_max      += alx_read_mem32(hw, ALX_MIB_TX_SZ_MAX);
+       hw->stats.tx_single_col  += alx_read_mem32(hw, ALX_MIB_TX_SINGLE_COL);
+       hw->stats.tx_multi_col   += alx_read_mem32(hw, ALX_MIB_TX_MULTI_COL);
+       hw->stats.tx_late_col    += alx_read_mem32(hw, ALX_MIB_TX_LATE_COL);
+       hw->stats.tx_abort_col   += alx_read_mem32(hw, ALX_MIB_TX_ABORT_COL);
+       hw->stats.tx_underrun    += alx_read_mem32(hw, ALX_MIB_TX_UNDERRUN);
+       hw->stats.tx_trd_eop     += alx_read_mem32(hw, ALX_MIB_TX_TRD_EOP);
+       hw->stats.tx_len_err     += alx_read_mem32(hw, ALX_MIB_TX_LEN_ERR);
+       hw->stats.tx_trunc       += alx_read_mem32(hw, ALX_MIB_TX_TRUNC);
+       hw->stats.tx_bc_byte_cnt += alx_read_mem32(hw, ALX_MIB_TX_BCCNT);
+       hw->stats.tx_mc_byte_cnt += alx_read_mem32(hw, ALX_MIB_TX_MCCNT);
+
+       hw->stats.update         += alx_read_mem32(hw, ALX_MIB_UPDATE);
+}
index 96f3b4381e17a11f5259d82e22ef7be144153c9d..15548802d6f8871db4a67dffaabe779852bbedd2 100644 (file)
@@ -381,6 +381,73 @@ struct alx_rrd {
                                 ALX_ISR_RX_Q6 | \
                                 ALX_ISR_RX_Q7)
 
+/* Statistics counters collected by the MAC
+ *
+ * The order of the fields must match the strings in alx_gstrings_stats
+ * All stats fields should be u64
+ * See ethtool.c
+ */
+struct alx_hw_stats {
+       /* rx */
+       u64 rx_ok;              /* good RX packets */
+       u64 rx_bcast;           /* good RX broadcast packets */
+       u64 rx_mcast;           /* good RX multicast packets */
+       u64 rx_pause;           /* RX pause frames */
+       u64 rx_ctrl;            /* RX control packets other than pause frames */
+       u64 rx_fcs_err;         /* RX packets with bad FCS */
+       u64 rx_len_err;         /* RX packets with length != actual size */
+       u64 rx_byte_cnt;        /* good bytes received. FCS is NOT included */
+       u64 rx_runt;            /* RX packets < 64 bytes with good FCS */
+       u64 rx_frag;            /* RX packets < 64 bytes with bad FCS */
+       u64 rx_sz_64B;          /* 64 byte RX packets */
+       u64 rx_sz_127B;         /* 65-127 byte RX packets */
+       u64 rx_sz_255B;         /* 128-255 byte RX packets */
+       u64 rx_sz_511B;         /* 256-511 byte RX packets */
+       u64 rx_sz_1023B;        /* 512-1023 byte RX packets */
+       u64 rx_sz_1518B;        /* 1024-1518 byte RX packets */
+       u64 rx_sz_max;          /* 1519 byte to MTU RX packets */
+       u64 rx_ov_sz;           /* truncated RX packets, size > MTU */
+       u64 rx_ov_rxf;          /* frames dropped due to RX FIFO overflow */
+       u64 rx_ov_rrd;          /* frames dropped due to RRD overflow */
+       u64 rx_align_err;       /* alignment errors */
+       u64 rx_bc_byte_cnt;     /* RX broadcast bytes, excluding FCS */
+       u64 rx_mc_byte_cnt;     /* RX multicast bytes, excluding FCS */
+       u64 rx_err_addr;        /* packets dropped due to address filtering */
+
+       /* tx */
+       u64 tx_ok;              /* good TX packets */
+       u64 tx_bcast;           /* good TX broadcast packets */
+       u64 tx_mcast;           /* good TX multicast packets */
+       u64 tx_pause;           /* TX pause frames */
+       u64 tx_exc_defer;       /* TX packets deferred excessively */
+       u64 tx_ctrl;            /* TX control frames, excluding pause frames */
+       u64 tx_defer;           /* TX packets deferred */
+       u64 tx_byte_cnt;        /* bytes transmitted, FCS is NOT included */
+       u64 tx_sz_64B;          /* 64 byte TX packets */
+       u64 tx_sz_127B;         /* 65-127 byte TX packets */
+       u64 tx_sz_255B;         /* 128-255 byte TX packets */
+       u64 tx_sz_511B;         /* 256-511 byte TX packets */
+       u64 tx_sz_1023B;        /* 512-1023 byte TX packets */
+       u64 tx_sz_1518B;        /* 1024-1518 byte TX packets */
+       u64 tx_sz_max;          /* 1519 byte to MTU TX packets */
+       u64 tx_single_col;      /* packets TX after a single collision */
+       u64 tx_multi_col;       /* packets TX after multiple collisions */
+       u64 tx_late_col;        /* TX packets with late collisions */
+       u64 tx_abort_col;       /* TX packets aborted w/excessive collisions */
+       u64 tx_underrun;        /* TX packets aborted due to TX FIFO underrun
+                                * or TRD FIFO underrun
+                                */
+       u64 tx_trd_eop;         /* reads beyond the EOP into the next frame
+                                * when TRD was not written timely
+                                */
+       u64 tx_len_err;         /* TX packets where length != actual size */
+       u64 tx_trunc;           /* TX packets truncated due to size > MTU */
+       u64 tx_bc_byte_cnt;     /* broadcast bytes transmitted, excluding FCS */
+       u64 tx_mc_byte_cnt;     /* multicast bytes transmitted, excluding FCS */
+       u64 update;
+};
+
+
 /* maximum interrupt vectors for msix */
 #define ALX_MAX_MSIX_INTRS     16
 
@@ -424,6 +491,9 @@ struct alx_hw {
 
        /* PHY link patch flag */
        bool lnk_patch;
+
+       /* cumulated stats from the hardware (registers are cleared on read) */
+       struct alx_hw_stats stats;
 };
 
 static inline int alx_hw_revision(struct alx_hw *hw)
@@ -491,6 +561,7 @@ bool alx_phy_configured(struct alx_hw *hw);
 void alx_configure_basic(struct alx_hw *hw);
 void alx_disable_rss(struct alx_hw *hw);
 bool alx_get_phy_info(struct alx_hw *hw);
+void alx_update_hw_stats(struct alx_hw *hw);
 
 static inline u32 alx_speed_to_ethadv(int speed, u8 duplex)
 {
index c3c4c266b8465981b658676617fa79202aa4396d..e92ffd6e1c15fdbd2aaaa21f9335fb25bc142d20 100644 (file)
@@ -1166,10 +1166,60 @@ static void alx_poll_controller(struct net_device *netdev)
 }
 #endif
 
+static struct rtnl_link_stats64 *alx_get_stats64(struct net_device *dev,
+                                       struct rtnl_link_stats64 *net_stats)
+{
+       struct alx_priv *alx = netdev_priv(dev);
+       struct alx_hw_stats *hw_stats = &alx->hw.stats;
+
+       spin_lock(&alx->stats_lock);
+
+       alx_update_hw_stats(&alx->hw);
+
+       net_stats->tx_bytes   = hw_stats->tx_byte_cnt;
+       net_stats->rx_bytes   = hw_stats->rx_byte_cnt;
+       net_stats->multicast  = hw_stats->rx_mcast;
+       net_stats->collisions = hw_stats->tx_single_col +
+                               hw_stats->tx_multi_col +
+                               hw_stats->tx_late_col +
+                               hw_stats->tx_abort_col;
+
+       net_stats->rx_errors  = hw_stats->rx_frag +
+                               hw_stats->rx_fcs_err +
+                               hw_stats->rx_len_err +
+                               hw_stats->rx_ov_sz +
+                               hw_stats->rx_ov_rrd +
+                               hw_stats->rx_align_err +
+                               hw_stats->rx_ov_rxf;
+
+       net_stats->rx_fifo_errors   = hw_stats->rx_ov_rxf;
+       net_stats->rx_length_errors = hw_stats->rx_len_err;
+       net_stats->rx_crc_errors    = hw_stats->rx_fcs_err;
+       net_stats->rx_frame_errors  = hw_stats->rx_align_err;
+       net_stats->rx_dropped       = hw_stats->rx_ov_rrd;
+
+       net_stats->tx_errors = hw_stats->tx_late_col +
+                              hw_stats->tx_abort_col +
+                              hw_stats->tx_underrun +
+                              hw_stats->tx_trunc;
+
+       net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
+       net_stats->tx_fifo_errors    = hw_stats->tx_underrun;
+       net_stats->tx_window_errors  = hw_stats->tx_late_col;
+
+       net_stats->tx_packets = hw_stats->tx_ok + net_stats->tx_errors;
+       net_stats->rx_packets = hw_stats->rx_ok + net_stats->rx_errors;
+
+       spin_unlock(&alx->stats_lock);
+
+       return net_stats;
+}
+
 static const struct net_device_ops alx_netdev_ops = {
        .ndo_open               = alx_open,
        .ndo_stop               = alx_stop,
        .ndo_start_xmit         = alx_start_xmit,
+       .ndo_get_stats64        = alx_get_stats64,
        .ndo_set_rx_mode        = alx_set_rx_mode,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = alx_set_mac_address,
index e4358c98bc4eee788fdc3a0c315f07b4635e8c1b..af006b44b2a66ec3fd0892672e6a61a9ca362cc3 100644 (file)
 
 /* MIB */
 #define ALX_MIB_BASE                                   0x1700
+
 #define ALX_MIB_RX_OK                                  (ALX_MIB_BASE + 0)
+#define ALX_MIB_RX_BCAST                               (ALX_MIB_BASE + 4)
+#define ALX_MIB_RX_MCAST                               (ALX_MIB_BASE + 8)
+#define ALX_MIB_RX_PAUSE                               (ALX_MIB_BASE + 12)
+#define ALX_MIB_RX_CTRL                                        (ALX_MIB_BASE + 16)
+#define ALX_MIB_RX_FCS_ERR                             (ALX_MIB_BASE + 20)
+#define ALX_MIB_RX_LEN_ERR                             (ALX_MIB_BASE + 24)
+#define ALX_MIB_RX_BYTE_CNT                            (ALX_MIB_BASE + 28)
+#define ALX_MIB_RX_RUNT                                        (ALX_MIB_BASE + 32)
+#define ALX_MIB_RX_FRAG                                        (ALX_MIB_BASE + 36)
+#define ALX_MIB_RX_SZ_64B                              (ALX_MIB_BASE + 40)
+#define ALX_MIB_RX_SZ_127B                             (ALX_MIB_BASE + 44)
+#define ALX_MIB_RX_SZ_255B                             (ALX_MIB_BASE + 48)
+#define ALX_MIB_RX_SZ_511B                             (ALX_MIB_BASE + 52)
+#define ALX_MIB_RX_SZ_1023B                            (ALX_MIB_BASE + 56)
+#define ALX_MIB_RX_SZ_1518B                            (ALX_MIB_BASE + 60)
+#define ALX_MIB_RX_SZ_MAX                              (ALX_MIB_BASE + 64)
+#define ALX_MIB_RX_OV_SZ                               (ALX_MIB_BASE + 68)
+#define ALX_MIB_RX_OV_RXF                              (ALX_MIB_BASE + 72)
+#define ALX_MIB_RX_OV_RRD                              (ALX_MIB_BASE + 76)
+#define ALX_MIB_RX_ALIGN_ERR                           (ALX_MIB_BASE + 80)
+#define ALX_MIB_RX_BCCNT                               (ALX_MIB_BASE + 84)
+#define ALX_MIB_RX_MCCNT                               (ALX_MIB_BASE + 88)
 #define ALX_MIB_RX_ERRADDR                             (ALX_MIB_BASE + 92)
+
 #define ALX_MIB_TX_OK                                  (ALX_MIB_BASE + 96)
+#define ALX_MIB_TX_BCAST                               (ALX_MIB_BASE + 100)
+#define ALX_MIB_TX_MCAST                               (ALX_MIB_BASE + 104)
+#define ALX_MIB_TX_PAUSE                               (ALX_MIB_BASE + 108)
+#define ALX_MIB_TX_EXC_DEFER                           (ALX_MIB_BASE + 112)
+#define ALX_MIB_TX_CTRL                                        (ALX_MIB_BASE + 116)
+#define ALX_MIB_TX_DEFER                               (ALX_MIB_BASE + 120)
+#define ALX_MIB_TX_BYTE_CNT                            (ALX_MIB_BASE + 124)
+#define ALX_MIB_TX_SZ_64B                              (ALX_MIB_BASE + 128)
+#define ALX_MIB_TX_SZ_127B                             (ALX_MIB_BASE + 132)
+#define ALX_MIB_TX_SZ_255B                             (ALX_MIB_BASE + 136)
+#define ALX_MIB_TX_SZ_511B                             (ALX_MIB_BASE + 140)
+#define ALX_MIB_TX_SZ_1023B                            (ALX_MIB_BASE + 144)
+#define ALX_MIB_TX_SZ_1518B                            (ALX_MIB_BASE + 148)
+#define ALX_MIB_TX_SZ_MAX                              (ALX_MIB_BASE + 152)
+#define ALX_MIB_TX_SINGLE_COL                          (ALX_MIB_BASE + 156)
+#define ALX_MIB_TX_MULTI_COL                           (ALX_MIB_BASE + 160)
+#define ALX_MIB_TX_LATE_COL                            (ALX_MIB_BASE + 164)
+#define ALX_MIB_TX_ABORT_COL                           (ALX_MIB_BASE + 168)
+#define ALX_MIB_TX_UNDERRUN                            (ALX_MIB_BASE + 172)
+#define ALX_MIB_TX_TRD_EOP                             (ALX_MIB_BASE + 176)
+#define ALX_MIB_TX_LEN_ERR                             (ALX_MIB_BASE + 180)
+#define ALX_MIB_TX_TRUNC                               (ALX_MIB_BASE + 184)
+#define ALX_MIB_TX_BCCNT                               (ALX_MIB_BASE + 188)
 #define ALX_MIB_TX_MCCNT                               (ALX_MIB_BASE + 192)
+#define ALX_MIB_UPDATE                                 (ALX_MIB_BASE + 196)
 
-#define ALX_RX_STATS_BIN                               ALX_MIB_RX_OK
-#define ALX_RX_STATS_END                               ALX_MIB_RX_ERRADDR
-#define ALX_TX_STATS_BIN                               ALX_MIB_TX_OK
-#define ALX_TX_STATS_END                               ALX_MIB_TX_MCCNT
 
 #define ALX_ISR                                                0x1600
 #define ALX_ISR_DIS                                    BIT(31)
index a36a760ada28af64272a5132a60648c543963bed..29801750f239b247389c7040f6616f9b79d14983 100644 (file)
@@ -145,9 +145,11 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
         * Mask some pcie error bits
         */
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
-       pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
-       data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
-       pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       if (pos) {
+               pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
+               data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
+               pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       }
        /* clear error status */
        pcie_capability_write_word(pdev, PCI_EXP_DEVSTA,
                        PCI_EXP_DEVSTA_NFED |
index 538211d6f7d9ad5fc806008a58d984750c91edcd..55d86ecdacfe3b553ea92b0bc691f884717c5160 100644 (file)
@@ -3122,7 +3122,8 @@ static void atl1_remove(struct pci_dev *pdev)
         * from the BIOS during POST.  If we've been messing with the MAC
         * address, we need to save the permanent one.
         */
-       if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
+       if (!ether_addr_equal_unaligned(adapter->hw.mac_addr,
+                                       adapter->hw.perm_mac_addr)) {
                memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
                        ETH_ALEN);
                atl1_set_mac_addr(&adapter->hw);
index 2fa5b86f139db626f1839c7b3bc9087444179b28..3f97d9fd0a71b66ec28c9db4fcc1df63ccf71b29 100644 (file)
@@ -23,6 +23,7 @@ config B44
        depends on SSB_POSSIBLE && HAS_DMA
        select SSB
        select MII
+       select PHYLIB
        ---help---
          If you have a network (Ethernet) controller of this type, say Y
          or M and read the Ethernet-HOWTO, available from
index 90e54d5488dcbda9b13a1820177630d2dd70b613..1f7b5aa114fae3ee3adf589af58e5def31fc84d7 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2006 Felix Fietkau (nbd@openwrt.org)
  * Copyright (C) 2006 Broadcom Corporation.
  * Copyright (C) 2007 Michael Buesch <m@bues.ch>
+ * Copyright (C) 2013 Hauke Mehrtens <hauke@hauke-m.de>
  *
  * Distribute under GPL.
  */
@@ -29,6 +30,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/ssb/ssb.h>
 #include <linux/slab.h>
+#include <linux/phy.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -284,7 +286,7 @@ static int __b44_writephy(struct b44 *bp, int phy_addr, int reg, u32 val)
 
 static inline int b44_readphy(struct b44 *bp, int reg, u32 *val)
 {
-       if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY)
                return 0;
 
        return __b44_readphy(bp, bp->phy_addr, reg, val);
@@ -292,14 +294,14 @@ static inline int b44_readphy(struct b44 *bp, int reg, u32 *val)
 
 static inline int b44_writephy(struct b44 *bp, int reg, u32 val)
 {
-       if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY)
                return 0;
 
        return __b44_writephy(bp, bp->phy_addr, reg, val);
 }
 
 /* miilib interface */
-static int b44_mii_read(struct net_device *dev, int phy_id, int location)
+static int b44_mdio_read_mii(struct net_device *dev, int phy_id, int location)
 {
        u32 val;
        struct b44 *bp = netdev_priv(dev);
@@ -309,19 +311,36 @@ static int b44_mii_read(struct net_device *dev, int phy_id, int location)
        return val;
 }
 
-static void b44_mii_write(struct net_device *dev, int phy_id, int location,
-                        int val)
+static void b44_mdio_write_mii(struct net_device *dev, int phy_id, int location,
+                              int val)
 {
        struct b44 *bp = netdev_priv(dev);
        __b44_writephy(bp, phy_id, location, val);
 }
 
+static int b44_mdio_read_phylib(struct mii_bus *bus, int phy_id, int location)
+{
+       u32 val;
+       struct b44 *bp = bus->priv;
+       int rc = __b44_readphy(bp, phy_id, location, &val);
+       if (rc)
+               return 0xffffffff;
+       return val;
+}
+
+static int b44_mdio_write_phylib(struct mii_bus *bus, int phy_id, int location,
+                                u16 val)
+{
+       struct b44 *bp = bus->priv;
+       return __b44_writephy(bp, phy_id, location, val);
+}
+
 static int b44_phy_reset(struct b44 *bp)
 {
        u32 val;
        int err;
 
-       if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY)
                return 0;
        err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
        if (err)
@@ -423,7 +442,7 @@ static int b44_setup_phy(struct b44 *bp)
 
        b44_wap54g10_workaround(bp);
 
-       if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY)
                return 0;
        if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
                goto out;
@@ -521,12 +540,14 @@ static void b44_check_phy(struct b44 *bp)
 {
        u32 bmsr, aux;
 
-       if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
                bp->flags |= B44_FLAG_100_BASE_T;
-               bp->flags |= B44_FLAG_FULL_DUPLEX;
                if (!netif_carrier_ok(bp->dev)) {
                        u32 val = br32(bp, B44_TX_CTRL);
-                       val |= TX_CTRL_DUPLEX;
+                       if (bp->flags & B44_FLAG_FULL_DUPLEX)
+                               val |= TX_CTRL_DUPLEX;
+                       else
+                               val &= ~TX_CTRL_DUPLEX;
                        bw32(bp, B44_TX_CTRL, val);
                        netif_carrier_on(bp->dev);
                        b44_link_report(bp);
@@ -1315,7 +1336,7 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind)
        if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
                bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
                br32(bp, B44_ENET_CTRL);
-               bp->flags &= ~B44_FLAG_INTERNAL_PHY;
+               bp->flags |= B44_FLAG_EXTERNAL_PHY;
        } else {
                u32 val = br32(bp, B44_DEVCTRL);
 
@@ -1324,7 +1345,7 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind)
                        br32(bp, B44_DEVCTRL);
                        udelay(100);
                }
-               bp->flags |= B44_FLAG_INTERNAL_PHY;
+               bp->flags &= ~B44_FLAG_EXTERNAL_PHY;
        }
 }
 
@@ -1339,7 +1360,10 @@ static void b44_halt(struct b44 *bp)
        bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);
        /* now reset the chip, but without enabling the MAC&PHY
         * part of it. This has to be done _after_ we shut down the PHY */
-       b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+               b44_chip_reset(bp, B44_CHIP_RESET_FULL);
+       else
+               b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
 }
 
 /* bp->lock is held. */
@@ -1805,6 +1829,11 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct b44 *bp = netdev_priv(dev);
 
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
+               BUG_ON(!bp->phydev);
+               return phy_ethtool_gset(bp->phydev, cmd);
+       }
+
        cmd->supported = (SUPPORTED_Autoneg);
        cmd->supported |= (SUPPORTED_100baseT_Half |
                          SUPPORTED_100baseT_Full |
@@ -1828,8 +1857,8 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                DUPLEX_FULL : DUPLEX_HALF;
        cmd->port = 0;
        cmd->phy_address = bp->phy_addr;
-       cmd->transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ?
-               XCVR_INTERNAL : XCVR_EXTERNAL;
+       cmd->transceiver = (bp->flags & B44_FLAG_EXTERNAL_PHY) ?
+               XCVR_EXTERNAL : XCVR_INTERNAL;
        cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
                AUTONEG_DISABLE : AUTONEG_ENABLE;
        if (cmd->autoneg == AUTONEG_ENABLE)
@@ -1846,7 +1875,23 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct b44 *bp = netdev_priv(dev);
-       u32 speed = ethtool_cmd_speed(cmd);
+       u32 speed;
+       int ret;
+
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
+               BUG_ON(!bp->phydev);
+               spin_lock_irq(&bp->lock);
+               if (netif_running(dev))
+                       b44_setup_phy(bp);
+
+               ret = phy_ethtool_sset(bp->phydev, cmd);
+
+               spin_unlock_irq(&bp->lock);
+
+               return ret;
+       }
+
+       speed = ethtool_cmd_speed(cmd);
 
        /* We do not support gigabit. */
        if (cmd->autoneg == AUTONEG_ENABLE) {
@@ -2076,7 +2121,6 @@ static const struct ethtool_ops b44_ethtool_ops = {
 
 static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-       struct mii_ioctl_data *data = if_mii(ifr);
        struct b44 *bp = netdev_priv(dev);
        int err = -EINVAL;
 
@@ -2084,7 +2128,12 @@ static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                goto out;
 
        spin_lock_irq(&bp->lock);
-       err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
+               BUG_ON(!bp->phydev);
+               err = phy_mii_ioctl(bp->phydev, ifr, cmd);
+       } else {
+               err = generic_mii_ioctl(&bp->mii_if, if_mii(ifr), cmd, NULL);
+       }
        spin_unlock_irq(&bp->lock);
 out:
        return err;
@@ -2146,6 +2195,141 @@ static const struct net_device_ops b44_netdev_ops = {
 #endif
 };
 
+static void b44_adjust_link(struct net_device *dev)
+{
+       struct b44 *bp = netdev_priv(dev);
+       struct phy_device *phydev = bp->phydev;
+       bool status_changed = 0;
+
+       BUG_ON(!phydev);
+
+       if (bp->old_link != phydev->link) {
+               status_changed = 1;
+               bp->old_link = phydev->link;
+       }
+
+       /* reflect duplex change */
+       if (phydev->link) {
+               if ((phydev->duplex == DUPLEX_HALF) &&
+                   (bp->flags & B44_FLAG_FULL_DUPLEX)) {
+                       status_changed = 1;
+                       bp->flags &= ~B44_FLAG_FULL_DUPLEX;
+               } else if ((phydev->duplex == DUPLEX_FULL) &&
+                          !(bp->flags & B44_FLAG_FULL_DUPLEX)) {
+                       status_changed = 1;
+                       bp->flags |= B44_FLAG_FULL_DUPLEX;
+               }
+       }
+
+       if (status_changed) {
+               b44_check_phy(bp);
+               phy_print_status(phydev);
+       }
+}
+
+static int b44_register_phy_one(struct b44 *bp)
+{
+       struct mii_bus *mii_bus;
+       struct ssb_device *sdev = bp->sdev;
+       struct phy_device *phydev;
+       char bus_id[MII_BUS_ID_SIZE + 3];
+       struct ssb_sprom *sprom = &sdev->bus->sprom;
+       int err;
+
+       mii_bus = mdiobus_alloc();
+       if (!mii_bus) {
+               dev_err(sdev->dev, "mdiobus_alloc() failed\n");
+               err = -ENOMEM;
+               goto err_out;
+       }
+
+       mii_bus->priv = bp;
+       mii_bus->read = b44_mdio_read_phylib;
+       mii_bus->write = b44_mdio_write_phylib;
+       mii_bus->name = "b44_eth_mii";
+       mii_bus->parent = sdev->dev;
+       mii_bus->phy_mask = ~(1 << bp->phy_addr);
+       snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%x", instance);
+       mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+       if (!mii_bus->irq) {
+               dev_err(sdev->dev, "mii_bus irq allocation failed\n");
+               err = -ENOMEM;
+               goto err_out_mdiobus;
+       }
+
+       memset(mii_bus->irq, PHY_POLL, sizeof(int) * PHY_MAX_ADDR);
+
+       bp->mii_bus = mii_bus;
+
+       err = mdiobus_register(mii_bus);
+       if (err) {
+               dev_err(sdev->dev, "failed to register MII bus\n");
+               goto err_out_mdiobus_irq;
+       }
+
+       if (!bp->mii_bus->phy_map[bp->phy_addr] &&
+           (sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) {
+
+               dev_info(sdev->dev,
+                        "could not find PHY at %i, use fixed one\n",
+                        bp->phy_addr);
+
+               bp->phy_addr = 0;
+               snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, "fixed-0",
+                        bp->phy_addr);
+       } else {
+               snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id,
+                        bp->phy_addr);
+       }
+
+       phydev = phy_connect(bp->dev, bus_id, &b44_adjust_link,
+                            PHY_INTERFACE_MODE_MII);
+       if (IS_ERR(phydev)) {
+               dev_err(sdev->dev, "could not attach PHY at %i\n",
+                       bp->phy_addr);
+               err = PTR_ERR(phydev);
+               goto err_out_mdiobus_unregister;
+       }
+
+       /* mask with MAC supported features */
+       phydev->supported &= (SUPPORTED_100baseT_Half |
+                             SUPPORTED_100baseT_Full |
+                             SUPPORTED_Autoneg |
+                             SUPPORTED_MII);
+       phydev->advertising = phydev->supported;
+
+       bp->phydev = phydev;
+       bp->old_link = 0;
+       bp->phy_addr = phydev->addr;
+
+       dev_info(sdev->dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
+                phydev->drv->name, dev_name(&phydev->dev));
+
+       return 0;
+
+err_out_mdiobus_unregister:
+       mdiobus_unregister(mii_bus);
+
+err_out_mdiobus_irq:
+       kfree(mii_bus->irq);
+
+err_out_mdiobus:
+       mdiobus_free(mii_bus);
+
+err_out:
+       return err;
+}
+
+static void b44_unregister_phy_one(struct b44 *bp)
+{
+       struct mii_bus *mii_bus = bp->mii_bus;
+
+       phy_disconnect(bp->phydev);
+       mdiobus_unregister(mii_bus);
+       kfree(mii_bus->irq);
+       mdiobus_free(mii_bus);
+}
+
 static int b44_init_one(struct ssb_device *sdev,
                        const struct ssb_device_id *ent)
 {
@@ -2206,9 +2390,15 @@ static int b44_init_one(struct ssb_device *sdev,
                goto err_out_powerdown;
        }
 
+       if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
+               dev_err(sdev->dev, "No PHY present on this MAC, aborting\n");
+               err = -ENODEV;
+               goto err_out_powerdown;
+       }
+
        bp->mii_if.dev = dev;
-       bp->mii_if.mdio_read = b44_mii_read;
-       bp->mii_if.mdio_write = b44_mii_write;
+       bp->mii_if.mdio_read = b44_mdio_read_mii;
+       bp->mii_if.mdio_write = b44_mdio_write_mii;
        bp->mii_if.phy_id = bp->phy_addr;
        bp->mii_if.phy_id_mask = 0x1f;
        bp->mii_if.reg_num_mask = 0x1f;
@@ -2236,13 +2426,26 @@ static int b44_init_one(struct ssb_device *sdev,
        b44_chip_reset(bp, B44_CHIP_RESET_FULL);
 
        /* do a phy reset to test if there is an active phy */
-       if (b44_phy_reset(bp) < 0)
-               bp->phy_addr = B44_PHY_ADDR_NO_PHY;
+       err = b44_phy_reset(bp);
+       if (err < 0) {
+               dev_err(sdev->dev, "phy reset failed\n");
+               goto err_out_unregister_netdev;
+       }
+
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
+               err = b44_register_phy_one(bp);
+               if (err) {
+                       dev_err(sdev->dev, "Cannot register PHY, aborting\n");
+                       goto err_out_unregister_netdev;
+               }
+       }
 
        netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
 
        return 0;
 
+err_out_unregister_netdev:
+       unregister_netdev(dev);
 err_out_powerdown:
        ssb_bus_may_powerdown(sdev->bus);
 
@@ -2256,8 +2459,11 @@ out:
 static void b44_remove_one(struct ssb_device *sdev)
 {
        struct net_device *dev = ssb_get_drvdata(sdev);
+       struct b44 *bp = netdev_priv(dev);
 
        unregister_netdev(dev);
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+               b44_unregister_phy_one(bp);
        ssb_device_disable(sdev, 0);
        ssb_bus_may_powerdown(sdev->bus);
        free_netdev(dev);
index 8993d72f042013c35f3fccebd4d40afe03f0a00b..3e9c3fc7591b2f05b71e5943e56a089ed7ce4e62 100644 (file)
@@ -280,9 +280,10 @@ struct ring_info {
        dma_addr_t      mapping;
 };
 
-#define B44_MCAST_TABLE_SIZE   32
-#define B44_PHY_ADDR_NO_PHY    30
-#define B44_MDC_RATIO          5000000
+#define B44_MCAST_TABLE_SIZE           32
+#define B44_PHY_ADDR_NO_LOCAL_PHY      30 /* no local phy regs */
+#define B44_PHY_ADDR_NO_PHY            31 /* no phy present at all */
+#define B44_MDC_RATIO                  5000000
 
 #define        B44_STAT_REG_DECLARE            \
        _B44(tx_good_octets)            \
@@ -344,6 +345,9 @@ B44_STAT_REG_DECLARE
        struct u64_stats_sync   syncp;
 };
 
+#define        B44_BOARDFLAG_ROBO              0x0010  /* Board has robo switch */
+#define        B44_BOARDFLAG_ADM               0x0080  /* Board has ADMtek switch */
+
 struct ssb_device;
 
 struct b44 {
@@ -376,7 +380,7 @@ struct b44 {
 #define B44_FLAG_ADV_10FULL    0x02000000
 #define B44_FLAG_ADV_100HALF   0x04000000
 #define B44_FLAG_ADV_100FULL   0x08000000
-#define B44_FLAG_INTERNAL_PHY  0x10000000
+#define B44_FLAG_EXTERNAL_PHY  0x10000000
 #define B44_FLAG_RX_RING_HACK  0x20000000
 #define B44_FLAG_TX_RING_HACK  0x40000000
 #define B44_FLAG_WOL_ENABLE    0x80000000
@@ -396,6 +400,9 @@ struct b44 {
        u32                     tx_pending;
        u8                      phy_addr;
        u8                      force_copybreak;
+       struct phy_device       *phydev;
+       struct mii_bus          *mii_bus;
+       int                     old_link;
        struct mii_if_info      mii_if;
 };
 
index b665a6aa7e14f1c2e27b73c4ee43c1cdb0bb2fa6..7f968a9b52c84200d64c6f7a35f43ad3630f606d 100644 (file)
@@ -96,6 +96,19 @@ static void bgmac_dma_tx_enable(struct bgmac *bgmac,
        u32 ctl;
 
        ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL);
+       if (bgmac->core->id.rev >= 4) {
+               ctl &= ~BGMAC_DMA_TX_BL_MASK;
+               ctl |= BGMAC_DMA_TX_BL_128 << BGMAC_DMA_TX_BL_SHIFT;
+
+               ctl &= ~BGMAC_DMA_TX_MR_MASK;
+               ctl |= BGMAC_DMA_TX_MR_2 << BGMAC_DMA_TX_MR_SHIFT;
+
+               ctl &= ~BGMAC_DMA_TX_PC_MASK;
+               ctl |= BGMAC_DMA_TX_PC_16 << BGMAC_DMA_TX_PC_SHIFT;
+
+               ctl &= ~BGMAC_DMA_TX_PT_MASK;
+               ctl |= BGMAC_DMA_TX_PT_8 << BGMAC_DMA_TX_PT_SHIFT;
+       }
        ctl |= BGMAC_DMA_TX_ENABLE;
        ctl |= BGMAC_DMA_TX_PARITY_DISABLE;
        bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, ctl);
@@ -240,6 +253,16 @@ static void bgmac_dma_rx_enable(struct bgmac *bgmac,
        u32 ctl;
 
        ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL);
+       if (bgmac->core->id.rev >= 4) {
+               ctl &= ~BGMAC_DMA_RX_BL_MASK;
+               ctl |= BGMAC_DMA_RX_BL_128 << BGMAC_DMA_RX_BL_SHIFT;
+
+               ctl &= ~BGMAC_DMA_RX_PC_MASK;
+               ctl |= BGMAC_DMA_RX_PC_8 << BGMAC_DMA_RX_PC_SHIFT;
+
+               ctl &= ~BGMAC_DMA_RX_PT_MASK;
+               ctl |= BGMAC_DMA_RX_PT_1 << BGMAC_DMA_RX_PT_SHIFT;
+       }
        ctl &= BGMAC_DMA_RX_ADDREXT_MASK;
        ctl |= BGMAC_DMA_RX_ENABLE;
        ctl |= BGMAC_DMA_RX_PARITY_DISABLE;
@@ -725,11 +748,9 @@ static void bgmac_phy_reset(struct bgmac *bgmac)
        if (bgmac->phyaddr == BGMAC_PHY_NOREGS)
                return;
 
-       bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL,
-                       BGMAC_PHY_CTL_RESET);
+       bgmac_phy_write(bgmac, bgmac->phyaddr, MII_BMCR, BMCR_RESET);
        udelay(100);
-       if (bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL) &
-           BGMAC_PHY_CTL_RESET)
+       if (bgmac_phy_read(bgmac, bgmac->phyaddr, MII_BMCR) & BMCR_RESET)
                bgmac_err(bgmac, "PHY reset failed\n");
        bgmac_phy_init(bgmac);
 }
@@ -747,13 +768,13 @@ static void bgmac_cmdcfg_maskset(struct bgmac *bgmac, u32 mask, u32 set,
        u32 cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
        u32 new_val = (cmdcfg & mask) | set;
 
-       bgmac_set(bgmac, BGMAC_CMDCFG, BGMAC_CMDCFG_SR);
+       bgmac_set(bgmac, BGMAC_CMDCFG, BGMAC_CMDCFG_SR(bgmac->core->id.rev));
        udelay(2);
 
        if (new_val != cmdcfg || force)
                bgmac_write(bgmac, BGMAC_CMDCFG, new_val);
 
-       bgmac_mask(bgmac, BGMAC_CMDCFG, ~BGMAC_CMDCFG_SR);
+       bgmac_mask(bgmac, BGMAC_CMDCFG, ~BGMAC_CMDCFG_SR(bgmac->core->id.rev));
        udelay(2);
 }
 
@@ -827,6 +848,9 @@ static void bgmac_mac_speed(struct bgmac *bgmac)
        case SPEED_1000:
                set |= BGMAC_CMDCFG_ES_1000;
                break;
+       case SPEED_2500:
+               set |= BGMAC_CMDCFG_ES_2500;
+               break;
        default:
                bgmac_err(bgmac, "Unsupported speed: %d\n", bgmac->mac_speed);
        }
@@ -839,12 +863,26 @@ static void bgmac_mac_speed(struct bgmac *bgmac)
 
 static void bgmac_miiconfig(struct bgmac *bgmac)
 {
-       u8 imode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) & BGMAC_DS_MM_MASK) >>
-                       BGMAC_DS_MM_SHIFT;
-       if (imode == 0 || imode == 1) {
-               bgmac->mac_speed = SPEED_100;
+       struct bcma_device *core = bgmac->core;
+       struct bcma_chipinfo *ci = &core->bus->chipinfo;
+       u8 imode;
+
+       if (ci->id == BCMA_CHIP_ID_BCM4707 ||
+           ci->id == BCMA_CHIP_ID_BCM53018) {
+               bcma_awrite32(core, BCMA_IOCTL,
+                             bcma_aread32(core, BCMA_IOCTL) | 0x40 |
+                             BGMAC_BCMA_IOCTL_SW_CLKEN);
+               bgmac->mac_speed = SPEED_2500;
                bgmac->mac_duplex = DUPLEX_FULL;
                bgmac_mac_speed(bgmac);
+       } else {
+               imode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) &
+                       BGMAC_DS_MM_MASK) >> BGMAC_DS_MM_SHIFT;
+               if (imode == 0 || imode == 1) {
+                       bgmac->mac_speed = SPEED_100;
+                       bgmac->mac_duplex = DUPLEX_FULL;
+                       bgmac_mac_speed(bgmac);
+               }
        }
 }
 
@@ -854,7 +892,7 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
        struct bcma_device *core = bgmac->core;
        struct bcma_bus *bus = core->bus;
        struct bcma_chipinfo *ci = &bus->chipinfo;
-       u32 flags = 0;
+       u32 flags;
        u32 iost;
        int i;
 
@@ -882,15 +920,21 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
            (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188))
                iost &= ~BGMAC_BCMA_IOST_ATTACHED;
 
-       if (iost & BGMAC_BCMA_IOST_ATTACHED) {
-               flags = BGMAC_BCMA_IOCTL_SW_CLKEN;
-               if (!bgmac->has_robosw)
-                       flags |= BGMAC_BCMA_IOCTL_SW_RESET;
+       /* 3GMAC: for BCM4707, only do core reset at bgmac_probe() */
+       if (ci->id != BCMA_CHIP_ID_BCM4707) {
+               flags = 0;
+               if (iost & BGMAC_BCMA_IOST_ATTACHED) {
+                       flags = BGMAC_BCMA_IOCTL_SW_CLKEN;
+                       if (!bgmac->has_robosw)
+                               flags |= BGMAC_BCMA_IOCTL_SW_RESET;
+               }
+               bcma_core_enable(core, flags);
        }
 
-       bcma_core_enable(core, flags);
-
-       if (core->id.rev > 2) {
+       /* Request Misc PLL for corerev > 2 */
+       if (core->id.rev > 2 &&
+           ci->id != BCMA_CHIP_ID_BCM4707 &&
+           ci->id != BCMA_CHIP_ID_BCM53018) {
                bgmac_set(bgmac, BCMA_CLKCTLST,
                          BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ);
                bgmac_wait_value(bgmac->core, BCMA_CLKCTLST,
@@ -956,7 +1000,7 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
                             BGMAC_CMDCFG_PROM |
                             BGMAC_CMDCFG_NLC |
                             BGMAC_CMDCFG_CFE |
-                            BGMAC_CMDCFG_SR,
+                            BGMAC_CMDCFG_SR(core->id.rev),
                             false);
        bgmac->mac_speed = SPEED_UNKNOWN;
        bgmac->mac_duplex = DUPLEX_UNKNOWN;
@@ -999,7 +1043,7 @@ static void bgmac_enable(struct bgmac *bgmac)
 
        cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
        bgmac_cmdcfg_maskset(bgmac, ~(BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE),
-                            BGMAC_CMDCFG_SR, true);
+                            BGMAC_CMDCFG_SR(bgmac->core->id.rev), true);
        udelay(2);
        cmdcfg |= BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE;
        bgmac_write(bgmac, BGMAC_CMDCFG, cmdcfg);
@@ -1028,12 +1072,16 @@ static void bgmac_enable(struct bgmac *bgmac)
                break;
        }
 
-       rxq_ctl = bgmac_read(bgmac, BGMAC_RXQ_CTL);
-       rxq_ctl &= ~BGMAC_RXQ_CTL_MDP_MASK;
-       bp_clk = bcma_pmu_get_bus_clock(&bgmac->core->bus->drv_cc) / 1000000;
-       mdp = (bp_clk * 128 / 1000) - 3;
-       rxq_ctl |= (mdp << BGMAC_RXQ_CTL_MDP_SHIFT);
-       bgmac_write(bgmac, BGMAC_RXQ_CTL, rxq_ctl);
+       if (ci->id != BCMA_CHIP_ID_BCM4707 &&
+           ci->id != BCMA_CHIP_ID_BCM53018) {
+               rxq_ctl = bgmac_read(bgmac, BGMAC_RXQ_CTL);
+               rxq_ctl &= ~BGMAC_RXQ_CTL_MDP_MASK;
+               bp_clk = bcma_pmu_get_bus_clock(&bgmac->core->bus->drv_cc) /
+                               1000000;
+               mdp = (bp_clk * 128 / 1000) - 3;
+               rxq_ctl |= (mdp << BGMAC_RXQ_CTL_MDP_SHIFT);
+               bgmac_write(bgmac, BGMAC_RXQ_CTL, rxq_ctl);
+       }
 }
 
 /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */
@@ -1200,27 +1248,11 @@ static int bgmac_set_mac_address(struct net_device *net_dev, void *addr)
 static int bgmac_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
 {
        struct bgmac *bgmac = netdev_priv(net_dev);
-       struct mii_ioctl_data *data = if_mii(ifr);
-
-       switch (cmd) {
-       case SIOCGMIIPHY:
-               data->phy_id = bgmac->phyaddr;
-               /* fallthru */
-       case SIOCGMIIREG:
-               if (!netif_running(net_dev))
-                       return -EAGAIN;
-               data->val_out = bgmac_phy_read(bgmac, data->phy_id,
-                                              data->reg_num & 0x1f);
-               return 0;
-       case SIOCSMIIREG:
-               if (!netif_running(net_dev))
-                       return -EAGAIN;
-               bgmac_phy_write(bgmac, data->phy_id, data->reg_num & 0x1f,
-                               data->val_in);
-               return 0;
-       default:
-               return -EOPNOTSUPP;
-       }
+
+       if (!netif_running(net_dev))
+               return -EINVAL;
+
+       return phy_mii_ioctl(bgmac->phy_dev, ifr, cmd);
 }
 
 static const struct net_device_ops bgmac_netdev_ops = {
@@ -1441,6 +1473,27 @@ static int bgmac_probe(struct bcma_device *core)
 
        bgmac_chip_reset(bgmac);
 
+       /* For Northstar, we have to take all GMAC core out of reset */
+       if (core->id.id == BCMA_CHIP_ID_BCM4707 ||
+           core->id.id == BCMA_CHIP_ID_BCM53018) {
+               struct bcma_device *ns_core;
+               int ns_gmac;
+
+               /* Northstar has 4 GMAC cores */
+               for (ns_gmac = 0; ns_gmac < 4; ns_gmac++) {
+                       /* As Northstar requirement, we have to reset all GMACs
+                        * before accessing one. bgmac_chip_reset() call
+                        * bcma_core_enable() for this core. Then the other
+                        * three GMACs didn't reset.  We do it here.
+                        */
+                       ns_core = bcma_find_core_unit(core->bus,
+                                                     BCMA_CORE_MAC_GBIT,
+                                                     ns_gmac);
+                       if (ns_core && !bcma_core_is_enabled(ns_core))
+                               bcma_core_enable(ns_core, 0);
+               }
+       }
+
        err = bgmac_dma_alloc(bgmac);
        if (err) {
                bgmac_err(bgmac, "Unable to alloc memory for DMA\n");
index 2d44119a764893bbdcf58bed93798f47779ef22d..89fa5bc69c515f3fd3a4c309558294448fceb386 100644 (file)
 #define   BGMAC_CMDCFG_ES_10                   0x00000000
 #define   BGMAC_CMDCFG_ES_100                  0x00000004
 #define   BGMAC_CMDCFG_ES_1000                 0x00000008
+#define   BGMAC_CMDCFG_ES_2500                 0x0000000C
 #define  BGMAC_CMDCFG_PROM                     0x00000010      /* Set to activate promiscuous mode */
 #define  BGMAC_CMDCFG_PAD_EN                   0x00000020
 #define  BGMAC_CMDCFG_CF                       0x00000040
 #define  BGMAC_CMDCFG_TAI                      0x00000200
 #define  BGMAC_CMDCFG_HD                       0x00000400      /* Set if in half duplex mode */
 #define  BGMAC_CMDCFG_HD_SHIFT                 10
-#define  BGMAC_CMDCFG_SR                       0x00000800      /* Set to reset mode */
+#define  BGMAC_CMDCFG_SR_REV0                  0x00000800      /* Set to reset mode, for other revs */
+#define  BGMAC_CMDCFG_SR_REV4                  0x00002000      /* Set to reset mode, only for core rev 4 */
+#define  BGMAC_CMDCFG_SR(rev)  ((rev == 4) ? BGMAC_CMDCFG_SR_REV4 : BGMAC_CMDCFG_SR_REV0)
 #define  BGMAC_CMDCFG_ML                       0x00008000      /* Set to activate mac loopback mode */
 #define  BGMAC_CMDCFG_AE                       0x00400000
 #define  BGMAC_CMDCFG_CFE                      0x00800000
 #define BGMAC_RX_STATUS                                0xb38
 #define BGMAC_TX_STATUS                                0xb3c
 
-#define BGMAC_PHY_CTL                          0x00
-#define  BGMAC_PHY_CTL_SPEED_MSB               0x0040
-#define  BGMAC_PHY_CTL_DUPLEX                  0x0100          /* duplex mode */
-#define  BGMAC_PHY_CTL_RESTART                 0x0200          /* restart autonegotiation */
-#define  BGMAC_PHY_CTL_ANENAB                  0x1000          /* enable autonegotiation */
-#define  BGMAC_PHY_CTL_SPEED                   0x2000
-#define  BGMAC_PHY_CTL_LOOP                    0x4000          /* loopback */
-#define  BGMAC_PHY_CTL_RESET                   0x8000          /* reset */
-/* Helpers */
-#define  BGMAC_PHY_CTL_SPEED_10                        0
-#define  BGMAC_PHY_CTL_SPEED_100               BGMAC_PHY_CTL_SPEED
-#define  BGMAC_PHY_CTL_SPEED_1000              BGMAC_PHY_CTL_SPEED_MSB
-#define BGMAC_PHY_ADV                          0x04
-#define  BGMAC_PHY_ADV_10HALF                  0x0020          /* advertise 10MBits/s half duplex */
-#define  BGMAC_PHY_ADV_10FULL                  0x0040          /* advertise 10MBits/s full duplex */
-#define  BGMAC_PHY_ADV_100HALF                 0x0080          /* advertise 100MBits/s half duplex */
-#define  BGMAC_PHY_ADV_100FULL                 0x0100          /* advertise 100MBits/s full duplex */
-#define BGMAC_PHY_ADV2                         0x09
-#define  BGMAC_PHY_ADV2_1000HALF               0x0100          /* advertise 1000MBits/s half duplex */
-#define  BGMAC_PHY_ADV2_1000FULL               0x0200          /* advertise 1000MBits/s full duplex */
-
 /* BCMA GMAC core specific IO Control (BCMA_IOCTL) flags */
 #define BGMAC_BCMA_IOCTL_SW_CLKEN              0x00000004      /* PHY Clock Enable */
 #define BGMAC_BCMA_IOCTL_SW_RESET              0x00000008      /* PHY Reset */
 #define  BGMAC_DMA_TX_SUSPEND                  0x00000002
 #define  BGMAC_DMA_TX_LOOPBACK                 0x00000004
 #define  BGMAC_DMA_TX_FLUSH                    0x00000010
+#define  BGMAC_DMA_TX_MR_MASK                  0x000000C0      /* Multiple outstanding reads */
+#define  BGMAC_DMA_TX_MR_SHIFT                 6
+#define   BGMAC_DMA_TX_MR_1                    0
+#define   BGMAC_DMA_TX_MR_2                    1
 #define  BGMAC_DMA_TX_PARITY_DISABLE           0x00000800
 #define  BGMAC_DMA_TX_ADDREXT_MASK             0x00030000
 #define  BGMAC_DMA_TX_ADDREXT_SHIFT            16
+#define  BGMAC_DMA_TX_BL_MASK                  0x001C0000      /* BurstLen bits */
+#define  BGMAC_DMA_TX_BL_SHIFT                 18
+#define   BGMAC_DMA_TX_BL_16                   0
+#define   BGMAC_DMA_TX_BL_32                   1
+#define   BGMAC_DMA_TX_BL_64                   2
+#define   BGMAC_DMA_TX_BL_128                  3
+#define   BGMAC_DMA_TX_BL_256                  4
+#define   BGMAC_DMA_TX_BL_512                  5
+#define   BGMAC_DMA_TX_BL_1024                 6
+#define  BGMAC_DMA_TX_PC_MASK                  0x00E00000      /* Prefetch control */
+#define  BGMAC_DMA_TX_PC_SHIFT                 21
+#define   BGMAC_DMA_TX_PC_0                    0
+#define   BGMAC_DMA_TX_PC_4                    1
+#define   BGMAC_DMA_TX_PC_8                    2
+#define   BGMAC_DMA_TX_PC_16                   3
+#define  BGMAC_DMA_TX_PT_MASK                  0x03000000      /* Prefetch threshold */
+#define  BGMAC_DMA_TX_PT_SHIFT                 24
+#define   BGMAC_DMA_TX_PT_1                    0
+#define   BGMAC_DMA_TX_PT_2                    1
+#define   BGMAC_DMA_TX_PT_4                    2
+#define   BGMAC_DMA_TX_PT_8                    3
 #define BGMAC_DMA_TX_INDEX                     0x04
 #define BGMAC_DMA_TX_RINGLO                    0x08
 #define BGMAC_DMA_TX_RINGHI                    0x0C
 #define  BGMAC_DMA_RX_DIRECT_FIFO              0x00000100
 #define  BGMAC_DMA_RX_OVERFLOW_CONT            0x00000400
 #define  BGMAC_DMA_RX_PARITY_DISABLE           0x00000800
+#define  BGMAC_DMA_RX_MR_MASK                  0x000000C0      /* Multiple outstanding reads */
+#define  BGMAC_DMA_RX_MR_SHIFT                 6
+#define   BGMAC_DMA_TX_MR_1                    0
+#define   BGMAC_DMA_TX_MR_2                    1
 #define  BGMAC_DMA_RX_ADDREXT_MASK             0x00030000
 #define  BGMAC_DMA_RX_ADDREXT_SHIFT            16
+#define  BGMAC_DMA_RX_BL_MASK                  0x001C0000      /* BurstLen bits */
+#define  BGMAC_DMA_RX_BL_SHIFT                 18
+#define   BGMAC_DMA_RX_BL_16                   0
+#define   BGMAC_DMA_RX_BL_32                   1
+#define   BGMAC_DMA_RX_BL_64                   2
+#define   BGMAC_DMA_RX_BL_128                  3
+#define   BGMAC_DMA_RX_BL_256                  4
+#define   BGMAC_DMA_RX_BL_512                  5
+#define   BGMAC_DMA_RX_BL_1024                 6
+#define  BGMAC_DMA_RX_PC_MASK                  0x00E00000      /* Prefetch control */
+#define  BGMAC_DMA_RX_PC_SHIFT                 21
+#define   BGMAC_DMA_RX_PC_0                    0
+#define   BGMAC_DMA_RX_PC_4                    1
+#define   BGMAC_DMA_RX_PC_8                    2
+#define   BGMAC_DMA_RX_PC_16                   3
+#define  BGMAC_DMA_RX_PT_MASK                  0x03000000      /* Prefetch threshold */
+#define  BGMAC_DMA_RX_PT_SHIFT                 24
+#define   BGMAC_DMA_RX_PT_1                    0
+#define   BGMAC_DMA_RX_PT_2                    1
+#define   BGMAC_DMA_RX_PT_4                    2
+#define   BGMAC_DMA_RX_PT_8                    3
 #define BGMAC_DMA_RX_INDEX                     0x24
 #define BGMAC_DMA_RX_RINGLO                    0x28
 #define BGMAC_DMA_RX_RINGHI                    0x2C
index 0ced3587c88877c7c56a9d6c034d2306485e5484..3f3cae288466287f1211ecd87fd37fa6f6433abe 100644 (file)
@@ -58,8 +58,8 @@
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME                "bnx2"
-#define DRV_MODULE_VERSION     "2.2.4"
-#define DRV_MODULE_RELDATE     "Aug 05, 2013"
+#define DRV_MODULE_VERSION     "2.2.5"
+#define DRV_MODULE_RELDATE     "December 20, 2013"
 #define FW_MIPS_FILE_06                "bnx2/bnx2-mips-06-6.2.3.fw"
 #define FW_RV2P_FILE_06                "bnx2/bnx2-rv2p-06-6.0.15.fw"
 #define FW_MIPS_FILE_09                "bnx2/bnx2-mips-09-6.2.1b.fw"
@@ -1197,6 +1197,8 @@ bnx2_copper_linkup(struct bnx2 *bp)
 {
        u32 bmcr;
 
+       bp->phy_flags &= ~BNX2_PHY_FLAG_MDIX;
+
        bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
        if (bmcr & BMCR_ANENABLE) {
                u32 local_adv, remote_adv, common;
@@ -1255,6 +1257,14 @@ bnx2_copper_linkup(struct bnx2 *bp)
                }
        }
 
+       if (bp->link_up) {
+               u32 ext_status;
+
+               bnx2_read_phy(bp, MII_BNX2_EXT_STATUS, &ext_status);
+               if (ext_status & EXT_STATUS_MDIX)
+                       bp->phy_flags |= BNX2_PHY_FLAG_MDIX;
+       }
+
        return 0;
 }
 
@@ -2048,29 +2058,27 @@ bnx2_setup_copper_phy(struct bnx2 *bp)
 __releases(&bp->phy_lock)
 __acquires(&bp->phy_lock)
 {
-       u32 bmcr;
+       u32 bmcr, adv_reg, new_adv = 0;
        u32 new_bmcr;
 
        bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 
+       bnx2_read_phy(bp, bp->mii_adv, &adv_reg);
+       adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
+                   ADVERTISE_PAUSE_ASYM);
+
+       new_adv = ADVERTISE_CSMA | ethtool_adv_to_mii_adv_t(bp->advertising);
+
        if (bp->autoneg & AUTONEG_SPEED) {
-               u32 adv_reg, adv1000_reg;
-               u32 new_adv = 0;
+               u32 adv1000_reg;
                u32 new_adv1000 = 0;
 
-               bnx2_read_phy(bp, bp->mii_adv, &adv_reg);
-               adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
-                       ADVERTISE_PAUSE_ASYM);
+               new_adv |= bnx2_phy_get_pause_adv(bp);
 
                bnx2_read_phy(bp, MII_CTRL1000, &adv1000_reg);
                adv1000_reg &= PHY_ALL_1000_SPEED;
 
-               new_adv = ethtool_adv_to_mii_adv_t(bp->advertising);
-               new_adv |= ADVERTISE_CSMA;
-               new_adv |= bnx2_phy_get_pause_adv(bp);
-
                new_adv1000 |= ethtool_adv_to_mii_ctrl1000_t(bp->advertising);
-
                if ((adv1000_reg != new_adv1000) ||
                        (adv_reg != new_adv) ||
                        ((bmcr & BMCR_ANENABLE) == 0)) {
@@ -2090,6 +2098,10 @@ __acquires(&bp->phy_lock)
                return 0;
        }
 
+       /* advertise nothing when forcing speed */
+       if (adv_reg != new_adv)
+               bnx2_write_phy(bp, bp->mii_adv, new_adv);
+
        new_bmcr = 0;
        if (bp->req_line_speed == SPEED_100) {
                new_bmcr |= BMCR_SPEED100;
@@ -2341,9 +2353,15 @@ bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy)
        }
 
        /* ethernet@wirespeed */
-       bnx2_write_phy(bp, 0x18, 0x7007);
-       bnx2_read_phy(bp, 0x18, &val);
-       bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4));
+       bnx2_write_phy(bp, MII_BNX2_AUX_CTL, AUX_CTL_MISC_CTL);
+       bnx2_read_phy(bp, MII_BNX2_AUX_CTL, &val);
+       val |=  AUX_CTL_MISC_CTL_WR | AUX_CTL_MISC_CTL_WIRESPEED;
+
+       /* auto-mdix */
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
+               val |=  AUX_CTL_MISC_CTL_AUTOMDIX;
+
+       bnx2_write_phy(bp, MII_BNX2_AUX_CTL, val);
        return 0;
 }
 
@@ -6866,6 +6884,12 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        if (netif_carrier_ok(dev)) {
                ethtool_cmd_speed_set(cmd, bp->line_speed);
                cmd->duplex = bp->duplex;
+               if (!(bp->phy_flags & BNX2_PHY_FLAG_SERDES)) {
+                       if (bp->phy_flags & BNX2_PHY_FLAG_MDIX)
+                               cmd->eth_tp_mdix = ETH_TP_MDI_X;
+                       else
+                               cmd->eth_tp_mdix = ETH_TP_MDI;
+               }
        }
        else {
                ethtool_cmd_speed_set(cmd, -1);
index 18cb2d23e56b344db90f8c7cef007f02f256f64e..f1cf2c44e7ed549519fe2eaf860d0d01302b032d 100644 (file)
@@ -6471,6 +6471,15 @@ struct l2_fhdr {
 
 #define BCM5708S_TX_ACTL3                      0x17
 
+#define MII_BNX2_EXT_STATUS                    0x11
+#define EXT_STATUS_MDIX                                 (1 << 13)
+
+#define MII_BNX2_AUX_CTL                       0x18
+#define AUX_CTL_MISC_CTL                        0x7007
+#define AUX_CTL_MISC_CTL_WIRESPEED               (1 << 4)
+#define AUX_CTL_MISC_CTL_AUTOMDIX                (1 << 9)
+#define AUX_CTL_MISC_CTL_WR                      (1 << 15)
+
 #define MII_BNX2_DSP_RW_PORT                   0x15
 #define MII_BNX2_DSP_ADDRESS                   0x17
 #define MII_BNX2_DSP_EXPAND_REG                         0x0f00
@@ -6844,6 +6853,7 @@ struct bnx2 {
 #define BNX2_PHY_FLAG_REMOTE_PHY_CAP           0x00000800
 #define BNX2_PHY_FLAG_FORCED_DOWN              0x00001000
 #define BNX2_PHY_FLAG_NO_PARALLEL              0x00002000
+#define BNX2_PHY_FLAG_MDIX                     0x00004000
 
        u32                     mii_bmcr;
        u32                     mii_bmsr;
index a6d840684731aa2e3f6f55ecbcea6305ceee6d68..0578fb90d8f3d46814ce1082a34979e24ddad6c9 100644 (file)
@@ -1250,7 +1250,10 @@ struct bnx2x_slowpath {
         * Therefore, if they would have been defined in the same union,
         * data can get corrupted.
         */
-       struct afex_vif_list_ramrod_data func_afex_rdata;
+       union {
+               struct afex_vif_list_ramrod_data        viflist_data;
+               struct function_update_data             func_update;
+       } func_afex_rdata;
 
        /* used by dmae command executer */
        struct dmae_command             dmae[MAX_DMAE_C];
@@ -1546,6 +1549,7 @@ struct bnx2x {
 #define INTERRUPTS_ENABLED_FLAG                (1 << 23)
 #define BC_SUPPORTS_RMMOD_CMD          (1 << 24)
 #define HAS_PHYS_PORT_ID               (1 << 25)
+#define AER_ENABLED                    (1 << 26)
 
 #define BP_NOMCP(bp)                   ((bp)->flags & NO_MCP_FLAG)
 
@@ -2053,7 +2057,6 @@ int bnx2x_del_all_macs(struct bnx2x *bp,
 void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p);
 void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
                    u8 vf_valid, int fw_sb_id, int igu_sb_id);
-u32 bnx2x_get_pretend_reg(struct bnx2x *bp);
 int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
 int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
 int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode);
@@ -2436,7 +2439,8 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
 
 #define GOOD_ME_REG(me_reg) (((me_reg) & ME_REG_VF_VALID) && \
                            (!((me_reg) & ME_REG_VF_ERR)))
-int bnx2x_nic_load_analyze_req(struct bnx2x *bp, u32 load_code);
+int bnx2x_compare_fw_ver(struct bnx2x *bp, u32 load_code, bool print_err);
+
 /* Congestion management fairness mode */
 #define CMNG_FNS_NONE                  0
 #define CMNG_FNS_MINMAX                        1
@@ -2499,4 +2503,6 @@ void bnx2x_set_local_cmng(struct bnx2x *bp);
 #define MCPR_SCRATCH_BASE(bp) \
        (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
 
+#define E1H_MAX_MF_SB_COUNT (HC_SB_MAX_SB_E1X/(E1HVN_MAX * PORT_MAX))
+
 #endif /* bnx2x.h */
index 37b203b7a5b3e2ee950f647a983e40534cacbcb9..cdc12ea0fc3ff686c43bb0e0db2cb4864065c179 100644 (file)
 #include "bnx2x_init.h"
 #include "bnx2x_sp.h"
 
+static void bnx2x_free_fp_mem_cnic(struct bnx2x *bp);
+static int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp);
+static int bnx2x_alloc_fp_mem(struct bnx2x *bp);
+static int bnx2x_poll(struct napi_struct *napi, int budget);
+
+static void bnx2x_add_all_napi_cnic(struct bnx2x *bp)
+{
+       int i;
+
+       /* Add NAPI objects */
+       for_each_rx_queue_cnic(bp, i) {
+               netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
+                              bnx2x_poll, NAPI_POLL_WEIGHT);
+               napi_hash_add(&bnx2x_fp(bp, i, napi));
+       }
+}
+
+static void bnx2x_add_all_napi(struct bnx2x *bp)
+{
+       int i;
+
+       /* Add NAPI objects */
+       for_each_eth_queue(bp, i) {
+               netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
+                              bnx2x_poll, NAPI_POLL_WEIGHT);
+               napi_hash_add(&bnx2x_fp(bp, i, napi));
+       }
+}
+
+static int bnx2x_calc_num_queues(struct bnx2x *bp)
+{
+       return  bnx2x_num_queues ?
+                min_t(int, bnx2x_num_queues, BNX2X_MAX_QUEUES(bp)) :
+                min_t(int, netif_get_num_default_rss_queues(),
+                      BNX2X_MAX_QUEUES(bp));
+}
+
 /**
  * bnx2x_move_fp - move content of the fastpath structure.
  *
@@ -145,7 +182,7 @@ static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta)
        }
 }
 
-int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */
+int bnx2x_load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */
 
 /* free skb in the packet ring at pos idx
  * return idx of last bd freed
@@ -813,7 +850,7 @@ void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe,
                skb->ip_summed = CHECKSUM_UNNECESSARY;
 }
 
-int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
+static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 {
        struct bnx2x *bp = fp->bp;
        u16 bd_cons, bd_prod, bd_prod_fw, comp_ring_cons;
@@ -1483,7 +1520,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
        }
 }
 
-void bnx2x_free_skbs_cnic(struct bnx2x *bp)
+static void bnx2x_free_skbs_cnic(struct bnx2x *bp)
 {
        bnx2x_free_tx_skbs_cnic(bp);
        bnx2x_free_rx_skbs_cnic(bp);
@@ -2265,7 +2302,7 @@ static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code)
  * virtualized environments a pf from another VM may have already
  * initialized the device including loading FW
  */
-int bnx2x_nic_load_analyze_req(struct bnx2x *bp, u32 load_code)
+int bnx2x_compare_fw_ver(struct bnx2x *bp, u32 load_code, bool print_err)
 {
        /* is another pf loaded on this engine? */
        if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP &&
@@ -2284,8 +2321,12 @@ int bnx2x_nic_load_analyze_req(struct bnx2x *bp, u32 load_code)
 
                /* abort nic load if version mismatch */
                if (my_fw != loaded_fw) {
-                       BNX2X_ERR("bnx2x with FW %x was already loaded which mismatches my %x FW. Aborting\n",
-                                 loaded_fw, my_fw);
+                       if (print_err)
+                               BNX2X_ERR("bnx2x with FW %x was already loaded which mismatches my %x FW. Aborting\n",
+                                         loaded_fw, my_fw);
+                       else
+                               BNX2X_DEV_INFO("bnx2x with FW %x was already loaded which mismatches my %x FW, possibly due to MF UNDI\n",
+                                              loaded_fw, my_fw);
                        return -EBUSY;
                }
        }
@@ -2298,16 +2339,16 @@ static int bnx2x_nic_load_no_mcp(struct bnx2x *bp, int port)
        int path = BP_PATH(bp);
 
        DP(NETIF_MSG_IFUP, "NO MCP - load counts[%d]      %d, %d, %d\n",
-          path, load_count[path][0], load_count[path][1],
-          load_count[path][2]);
-       load_count[path][0]++;
-       load_count[path][1 + port]++;
+          path, bnx2x_load_count[path][0], bnx2x_load_count[path][1],
+          bnx2x_load_count[path][2]);
+       bnx2x_load_count[path][0]++;
+       bnx2x_load_count[path][1 + port]++;
        DP(NETIF_MSG_IFUP, "NO MCP - new load counts[%d]  %d, %d, %d\n",
-          path, load_count[path][0], load_count[path][1],
-          load_count[path][2]);
-       if (load_count[path][0] == 1)
+          path, bnx2x_load_count[path][0], bnx2x_load_count[path][1],
+          bnx2x_load_count[path][2]);
+       if (bnx2x_load_count[path][0] == 1)
                return FW_MSG_CODE_DRV_LOAD_COMMON;
-       else if (load_count[path][1 + port] == 1)
+       else if (bnx2x_load_count[path][1 + port] == 1)
                return FW_MSG_CODE_DRV_LOAD_PORT;
        else
                return FW_MSG_CODE_DRV_LOAD_FUNCTION;
@@ -2600,7 +2641,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                                LOAD_ERROR_EXIT(bp, load_error1);
 
                        /* what did mcp say? */
-                       rc = bnx2x_nic_load_analyze_req(bp, load_code);
+                       rc = bnx2x_compare_fw_ver(bp, load_code, true);
                        if (rc) {
                                bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
                                LOAD_ERROR_EXIT(bp, load_error2);
@@ -3065,7 +3106,7 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
 /*
  * net_device service functions
  */
-int bnx2x_poll(struct napi_struct *napi, int budget)
+static int bnx2x_poll(struct napi_struct *napi, int budget)
 {
        int work_done = 0;
        u8 cos;
@@ -4192,7 +4233,7 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
        /* end of fastpath */
 }
 
-void bnx2x_free_fp_mem_cnic(struct bnx2x *bp)
+static void bnx2x_free_fp_mem_cnic(struct bnx2x *bp)
 {
        int i;
        for_each_cnic_queue(bp, i)
@@ -4406,7 +4447,7 @@ alloc_mem_err:
        return 0;
 }
 
-int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp)
+static int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp)
 {
        if (!NO_FCOE(bp))
                /* FCoE */
@@ -4419,7 +4460,7 @@ int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp)
        return 0;
 }
 
-int bnx2x_alloc_fp_mem(struct bnx2x *bp)
+static int bnx2x_alloc_fp_mem(struct bnx2x *bp)
 {
        int i;
 
index da8fcaa74495475cb2c2c3984f3aa3cf85fc83ba..7ebbddc7290c839592db6df45ea7a303f14580c2 100644 (file)
 #include "bnx2x_sriov.h"
 
 /* This is used as a replacement for an MCP if it's not present */
-extern int load_count[2][3]; /* per-path: 0-common, 1-port0, 2-port1 */
-
-extern int num_queues;
-extern int int_mode;
+extern int bnx2x_load_count[2][3]; /* per-path: 0-common, 1-port0, 2-port1 */
+extern int bnx2x_num_queues;
 
 /************************ Macros ********************************/
 #define BNX2X_PCI_FREE(x, y, size) \
@@ -417,35 +415,8 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set);
  * If bp->state is OPEN, should be called with
  * netif_addr_lock_bh()
  */
-void bnx2x_set_rx_mode(struct net_device *dev);
 void bnx2x_set_rx_mode_inner(struct bnx2x *bp);
 
-/**
- * bnx2x_set_storm_rx_mode - configure MAC filtering rules in a FW.
- *
- * @bp:                driver handle
- *
- * If bp->state is OPEN, should be called with
- * netif_addr_lock_bh().
- */
-int bnx2x_set_storm_rx_mode(struct bnx2x *bp);
-
-/**
- * bnx2x_set_q_rx_mode - configures rx_mode for a single queue.
- *
- * @bp:                        driver handle
- * @cl_id:             client id
- * @rx_mode_flags:     rx mode configuration
- * @rx_accept_flags:   rx accept configuration
- * @tx_accept_flags:   tx accept configuration (tx switch)
- * @ramrod_flags:      ramrod configuration
- */
-int bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
-                       unsigned long rx_mode_flags,
-                       unsigned long rx_accept_flags,
-                       unsigned long tx_accept_flags,
-                       unsigned long ramrod_flags);
-
 /* Parity errors related */
 void bnx2x_set_pf_load(struct bnx2x *bp);
 bool bnx2x_clear_pf_load(struct bnx2x *bp);
@@ -564,9 +535,6 @@ int bnx2x_reload_if_running(struct net_device *dev);
 
 int bnx2x_change_mac_addr(struct net_device *dev, void *p);
 
-/* NAPI poll Rx part */
-int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
-
 /* NAPI poll Tx part */
 int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata);
 
@@ -577,13 +545,9 @@ int bnx2x_resume(struct pci_dev *pdev);
 /* Release IRQ vectors */
 void bnx2x_free_irq(struct bnx2x *bp);
 
-void bnx2x_free_fp_mem_cnic(struct bnx2x *bp);
 void bnx2x_free_fp_mem(struct bnx2x *bp);
-int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp);
-int bnx2x_alloc_fp_mem(struct bnx2x *bp);
 void bnx2x_init_rx_rings(struct bnx2x *bp);
 void bnx2x_init_rx_rings_cnic(struct bnx2x *bp);
-void bnx2x_free_skbs_cnic(struct bnx2x *bp);
 void bnx2x_free_skbs(struct bnx2x *bp);
 void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
 void bnx2x_netif_start(struct bnx2x *bp);
@@ -606,15 +570,6 @@ int bnx2x_enable_msix(struct bnx2x *bp);
  */
 int bnx2x_enable_msi(struct bnx2x *bp);
 
-/**
- * bnx2x_poll - NAPI callback
- *
- * @napi:      napi structure
- * @budget:
- *
- */
-int bnx2x_poll(struct napi_struct *napi, int budget);
-
 /**
  * bnx2x_low_latency_recv - LL callback
  *
@@ -861,30 +816,6 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
        sge->addr_lo = 0;
 }
 
-static inline void bnx2x_add_all_napi_cnic(struct bnx2x *bp)
-{
-       int i;
-
-       /* Add NAPI objects */
-       for_each_rx_queue_cnic(bp, i) {
-               netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
-                              bnx2x_poll, NAPI_POLL_WEIGHT);
-               napi_hash_add(&bnx2x_fp(bp, i, napi));
-       }
-}
-
-static inline void bnx2x_add_all_napi(struct bnx2x *bp)
-{
-       int i;
-
-       /* Add NAPI objects */
-       for_each_eth_queue(bp, i) {
-               netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
-                              bnx2x_poll, NAPI_POLL_WEIGHT);
-               napi_hash_add(&bnx2x_fp(bp, i, napi));
-       }
-}
-
 static inline void bnx2x_del_all_napi_cnic(struct bnx2x *bp)
 {
        int i;
@@ -918,14 +849,6 @@ static inline void bnx2x_disable_msi(struct bnx2x *bp)
        }
 }
 
-static inline int bnx2x_calc_num_queues(struct bnx2x *bp)
-{
-       return  num_queues ?
-                min_t(int, num_queues, BNX2X_MAX_QUEUES(bp)) :
-                min_t(int, netif_get_num_default_rss_queues(),
-                      BNX2X_MAX_QUEUES(bp));
-}
-
 static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp)
 {
        int i, j;
@@ -1172,8 +1095,6 @@ static inline u8 bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp)
                return fp->cl_id;
 }
 
-u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp);
-
 static inline void bnx2x_init_txdata(struct bnx2x *bp,
                                     struct bnx2x_fp_txdata *txdata, u32 cid,
                                     int txq_index, __le16 *tx_cons_sb,
@@ -1206,47 +1127,6 @@ static inline u8 bnx2x_cnic_igu_sb_id(struct bnx2x *bp)
        return bp->igu_base_sb;
 }
 
-static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
-{
-       struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
-       unsigned long q_type = 0;
-
-       bnx2x_fcoe(bp, rx_queue) = BNX2X_NUM_ETH_QUEUES(bp);
-       bnx2x_fcoe(bp, cl_id) = bnx2x_cnic_eth_cl_id(bp,
-                                                    BNX2X_FCOE_ETH_CL_ID_IDX);
-       bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID(bp);
-       bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
-       bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
-       bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
-       bnx2x_init_txdata(bp, bnx2x_fcoe(bp, txdata_ptr[0]),
-                         fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX,
-                         fp);
-
-       DP(NETIF_MSG_IFUP, "created fcoe tx data (fp index %d)\n", fp->index);
-
-       /* qZone id equals to FW (per path) client id */
-       bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
-       /* init shortcut */
-       bnx2x_fcoe(bp, ustorm_rx_prods_offset) =
-               bnx2x_rx_ustorm_prods_offset(fp);
-
-       /* Configure Queue State object */
-       __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
-       __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
-
-       /* No multi-CoS for FCoE L2 client */
-       BUG_ON(fp->max_cos != 1);
-
-       bnx2x_init_queue_obj(bp, &bnx2x_sp_obj(bp, fp).q_obj, fp->cl_id,
-                            &fp->cid, 1, BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
-                            bnx2x_sp_mapping(bp, q_rdata), q_type);
-
-       DP(NETIF_MSG_IFUP,
-          "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d igu_sb %d\n",
-          fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
-          fp->igu_sb_id);
-}
-
 static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
                                       struct bnx2x_fp_txdata *txdata)
 {
index 32d0f1435fb410b54c3105236c14a211f35bc0b2..92a467ff4104da3bedd8aa6762c51c19ea977a22 100644 (file)
@@ -1639,6 +1639,12 @@ static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf,
 
                memcpy(&val, data_buf, 4);
 
+               /* Notice unlike bnx2x_nvram_read_dword() this will not
+                * change val using be32_to_cpu(), which causes data to flip
+                * if the eeprom is read and then written back. This is due
+                * to tools utilizing this functionality that would break
+                * if this would be resolved.
+                */
                rc = bnx2x_nvram_write_dword(bp, offset, val, cmd_flags);
 
                /* advance to the next dword */
index 20dcc02431cac441a8bf3076a7fe6db1abfb04e9..c5ce99be4d90f4e269277aae48076af54e66e326 100644 (file)
@@ -205,6 +205,11 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,
                (_bank + (_addr & 0xf)), \
                _val)
 
+static int bnx2x_check_half_open_conn(struct link_params *params,
+                                     struct link_vars *vars, u8 notify);
+static int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
+                                     struct link_params *params);
+
 static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
 {
        u32 val = REG_RD(bp, reg);
@@ -1399,57 +1404,6 @@ static void bnx2x_update_pfc_xmac(struct link_params *params,
        udelay(30);
 }
 
-
-static void bnx2x_emac_get_pfc_stat(struct link_params *params,
-                                   u32 pfc_frames_sent[2],
-                                   u32 pfc_frames_received[2])
-{
-       /* Read pfc statistic */
-       struct bnx2x *bp = params->bp;
-       u32 emac_base = params->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-       u32 val_xon = 0;
-       u32 val_xoff = 0;
-
-       DP(NETIF_MSG_LINK, "pfc statistic read from EMAC\n");
-
-       /* PFC received frames */
-       val_xoff = REG_RD(bp, emac_base +
-                               EMAC_REG_RX_PFC_STATS_XOFF_RCVD);
-       val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_RCVD_COUNT;
-       val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_RCVD);
-       val_xon &= EMAC_REG_RX_PFC_STATS_XON_RCVD_COUNT;
-
-       pfc_frames_received[0] = val_xon + val_xoff;
-
-       /* PFC received sent */
-       val_xoff = REG_RD(bp, emac_base +
-                               EMAC_REG_RX_PFC_STATS_XOFF_SENT);
-       val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_SENT_COUNT;
-       val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_SENT);
-       val_xon &= EMAC_REG_RX_PFC_STATS_XON_SENT_COUNT;
-
-       pfc_frames_sent[0] = val_xon + val_xoff;
-}
-
-/* Read pfc statistic*/
-void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
-                        u32 pfc_frames_sent[2],
-                        u32 pfc_frames_received[2])
-{
-       /* Read pfc statistic */
-       struct bnx2x *bp = params->bp;
-
-       DP(NETIF_MSG_LINK, "pfc statistic\n");
-
-       if (!vars->link_up)
-               return;
-
-       if (vars->mac_type == MAC_TYPE_EMAC) {
-               DP(NETIF_MSG_LINK, "About to read PFC stats from EMAC\n");
-               bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
-                                       pfc_frames_received);
-       }
-}
 /******************************************************************/
 /*                     MAC/PBF section                           */
 /******************************************************************/
@@ -3865,6 +3819,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
                bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
        } else {
+               /* Enable Auto-Detect to support 1G over CL37 as well */
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x10);
+
+               /* Force cl48 sync_status LOW to avoid getting stuck in CL73
+                * parallel-detect loop when CL73 and CL37 are enabled.
+                */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI, 0x0800);
+               bnx2x_set_aer_mmd(params, phy);
+
                bnx2x_disable_kr2(params, vars, phy);
        }
 
@@ -8120,17 +8087,20 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                                *edc_mode = EDC_MODE_ACTIVE_DAC;
                        else
                                check_limiting_mode = 1;
-               } else if (copper_module_type &
-                       SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
+               } else {
+                       *edc_mode = EDC_MODE_PASSIVE_DAC;
+                       /* Even in case PASSIVE_DAC indication is not set,
+                        * treat it as a passive DAC cable, since some cables
+                        * don't have this indication.
+                        */
+                       if (copper_module_type &
+                           SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
                                DP(NETIF_MSG_LINK,
                                   "Passive Copper cable detected\n");
-                               *edc_mode =
-                                     EDC_MODE_PASSIVE_DAC;
-               } else {
-                       DP(NETIF_MSG_LINK,
-                          "Unknown copper-cable-type 0x%x !!!\n",
-                          copper_module_type);
-                       return -EINVAL;
+                       } else {
+                               DP(NETIF_MSG_LINK,
+                                  "Unknown copper-cable-type\n");
+                       }
                }
                break;
        }
@@ -10825,9 +10795,9 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                           (1<<11));
 
        if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
-                       (phy->req_line_speed == SPEED_1000)) {
+            (phy->speed_cap_mask &
+             PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+           (phy->req_line_speed == SPEED_1000)) {
                an_1000_val |= (1<<8);
                autoneg_val |= (1<<9 | 1<<12);
                if (phy->req_duplex == DUPLEX_FULL)
@@ -10843,30 +10813,32 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                        0x09,
                        &an_1000_val);
 
-       /* Set 100 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
-               an_10_100_val |= (1<<7);
-               /* Enable autoneg and restart autoneg for legacy speeds */
-               autoneg_val |= (1<<9 | 1<<12);
-
-               if (phy->req_duplex == DUPLEX_FULL)
-                       an_10_100_val |= (1<<8);
-               DP(NETIF_MSG_LINK, "Advertising 100M\n");
-       }
-
-       /* Set 10 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
-               an_10_100_val |= (1<<5);
-               autoneg_val |= (1<<9 | 1<<12);
-               if (phy->req_duplex == DUPLEX_FULL)
+       /* Advertise 10/100 link speed */
+       if (phy->req_line_speed == SPEED_AUTO_NEG) {
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) {
+                       an_10_100_val |= (1<<5);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) {
                        an_10_100_val |= (1<<6);
-               DP(NETIF_MSG_LINK, "Advertising 10M\n");
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-FD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
+                       an_10_100_val |= (1<<7);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
+                       an_10_100_val |= (1<<8);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-FD\n");
+               }
        }
 
        /* Only 10/100 are allowed to work in FORCE mode */
@@ -13342,6 +13314,10 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
        DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,
           old_status, status);
 
+       /* Do not touch the link in case physical link down */
+       if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
+               return 1;
+
        /* a. Update shmem->link_status accordingly
         * b. Update link_vars->link_up
         */
@@ -13391,9 +13367,9 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
 *      a fault, for example, due to break in the TX side of fiber.
 *
 ******************************************************************************/
-int bnx2x_check_half_open_conn(struct link_params *params,
-                               struct link_vars *vars,
-                               u8 notify)
+static int bnx2x_check_half_open_conn(struct link_params *params,
+                                     struct link_vars *vars,
+                                     u8 notify)
 {
        struct bnx2x *bp = params->bp;
        u32 lss_status = 0;
@@ -13550,7 +13526,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
         */
        not_kr2_device = (((base_page & 0x8000) == 0) ||
                          (((base_page & 0x8000) &&
-                           ((next_page & 0xe0) == 0x2))));
+                           ((next_page & 0xe0) == 0x20))));
 
        /* In case KR2 is already disabled, check if we need to re-enable it */
        if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
index 4df45234fdc067fc635919bd70cb9195c0a71525..389f5f8cb0a3c3108f2305b62c0843037ea4f72e 100644 (file)
@@ -533,19 +533,11 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
 int bnx2x_ets_e3b0_config(const struct link_params *params,
                         const struct link_vars *vars,
                         struct bnx2x_ets_params *ets_params);
-/* Read pfc statistic*/
-void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
-                                                u32 pfc_frames_sent[2],
-                                                u32 pfc_frames_received[2]);
+
 void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
                            u32 chip_id, u32 shmem_base, u32 shmem2_base,
                            u8 port);
 
-int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
-                              struct link_params *params);
-
 void bnx2x_period_func(struct link_params *params, struct link_vars *vars);
 
-int bnx2x_check_half_open_conn(struct link_params *params,
-                              struct link_vars *vars, u8 notify);
 #endif /* BNX2X_LINK_H */
index 814d0eca9b334ea86c862bc617a46f137f04d475..f90079acb58c620a5ec9f4d903b355f14a5e48fb 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/aer.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -93,8 +94,8 @@ MODULE_FIRMWARE(FW_FILE_NAME_E1);
 MODULE_FIRMWARE(FW_FILE_NAME_E1H);
 MODULE_FIRMWARE(FW_FILE_NAME_E2);
 
-int num_queues;
-module_param(num_queues, int, 0);
+int bnx2x_num_queues;
+module_param_named(num_queues, bnx2x_num_queues, int, 0);
 MODULE_PARM_DESC(num_queues,
                 " Set number of queues (default is as a number of CPUs)");
 
@@ -102,7 +103,7 @@ static int disable_tpa;
 module_param(disable_tpa, int, 0);
 MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");
 
-int int_mode;
+static int int_mode;
 module_param(int_mode, int, 0);
 MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
                                "(1 INT#x; 2 MSI)");
@@ -278,6 +279,12 @@ MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl);
 #define BNX2X_PREV_WAIT_NEEDED 1
 static DEFINE_SEMAPHORE(bnx2x_prev_sem);
 static LIST_HEAD(bnx2x_prev_list);
+
+/* Forward declaration */
+static struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev);
+static u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp);
+static int bnx2x_set_storm_rx_mode(struct bnx2x *bp);
+
 /****************************************************************************
 * General service functions
 ****************************************************************************/
@@ -3297,6 +3304,10 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
 
        ether_stat->txq_size = bp->tx_ring_size;
        ether_stat->rxq_size = bp->rx_ring_size;
+
+#ifdef CONFIG_BNX2X_SRIOV
+       ether_stat->vf_cnt = IS_SRIOV(bp) ? bp->vfdb->sriov.nr_virtfn : 0;
+#endif
 }
 
 static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
@@ -5852,11 +5863,11 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
 }
 
 /* called with netif_addr_lock_bh() */
-int bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
-                       unsigned long rx_mode_flags,
-                       unsigned long rx_accept_flags,
-                       unsigned long tx_accept_flags,
-                       unsigned long ramrod_flags)
+static int bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
+                              unsigned long rx_mode_flags,
+                              unsigned long rx_accept_flags,
+                              unsigned long tx_accept_flags,
+                              unsigned long ramrod_flags)
 {
        struct bnx2x_rx_mode_ramrod_params ramrod_param;
        int rc;
@@ -5964,7 +5975,7 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode,
 }
 
 /* called with netif_addr_lock_bh() */
-int bnx2x_set_storm_rx_mode(struct bnx2x *bp)
+static int bnx2x_set_storm_rx_mode(struct bnx2x *bp)
 {
        unsigned long rx_mode_flags = 0, ramrod_flags = 0;
        unsigned long rx_accept_flags = 0, tx_accept_flags = 0;
@@ -6160,6 +6171,47 @@ static void bnx2x_init_tx_rings(struct bnx2x *bp)
                        bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[cos]);
 }
 
+static void bnx2x_init_fcoe_fp(struct bnx2x *bp)
+{
+       struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
+       unsigned long q_type = 0;
+
+       bnx2x_fcoe(bp, rx_queue) = BNX2X_NUM_ETH_QUEUES(bp);
+       bnx2x_fcoe(bp, cl_id) = bnx2x_cnic_eth_cl_id(bp,
+                                                    BNX2X_FCOE_ETH_CL_ID_IDX);
+       bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID(bp);
+       bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
+       bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
+       bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
+       bnx2x_init_txdata(bp, bnx2x_fcoe(bp, txdata_ptr[0]),
+                         fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX,
+                         fp);
+
+       DP(NETIF_MSG_IFUP, "created fcoe tx data (fp index %d)\n", fp->index);
+
+       /* qZone id equals to FW (per path) client id */
+       bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
+       /* init shortcut */
+       bnx2x_fcoe(bp, ustorm_rx_prods_offset) =
+               bnx2x_rx_ustorm_prods_offset(fp);
+
+       /* Configure Queue State object */
+       __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
+       __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
+
+       /* No multi-CoS for FCoE L2 client */
+       BUG_ON(fp->max_cos != 1);
+
+       bnx2x_init_queue_obj(bp, &bnx2x_sp_obj(bp, fp).q_obj, fp->cl_id,
+                            &fp->cid, 1, BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
+                            bnx2x_sp_mapping(bp, q_rdata), q_type);
+
+       DP(NETIF_MSG_IFUP,
+          "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d igu_sb %d\n",
+          fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
+          fp->igu_sb_id);
+}
+
 void bnx2x_nic_init_cnic(struct bnx2x *bp)
 {
        if (!NO_FCOE(bp))
@@ -8732,16 +8784,16 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode)
                int path = BP_PATH(bp);
 
                DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d]      %d, %d, %d\n",
-                  path, load_count[path][0], load_count[path][1],
-                  load_count[path][2]);
-               load_count[path][0]--;
-               load_count[path][1 + port]--;
+                  path, bnx2x_load_count[path][0], bnx2x_load_count[path][1],
+                  bnx2x_load_count[path][2]);
+               bnx2x_load_count[path][0]--;
+               bnx2x_load_count[path][1 + port]--;
                DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d]  %d, %d, %d\n",
-                  path, load_count[path][0], load_count[path][1],
-                  load_count[path][2]);
-               if (load_count[path][0] == 0)
+                  path, bnx2x_load_count[path][0], bnx2x_load_count[path][1],
+                  bnx2x_load_count[path][2]);
+               if (bnx2x_load_count[path][0] == 0)
                        reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
-               else if (load_count[path][1 + port] == 0)
+               else if (bnx2x_load_count[path][1 + port] == 0)
                        reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
                else
                        reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
@@ -9767,7 +9819,7 @@ period_task_exit:
  * Init service functions
  */
 
-u32 bnx2x_get_pretend_reg(struct bnx2x *bp)
+static u32 bnx2x_get_pretend_reg(struct bnx2x *bp)
 {
        u32 base = PXP2_REG_PGL_PRETEND_FUNC_F0;
        u32 stride = PXP2_REG_PGL_PRETEND_FUNC_F1 - base;
@@ -9854,6 +9906,64 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
 #define BNX2X_PREV_UNDI_BD(val)                ((val) >> 16 & 0xffff)
 #define BNX2X_PREV_UNDI_PROD(rcq, bd)  ((bd) << 16 | (rcq))
 
+#define BCM_5710_UNDI_FW_MF_MAJOR      (0x07)
+#define BCM_5710_UNDI_FW_MF_MINOR      (0x08)
+#define BCM_5710_UNDI_FW_MF_VERS       (0x05)
+#define BNX2X_PREV_UNDI_MF_PORT(p)     (0x1a150c + ((p) << 4))
+#define BNX2X_PREV_UNDI_MF_FUNC(f)     (0x1a184c + ((f) << 4))
+static bool bnx2x_prev_unload_undi_fw_supports_mf(struct bnx2x *bp)
+{
+       u8 major, minor, version;
+       u32 fw;
+
+       /* Must check that FW is loaded */
+       if (!(REG_RD(bp, MISC_REG_RESET_REG_1) &
+            MISC_REGISTERS_RESET_REG_1_RST_XSEM)) {
+               BNX2X_DEV_INFO("XSEM is reset - UNDI MF FW is not loaded\n");
+               return false;
+       }
+
+       /* Read Currently loaded FW version */
+       fw = REG_RD(bp, XSEM_REG_PRAM);
+       major = fw & 0xff;
+       minor = (fw >> 0x8) & 0xff;
+       version = (fw >> 0x10) & 0xff;
+       BNX2X_DEV_INFO("Loaded FW: 0x%08x: Major 0x%02x Minor 0x%02x Version 0x%02x\n",
+                      fw, major, minor, version);
+
+       if (major > BCM_5710_UNDI_FW_MF_MAJOR)
+               return true;
+
+       if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
+           (minor > BCM_5710_UNDI_FW_MF_MINOR))
+               return true;
+
+       if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
+           (minor == BCM_5710_UNDI_FW_MF_MINOR) &&
+           (version >= BCM_5710_UNDI_FW_MF_VERS))
+               return true;
+
+       return false;
+}
+
+static void bnx2x_prev_unload_undi_mf(struct bnx2x *bp)
+{
+       int i;
+
+       /* Due to legacy (FW) code, the first function on each engine has a
+        * different offset macro from the rest of the functions.
+        * Setting this for all 8 functions is harmless regardless of whether
+        * this is actually a multi-function device.
+        */
+       for (i = 0; i < 2; i++)
+               REG_WR(bp, BNX2X_PREV_UNDI_MF_PORT(i), 1);
+
+       for (i = 2; i < 8; i++)
+               REG_WR(bp, BNX2X_PREV_UNDI_MF_FUNC(i - 2), 1);
+
+       BNX2X_DEV_INFO("UNDI FW (MF) set to discard\n");
+}
+
 static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, u8 inc)
 {
        u16 rcq, bd;
@@ -10054,7 +10164,7 @@ static int bnx2x_prev_unload_uncommon(struct bnx2x *bp)
         * the one required, then FLR will be sufficient to clean any residue
         * left by previous driver
         */
-       rc = bnx2x_nic_load_analyze_req(bp, FW_MSG_CODE_DRV_LOAD_FUNCTION);
+       rc = bnx2x_compare_fw_ver(bp, FW_MSG_CODE_DRV_LOAD_FUNCTION, false);
 
        if (!rc) {
                /* fw version is good */
@@ -10142,10 +10252,17 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
                        else
                                timer_count--;
 
-                       /* If UNDI resides in memory, manually increment it */
-                       if (prev_undi)
+                       /* New UNDI FW supports MF and contains better
+                        * cleaning methods - might be redundant but harmless.
+                        */
+                       if (bnx2x_prev_unload_undi_fw_supports_mf(bp)) {
+                               bnx2x_prev_unload_undi_mf(bp);
+                       } else if (prev_undi) {
+                               /* If UNDI resides in memory,
+                                * manually increment it
+                                */
                                bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1);
-
+                       }
                        udelay(10);
                }
 
@@ -10265,8 +10382,8 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
        } while (--time_counter);
 
        if (!time_counter || rc) {
-               BNX2X_ERR("Failed unloading previous driver, aborting\n");
-               rc = -EBUSY;
+               BNX2X_DEV_INFO("Unloading previous driver did not occur, Possibly due to MF UNDI\n");
+               rc = -EPROBE_DEFER;
        }
 
        /* Mark function if its port was used to boot from SAN */
@@ -11447,9 +11564,9 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
                }
        }
 
-       /* adjust igu_sb_cnt to MF for E1x */
-       if (CHIP_IS_E1x(bp) && IS_MF(bp))
-               bp->igu_sb_cnt /= E1HVN_MAX;
+       /* adjust igu_sb_cnt to MF for E1H */
+       if (CHIP_IS_E1H(bp) && IS_MF(bp))
+               bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, E1H_MAX_MF_SB_COUNT);
 
        /* port info */
        bnx2x_get_port_hwinfo(bp);
@@ -11636,7 +11753,11 @@ static int bnx2x_init_bp(struct bnx2x *bp)
                                                        DRV_MSG_SEQ_NUMBER_MASK;
                BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
 
-               bnx2x_prev_unload(bp);
+               rc = bnx2x_prev_unload(bp);
+               if (rc) {
+                       bnx2x_free_mem_bp(bp);
+                       return rc;
+               }
        }
 
        if (CHIP_REV_IS_FPGA(bp))
@@ -11931,7 +12052,7 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
 }
 
 /* If bp->state is OPEN, should be called with netif_addr_lock_bh() */
-void bnx2x_set_rx_mode(struct net_device *dev)
+static void bnx2x_set_rx_mode(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
@@ -12156,6 +12277,14 @@ static int bnx2x_set_coherency_mask(struct bnx2x *bp)
        return 0;
 }
 
+static void bnx2x_disable_pcie_error_reporting(struct bnx2x *bp)
+{
+       if (bp->flags & AER_ENABLED) {
+               pci_disable_pcie_error_reporting(bp->pdev);
+               bp->flags &= ~AER_ENABLED;
+       }
+}
+
 static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
                          struct net_device *dev, unsigned long board_type)
 {
@@ -12262,6 +12391,14 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
        /* clean indirect addresses */
        pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS,
                               PCICFG_VENDOR_ID_OFFSET);
+
+       /* AER (Advanced Error reporting) configuration */
+       rc = pci_enable_pcie_error_reporting(pdev);
+       if (!rc)
+               bp->flags |= AER_ENABLED;
+       else
+               BNX2X_DEV_INFO("Failed To configure PCIe AER [%d]\n", rc);
+
        /*
         * Clean the following indirect addresses for all functions since it
         * is not used by the driver.
@@ -12693,8 +12830,6 @@ static int set_is_vf(int chip_id)
        }
 }
 
-struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev);
-
 static int bnx2x_init_one(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
 {
@@ -12869,6 +13004,8 @@ static int bnx2x_init_one(struct pci_dev *pdev,
        return 0;
 
 init_one_exit:
+       bnx2x_disable_pcie_error_reporting(bp);
+
        if (bp->regview)
                iounmap(bp->regview);
 
@@ -12942,6 +13079,8 @@ static void __bnx2x_remove(struct pci_dev *pdev,
                pci_set_power_state(pdev, PCI_D3hot);
        }
 
+       bnx2x_disable_pcie_error_reporting(bp);
+
        if (bp->regview)
                iounmap(bp->regview);
 
@@ -13119,6 +13258,14 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev)
 
        rtnl_unlock();
 
+       /* If AER, perform cleanup of the PCIe registers */
+       if (bp->flags & AER_ENABLED) {
+               if (pci_cleanup_aer_uncorrect_error_status(pdev))
+                       BNX2X_ERR("pci_cleanup_aer_uncorrect_error_status failed\n");
+               else
+                       DP(NETIF_MSG_HW, "pci_cleanup_aer_uncorrect_error_status succeeded\n");
+       }
+
        return PCI_ERS_RESULT_RECOVERED;
 }
 
@@ -13757,7 +13904,7 @@ static int bnx2x_unregister_cnic(struct net_device *dev)
        return 0;
 }
 
-struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
+static struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
        struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
@@ -13807,7 +13954,7 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
        return cp;
 }
 
-u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
+static u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
 {
        struct bnx2x *bp = fp->bp;
        u32 offset = BAR_USTRORM_INTMEM;
index 3efbb35267c853d576cc3a4d3104ec4ba1a18d1d..2beb5430b876cb8d77cec26661c51140ab2712ed 100644 (file)
 #define MISC_REGISTERS_RESET_REG_1_RST_NIG                      (0x1<<7)
 #define MISC_REGISTERS_RESET_REG_1_RST_PXP                      (0x1<<26)
 #define MISC_REGISTERS_RESET_REG_1_RST_PXPV                     (0x1<<27)
+#define MISC_REGISTERS_RESET_REG_1_RST_XSEM                     (0x1<<22)
 #define MISC_REGISTERS_RESET_REG_1_SET                          0x584
 #define MISC_REGISTERS_RESET_REG_2_CLEAR                        0x598
 #define MISC_REGISTERS_RESET_REG_2_MSTAT0                       (0x1<<24)
@@ -7179,6 +7180,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_RX1_PCI_CTRL                       0x80ca
 #define MDIO_WC_REG_RX2_PCI_CTRL                       0x80da
 #define MDIO_WC_REG_RX3_PCI_CTRL                       0x80ea
+#define MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI             0x80fa
 #define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G          0x8104
 #define MDIO_WC_REG_XGXS_STATUS3                       0x8129
 #define MDIO_WC_REG_PAR_DET_10G_STATUS                 0x8130
index 32c92abf50949fa1494812ab9d3734a5a2f3db1f..9373584e400f1addf2c4827247f1ea9b5d082225 100644 (file)
@@ -355,23 +355,6 @@ static bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o)
 
        return vp->get(vp, 1);
 }
-
-static bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
-{
-       struct bnx2x_credit_pool_obj *mp = o->macs_pool;
-       struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
-
-       if (!mp->get(mp, 1))
-               return false;
-
-       if (!vp->get(vp, 1)) {
-               mp->put(mp, 1);
-               return false;
-       }
-
-       return true;
-}
-
 static bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset)
 {
        struct bnx2x_credit_pool_obj *mp = o->macs_pool;
@@ -400,22 +383,6 @@ static bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o)
        return vp->put(vp, 1);
 }
 
-static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
-{
-       struct bnx2x_credit_pool_obj *mp = o->macs_pool;
-       struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
-
-       if (!mp->put(mp, 1))
-               return false;
-
-       if (!vp->put(vp, 1)) {
-               mp->get(mp, 1);
-               return false;
-       }
-
-       return true;
-}
-
 /**
  * __bnx2x_vlan_mac_h_write_trylock - try getting the vlan mac writer lock
  *
@@ -507,22 +474,6 @@ static void __bnx2x_vlan_mac_h_write_unlock(struct bnx2x *bp,
        }
 }
 
-/**
- * bnx2x_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock
- *
- * @bp:                        device handle
- * @o:                 vlan_mac object
- *
- * @details Notice if a pending execution exists, it would perform it -
- *          possibly releasing and reclaiming the execution queue lock.
- */
-void bnx2x_vlan_mac_h_write_unlock(struct bnx2x *bp,
-                                  struct bnx2x_vlan_mac_obj *o)
-{
-       spin_lock_bh(&o->exe_queue.lock);
-       __bnx2x_vlan_mac_h_write_unlock(bp, o);
-       spin_unlock_bh(&o->exe_queue.lock);
-}
 
 /**
  * __bnx2x_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
@@ -663,7 +614,7 @@ static int bnx2x_check_mac_add(struct bnx2x *bp,
 
        /* Check if a requested MAC already exists */
        list_for_each_entry(pos, &o->head, link)
-               if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN) &&
+               if (ether_addr_equal(data->mac.mac, pos->u.mac.mac) &&
                    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
                        return -EEXIST;
 
@@ -685,26 +636,6 @@ static int bnx2x_check_vlan_add(struct bnx2x *bp,
        return 0;
 }
 
-static int bnx2x_check_vlan_mac_add(struct bnx2x *bp,
-                                   struct bnx2x_vlan_mac_obj *o,
-                                  union bnx2x_classification_ramrod_data *data)
-{
-       struct bnx2x_vlan_mac_registry_elem *pos;
-
-       DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for ADD command\n",
-          data->vlan_mac.mac, data->vlan_mac.vlan);
-
-       list_for_each_entry(pos, &o->head, link)
-               if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
-                   (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
-                                 ETH_ALEN)) &&
-                   (data->vlan_mac.is_inner_mac ==
-                    pos->u.vlan_mac.is_inner_mac))
-                       return -EEXIST;
-
-       return 0;
-}
-
 /* check_del() callbacks */
 static struct bnx2x_vlan_mac_registry_elem *
        bnx2x_check_mac_del(struct bnx2x *bp,
@@ -716,7 +647,7 @@ static struct bnx2x_vlan_mac_registry_elem *
        DP(BNX2X_MSG_SP, "Checking MAC %pM for DEL command\n", data->mac.mac);
 
        list_for_each_entry(pos, &o->head, link)
-               if ((!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN)) &&
+               if (ether_addr_equal(data->mac.mac, pos->u.mac.mac) &&
                    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
                        return pos;
 
@@ -739,27 +670,6 @@ static struct bnx2x_vlan_mac_registry_elem *
        return NULL;
 }
 
-static struct bnx2x_vlan_mac_registry_elem *
-       bnx2x_check_vlan_mac_del(struct bnx2x *bp,
-                                struct bnx2x_vlan_mac_obj *o,
-                                union bnx2x_classification_ramrod_data *data)
-{
-       struct bnx2x_vlan_mac_registry_elem *pos;
-
-       DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for DEL command\n",
-          data->vlan_mac.mac, data->vlan_mac.vlan);
-
-       list_for_each_entry(pos, &o->head, link)
-               if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
-                   (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
-                            ETH_ALEN)) &&
-                   (data->vlan_mac.is_inner_mac ==
-                    pos->u.vlan_mac.is_inner_mac))
-                       return pos;
-
-       return NULL;
-}
-
 /* check_move() callback */
 static bool bnx2x_check_move(struct bnx2x *bp,
                             struct bnx2x_vlan_mac_obj *src_o,
@@ -811,8 +721,8 @@ static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
        return rx_tx_flag;
 }
 
-void bnx2x_set_mac_in_nig(struct bnx2x *bp,
-                         bool add, unsigned char *dev_addr, int index)
+static void bnx2x_set_mac_in_nig(struct bnx2x *bp,
+                                bool add, unsigned char *dev_addr, int index)
 {
        u32 wb_data[2];
        u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
@@ -1126,97 +1036,6 @@ static void bnx2x_set_one_vlan_e2(struct bnx2x *bp,
                                        rule_cnt);
 }
 
-static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
-                                     struct bnx2x_vlan_mac_obj *o,
-                                     struct bnx2x_exeq_elem *elem,
-                                     int rule_idx, int cam_offset)
-{
-       struct bnx2x_raw_obj *raw = &o->raw;
-       struct eth_classify_rules_ramrod_data *data =
-               (struct eth_classify_rules_ramrod_data *)(raw->rdata);
-       int rule_cnt = rule_idx + 1;
-       union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
-       enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
-       bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
-       u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
-       u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
-
-       /* Reset the ramrod data buffer for the first rule */
-       if (rule_idx == 0)
-               memset(data, 0, sizeof(*data));
-
-       /* Set a rule header */
-       bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
-                                     &rule_entry->pair.header);
-
-       /* Set VLAN and MAC themselves */
-       rule_entry->pair.vlan = cpu_to_le16(vlan);
-       bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
-                             &rule_entry->pair.mac_mid,
-                             &rule_entry->pair.mac_lsb, mac);
-       rule_entry->pair.inner_mac =
-               cpu_to_le16(elem->cmd_data.vlan_mac.u.vlan_mac.is_inner_mac);
-       /* MOVE: Add a rule that will add this MAC to the target Queue */
-       if (cmd == BNX2X_VLAN_MAC_MOVE) {
-               rule_entry++;
-               rule_cnt++;
-
-               /* Setup ramrod data */
-               bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
-                                       elem->cmd_data.vlan_mac.target_obj,
-                                             true, CLASSIFY_RULE_OPCODE_PAIR,
-                                             &rule_entry->pair.header);
-
-               /* Set a VLAN itself */
-               rule_entry->pair.vlan = cpu_to_le16(vlan);
-               bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
-                                     &rule_entry->pair.mac_mid,
-                                     &rule_entry->pair.mac_lsb, mac);
-               rule_entry->pair.inner_mac =
-                       cpu_to_le16(elem->cmd_data.vlan_mac.u.
-                                               vlan_mac.is_inner_mac);
-       }
-
-       /* Set the ramrod data header */
-       /* TODO: take this to the higher level in order to prevent multiple
-                writing */
-       bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
-                                       rule_cnt);
-}
-
-/**
- * bnx2x_set_one_vlan_mac_e1h -
- *
- * @bp:                device handle
- * @o:         bnx2x_vlan_mac_obj
- * @elem:      bnx2x_exeq_elem
- * @rule_idx:  rule_idx
- * @cam_offset:        cam_offset
- */
-static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
-                                      struct bnx2x_vlan_mac_obj *o,
-                                      struct bnx2x_exeq_elem *elem,
-                                      int rule_idx, int cam_offset)
-{
-       struct bnx2x_raw_obj *raw = &o->raw;
-       struct mac_configuration_cmd *config =
-               (struct mac_configuration_cmd *)(raw->rdata);
-       /* 57710 and 57711 do not support MOVE command,
-        * so it's either ADD or DEL
-        */
-       bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
-               true : false;
-
-       /* Reset the ramrod data buffer */
-       memset(config, 0, sizeof(*config));
-
-       bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING,
-                                    cam_offset, add,
-                                    elem->cmd_data.vlan_mac.u.vlan_mac.mac,
-                                    elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
-                                    ETH_VLAN_FILTER_CLASSIFY, config);
-}
-
 /**
  * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
  *
@@ -1316,24 +1135,6 @@ static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan(
        return NULL;
 }
 
-static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac(
-       struct bnx2x_exe_queue_obj *o,
-       struct bnx2x_exeq_elem *elem)
-{
-       struct bnx2x_exeq_elem *pos;
-       struct bnx2x_vlan_mac_ramrod_data *data =
-               &elem->cmd_data.vlan_mac.u.vlan_mac;
-
-       /* Check pending for execution commands */
-       list_for_each_entry(pos, &o->exe_queue, link)
-               if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
-                             sizeof(*data)) &&
-                   (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
-                       return pos;
-
-       return NULL;
-}
-
 /**
  * bnx2x_validate_vlan_mac_add - check if an ADD command can be executed
  *
@@ -2038,6 +1839,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        struct bnx2x_vlan_mac_ramrod_params p;
        struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
        struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
+       unsigned long flags;
        int read_lock;
        int rc = 0;
 
@@ -2046,8 +1848,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        spin_lock_bh(&exeq->lock);
 
        list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
-               if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
-                   *vlan_mac_flags) {
+               flags = exeq_pos->cmd_data.vlan_mac.vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        rc = exeq->remove(bp, exeq->owner, exeq_pos);
                        if (rc) {
                                BNX2X_ERR("Failed to remove command\n");
@@ -2080,7 +1883,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
                return read_lock;
 
        list_for_each_entry(pos, &o->head, link) {
-               if (pos->vlan_mac_flags == *vlan_mac_flags) {
+               flags = pos->vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
                        memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
                        rc = bnx2x_config_vlan_mac(bp, &p);
@@ -2237,69 +2042,6 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
        }
 }
 
-void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
-                            struct bnx2x_vlan_mac_obj *vlan_mac_obj,
-                            u8 cl_id, u32 cid, u8 func_id, void *rdata,
-                            dma_addr_t rdata_mapping, int state,
-                            unsigned long *pstate, bnx2x_obj_type type,
-                            struct bnx2x_credit_pool_obj *macs_pool,
-                            struct bnx2x_credit_pool_obj *vlans_pool)
-{
-       union bnx2x_qable_obj *qable_obj =
-               (union bnx2x_qable_obj *)vlan_mac_obj;
-
-       bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
-                                  rdata_mapping, state, pstate, type,
-                                  macs_pool, vlans_pool);
-
-       /* CAM pool handling */
-       vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac;
-       vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac;
-       /* CAM offset is relevant for 57710 and 57711 chips only which have a
-        * single CAM for both MACs and VLAN-MAC pairs. So the offset
-        * will be taken from MACs' pool object only.
-        */
-       vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
-       vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
-
-       if (CHIP_IS_E1(bp)) {
-               BNX2X_ERR("Do not support chips others than E2\n");
-               BUG();
-       } else if (CHIP_IS_E1H(bp)) {
-               vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e1h;
-               vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
-               vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
-               vlan_mac_obj->check_move        = bnx2x_check_move_always_err;
-               vlan_mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
-
-               /* Exe Queue */
-               bnx2x_exe_queue_init(bp,
-                                    &vlan_mac_obj->exe_queue, 1, qable_obj,
-                                    bnx2x_validate_vlan_mac,
-                                    bnx2x_remove_vlan_mac,
-                                    bnx2x_optimize_vlan_mac,
-                                    bnx2x_execute_vlan_mac,
-                                    bnx2x_exeq_get_vlan_mac);
-       } else {
-               vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e2;
-               vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
-               vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
-               vlan_mac_obj->check_move        = bnx2x_check_move;
-               vlan_mac_obj->ramrod_cmd        =
-                       RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
-
-               /* Exe Queue */
-               bnx2x_exe_queue_init(bp,
-                                    &vlan_mac_obj->exe_queue,
-                                    CLASSIFY_RULES_COUNT,
-                                    qable_obj, bnx2x_validate_vlan_mac,
-                                    bnx2x_remove_vlan_mac,
-                                    bnx2x_optimize_vlan_mac,
-                                    bnx2x_execute_vlan_mac,
-                                    bnx2x_exeq_get_vlan_mac);
-       }
-}
-
 /* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
 static inline void __storm_memset_mac_filters(struct bnx2x *bp,
                        struct tstorm_eth_mac_filter_config *mac_filters,
@@ -4382,8 +4124,11 @@ int bnx2x_config_rss(struct bnx2x *bp,
        struct bnx2x_raw_obj *r = &o->raw;
 
        /* Do nothing if only driver cleanup was requested */
-       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
+       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+               DP(BNX2X_MSG_SP, "Not configuring RSS ramrod_flags=%lx\n",
+                  p->ramrod_flags);
                return 0;
+       }
 
        r->set_pending(r);
 
index 658f4e33abf9281d76e083873cb963c9b47b05f1..c8b939b141dec7c146686c094d9b88a0f8f3de76 100644 (file)
@@ -266,6 +266,13 @@ enum {
        BNX2X_DONT_CONSUME_CAM_CREDIT,
        BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
 };
+/* When looking for matching filters, some flags are not interesting */
+#define BNX2X_VLAN_MAC_CMP_MASK        (1 << BNX2X_UC_LIST_MAC | \
+                                1 << BNX2X_ETH_MAC | \
+                                1 << BNX2X_ISCSI_ETH_MAC | \
+                                1 << BNX2X_NETQ_ETH_MAC)
+#define BNX2X_VLAN_MAC_CMP_FLAGS(flags) \
+       ((flags) & BNX2X_VLAN_MAC_CMP_MASK)
 
 struct bnx2x_vlan_mac_ramrod_params {
        /* Object to run the command from */
@@ -441,9 +448,6 @@ enum {
        BNX2X_LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE / 2
 };
 
-void bnx2x_set_mac_in_nig(struct bnx2x *bp,
-                         bool add, unsigned char *dev_addr, int index);
-
 /** RX_MODE verbs:DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
 
 /* RX_MODE ramrod special flags: set in rx_mode_flags field in
@@ -1300,22 +1304,12 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
                         unsigned long *pstate, bnx2x_obj_type type,
                         struct bnx2x_credit_pool_obj *vlans_pool);
 
-void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
-                            struct bnx2x_vlan_mac_obj *vlan_mac_obj,
-                            u8 cl_id, u32 cid, u8 func_id, void *rdata,
-                            dma_addr_t rdata_mapping, int state,
-                            unsigned long *pstate, bnx2x_obj_type type,
-                            struct bnx2x_credit_pool_obj *macs_pool,
-                            struct bnx2x_credit_pool_obj *vlans_pool);
-
 int bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
                                        struct bnx2x_vlan_mac_obj *o);
 void bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
                                  struct bnx2x_vlan_mac_obj *o);
 int bnx2x_vlan_mac_h_write_lock(struct bnx2x *bp,
                                struct bnx2x_vlan_mac_obj *o);
-void bnx2x_vlan_mac_h_write_unlock(struct bnx2x *bp,
-                                         struct bnx2x_vlan_mac_obj *o);
 int bnx2x_config_vlan_mac(struct bnx2x *bp,
                           struct bnx2x_vlan_mac_ramrod_params *p);
 
index 2e46c28fc6019a892f7792c6017effe3f7db7063..208636d05cc0d51e97b8703c5fb22fd5a21cdffb 100644 (file)
@@ -166,6 +166,7 @@ enum bnx2x_vfop_qteardown_state {
           BNX2X_VFOP_QTEARDOWN_RXMODE,
           BNX2X_VFOP_QTEARDOWN_CLR_VLAN,
           BNX2X_VFOP_QTEARDOWN_CLR_MAC,
+          BNX2X_VFOP_QTEARDOWN_CLR_MCAST,
           BNX2X_VFOP_QTEARDOWN_QDTOR,
           BNX2X_VFOP_QTEARDOWN_DONE
 };
@@ -798,10 +799,10 @@ int bnx2x_vfop_mac_list_cmd(struct bnx2x *bp,
        return -ENOMEM;
 }
 
-int bnx2x_vfop_vlan_set_cmd(struct bnx2x *bp,
-                           struct bnx2x_virtf *vf,
-                           struct bnx2x_vfop_cmd *cmd,
-                           int qid, u16 vid, bool add)
+static int bnx2x_vfop_vlan_set_cmd(struct bnx2x *bp,
+                                  struct bnx2x_virtf *vf,
+                                  struct bnx2x_vfop_cmd *cmd,
+                                  int qid, u16 vid, bool add)
 {
        struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
        int rc;
@@ -1112,7 +1113,10 @@ static void bnx2x_vfop_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf)
        switch (state) {
        case BNX2X_VFOP_MCAST_DEL:
                /* clear existing mcasts */
-               vfop->state = BNX2X_VFOP_MCAST_ADD;
+               vfop->state = (args->mc_num) ? BNX2X_VFOP_MCAST_ADD
+                                            : BNX2X_VFOP_MCAST_CHK_DONE;
+               mcast->mcast_list_len = vf->mcast_list_len;
+               vf->mcast_list_len = args->mc_num;
                vfop->rc = bnx2x_config_mcast(bp, mcast, BNX2X_MCAST_CMD_DEL);
                bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT);
 
@@ -1120,17 +1124,17 @@ static void bnx2x_vfop_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf)
                if (raw->check_pending(raw))
                        goto op_pending;
 
-               if (args->mc_num) {
-                       /* update mcast list on the ramrod params */
-                       INIT_LIST_HEAD(&mcast->mcast_list);
-                       for (i = 0; i < args->mc_num; i++)
-                               list_add_tail(&(args->mc[i].link),
-                                             &mcast->mcast_list);
-                       /* add new mcasts */
-                       vfop->state = BNX2X_VFOP_MCAST_CHK_DONE;
-                       vfop->rc = bnx2x_config_mcast(bp, mcast,
-                                                     BNX2X_MCAST_CMD_ADD);
-               }
+               /* update mcast list on the ramrod params */
+               INIT_LIST_HEAD(&mcast->mcast_list);
+               for (i = 0; i < args->mc_num; i++)
+                       list_add_tail(&(args->mc[i].link),
+                                     &mcast->mcast_list);
+               mcast->mcast_list_len = args->mc_num;
+
+               /* add new mcasts */
+               vfop->state = BNX2X_VFOP_MCAST_CHK_DONE;
+               vfop->rc = bnx2x_config_mcast(bp, mcast,
+                                             BNX2X_MCAST_CMD_ADD);
                bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE);
 
        case BNX2X_VFOP_MCAST_CHK_DONE:
@@ -1209,6 +1213,11 @@ static void bnx2x_vfop_rxmode(struct bnx2x *bp, struct bnx2x_virtf *vf)
                /* next state */
                vfop->state = BNX2X_VFOP_RXMODE_DONE;
 
+               /* record the accept flags in vfdb so hypervisor can modify them
+                * if necessary
+                */
+               bnx2x_vfq(vf, ramrod->cl_id - vf->igu_base_id, accept_flags) =
+                       ramrod->rx_accept_flags;
                vfop->rc = bnx2x_config_rx_mode(bp, ramrod);
                bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE);
 op_err:
@@ -1224,39 +1233,43 @@ op_pending:
        return;
 }
 
+static void bnx2x_vf_prep_rx_mode(struct bnx2x *bp, u8 qid,
+                                 struct bnx2x_rx_mode_ramrod_params *ramrod,
+                                 struct bnx2x_virtf *vf,
+                                 unsigned long accept_flags)
+{
+       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
+
+       memset(ramrod, 0, sizeof(*ramrod));
+       ramrod->cid = vfq->cid;
+       ramrod->cl_id = vfq_cl_id(vf, vfq);
+       ramrod->rx_mode_obj = &bp->rx_mode_obj;
+       ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
+       ramrod->rx_accept_flags = accept_flags;
+       ramrod->tx_accept_flags = accept_flags;
+       ramrod->pstate = &vf->filter_state;
+       ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
+
+       set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
+       set_bit(RAMROD_RX, &ramrod->ramrod_flags);
+       set_bit(RAMROD_TX, &ramrod->ramrod_flags);
+
+       ramrod->rdata = bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
+       ramrod->rdata_mapping = bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+}
+
 int bnx2x_vfop_rxmode_cmd(struct bnx2x *bp,
                          struct bnx2x_virtf *vf,
                          struct bnx2x_vfop_cmd *cmd,
                          int qid, unsigned long accept_flags)
 {
-       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
        struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
 
        if (vfop) {
                struct bnx2x_rx_mode_ramrod_params *ramrod =
                        &vf->op_params.rx_mode;
 
-               memset(ramrod, 0, sizeof(*ramrod));
-
-               /* Prepare ramrod parameters */
-               ramrod->cid = vfq->cid;
-               ramrod->cl_id = vfq_cl_id(vf, vfq);
-               ramrod->rx_mode_obj = &bp->rx_mode_obj;
-               ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
-
-               ramrod->rx_accept_flags = accept_flags;
-               ramrod->tx_accept_flags = accept_flags;
-               ramrod->pstate = &vf->filter_state;
-               ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
-
-               set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
-               set_bit(RAMROD_RX, &ramrod->ramrod_flags);
-               set_bit(RAMROD_TX, &ramrod->ramrod_flags);
-
-               ramrod->rdata =
-                       bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
-               ramrod->rdata_mapping =
-                       bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+               bnx2x_vf_prep_rx_mode(bp, qid, ramrod, vf, accept_flags);
 
                bnx2x_vfop_opset(BNX2X_VFOP_RXMODE_CONFIG,
                                 bnx2x_vfop_rxmode, cmd->done);
@@ -1303,12 +1316,19 @@ static void bnx2x_vfop_qdown(struct bnx2x *bp, struct bnx2x_virtf *vf)
 
        case BNX2X_VFOP_QTEARDOWN_CLR_MAC:
                /* mac-clear-all: consume credit */
-               vfop->state = BNX2X_VFOP_QTEARDOWN_QDTOR;
+               vfop->state = BNX2X_VFOP_QTEARDOWN_CLR_MCAST;
                vfop->rc = bnx2x_vfop_mac_delall_cmd(bp, vf, &cmd, qid, false);
                if (vfop->rc)
                        goto op_err;
                return;
 
+       case BNX2X_VFOP_QTEARDOWN_CLR_MCAST:
+               vfop->state = BNX2X_VFOP_QTEARDOWN_QDTOR;
+               vfop->rc = bnx2x_vfop_mcast_cmd(bp, vf, &cmd, NULL, 0, false);
+               if (vfop->rc)
+                       goto op_err;
+               return;
+
        case BNX2X_VFOP_QTEARDOWN_QDTOR:
                /* run the queue destruction flow */
                DP(BNX2X_MSG_IOV, "case: BNX2X_VFOP_QTEARDOWN_QDTOR\n");
@@ -2188,6 +2208,7 @@ int bnx2x_iov_nic_init(struct bnx2x *bp)
                 *  It needs to be initialized here so that it can be safely
                 *  handled by a subsequent FLR flow.
                 */
+               vf->mcast_list_len = 0;
                bnx2x_init_mcast_obj(bp, &vf->mcast_obj, 0xFF,
                                     0xFF, 0xFF, 0xFF,
                                     bnx2x_vf_sp(bp, vf, mcast_rdata),
@@ -2848,13 +2869,9 @@ static void bnx2x_vfop_close(struct bnx2x *bp, struct bnx2x_virtf *vf)
                                goto op_err;
                        return;
                }
-
-               /* remove multicasts */
                vfop->state = BNX2X_VFOP_CLOSE_HW;
-               vfop->rc = bnx2x_vfop_mcast_cmd(bp, vf, &cmd, NULL, 0, false);
-               if (vfop->rc)
-                       goto op_err;
-               return;
+               vfop->rc = 0;
+               bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT);
 
        case BNX2X_VFOP_CLOSE_HW:
 
@@ -2888,6 +2905,9 @@ op_done:
 
        DP(BNX2X_MSG_IOV, "set state to acquired\n");
        bnx2x_vfop_end(bp, vf, vfop);
+op_pending:
+       /* Not supported at the moment; Exists for macros only */
+       return;
 }
 
 int bnx2x_vfop_close_cmd(struct bnx2x *bp,
@@ -3202,13 +3222,16 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
                bnx2x_iov_static_resc(bp, vf);
        }
 
-       /* prepare msix vectors in VF configuration space */
+       /* prepare msix vectors in VF configuration space - the value in the
+        * PCI configuration space should be the index of the last entry,
+        * namely one less than the actual size of the table
+        */
        for (vf_idx = first_vf; vf_idx < first_vf + req_vfs; vf_idx++) {
                bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf_idx));
                REG_WR(bp, PCICFG_OFFSET + GRC_CONFIG_REG_VF_MSIX_CONTROL,
-                      num_vf_queues);
+                      num_vf_queues - 1);
                DP(BNX2X_MSG_IOV, "set msix vec num in VF %d cfg space to %d\n",
-                  vf_idx, num_vf_queues);
+                  vf_idx, num_vf_queues - 1);
        }
        bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 
@@ -3436,10 +3459,18 @@ out:
 
 int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 {
+       struct bnx2x_queue_state_params q_params = {NULL};
+       struct bnx2x_vlan_mac_ramrod_params ramrod_param;
+       struct bnx2x_queue_update_params *update_params;
+       struct pf_vf_bulletin_content *bulletin = NULL;
+       struct bnx2x_rx_mode_ramrod_params rx_ramrod;
        struct bnx2x *bp = netdev_priv(dev);
-       int rc, q_logical_state;
+       struct bnx2x_vlan_mac_obj *vlan_obj;
+       unsigned long vlan_mac_flags = 0;
+       unsigned long ramrod_flags = 0;
        struct bnx2x_virtf *vf = NULL;
-       struct pf_vf_bulletin_content *bulletin = NULL;
+       unsigned long accept_flags;
+       int rc;
 
        /* sanity and init */
        rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
@@ -3457,104 +3488,118 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
        /* update PF's copy of the VF's bulletin. No point in posting the vlan
         * to the VF since it doesn't have anything to do with it. But it useful
         * to store it here in case the VF is not up yet and we can only
-        * configure the vlan later when it does.
+        * configure the vlan later when it does. Treat vlan id 0 as remove the
+        * Host tag.
         */
-       bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       if (vlan > 0)
+               bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       else
+               bulletin->valid_bitmap &= ~(1 << VLAN_VALID);
        bulletin->vlan = vlan;
 
        /* is vf initialized and queue set up? */
-       q_logical_state =
-               bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj));
-       if (vf->state == VF_ENABLED &&
-           q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
-               /* configure the vlan in device on this vf's queue */
-               unsigned long ramrod_flags = 0;
-               unsigned long vlan_mac_flags = 0;
-               struct bnx2x_vlan_mac_obj *vlan_obj =
-                       &bnx2x_leading_vfq(vf, vlan_obj);
-               struct bnx2x_vlan_mac_ramrod_params ramrod_param;
-               struct bnx2x_queue_state_params q_params = {NULL};
-               struct bnx2x_queue_update_params *update_params;
+       if (vf->state != VF_ENABLED ||
+           bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj)) !=
+           BNX2X_Q_LOGICAL_STATE_ACTIVE)
+               return rc;
 
-               rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
-               if (rc)
-                       return rc;
-               memset(&ramrod_param, 0, sizeof(ramrod_param));
+       /* configure the vlan in device on this vf's queue */
+       vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
+       rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
+       if (rc)
+               return rc;
 
-               /* must lock vfpf channel to protect against vf flows */
-               bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+       /* must lock vfpf channel to protect against vf flows */
+       bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
 
-               /* remove existing vlans */
-               __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-               rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
-                                         &ramrod_flags);
-               if (rc) {
-                       BNX2X_ERR("failed to delete vlans\n");
-                       rc = -EINVAL;
-                       goto out;
-               }
+       /* remove existing vlans */
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
+                                 &ramrod_flags);
+       if (rc) {
+               BNX2X_ERR("failed to delete vlans\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       /* need to remove/add the VF's accept_any_vlan bit */
+       accept_flags = bnx2x_leading_vfq(vf, accept_flags);
+       if (vlan)
+               clear_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+       else
+               set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+
+       bnx2x_vf_prep_rx_mode(bp, LEADING_IDX, &rx_ramrod, vf,
+                             accept_flags);
+       bnx2x_leading_vfq(vf, accept_flags) = accept_flags;
+       bnx2x_config_rx_mode(bp, &rx_ramrod);
+
+       /* configure the new vlan to device */
+       memset(&ramrod_param, 0, sizeof(ramrod_param));
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       ramrod_param.vlan_mac_obj = vlan_obj;
+       ramrod_param.ramrod_flags = ramrod_flags;
+       set_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+               &ramrod_param.user_req.vlan_mac_flags);
+       ramrod_param.user_req.u.vlan.vlan = vlan;
+       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+       if (rc) {
+               BNX2X_ERR("failed to configure vlan\n");
+               rc =  -EINVAL;
+               goto out;
+       }
 
-               /* send queue update ramrod to configure default vlan and silent
-                * vlan removal
+       /* send queue update ramrod to configure default vlan and silent
+        * vlan removal
+        */
+       __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+       q_params.cmd = BNX2X_Q_CMD_UPDATE;
+       q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
+       update_params = &q_params.params.update;
+       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+                 &update_params->update_flags);
+       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+                 &update_params->update_flags);
+       if (vlan == 0) {
+               /* if vlan is 0 then we want to leave the VF traffic
+                * untagged, and leave the incoming traffic untouched
+                * (i.e. do not remove any vlan tags).
                 */
-               __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
-               q_params.cmd = BNX2X_Q_CMD_UPDATE;
-               q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
-               update_params = &q_params.params.update;
-               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+               __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+                           &update_params->update_flags);
+               __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+                           &update_params->update_flags);
+       } else {
+               /* configure default vlan to vf queue and set silent
+                * vlan removal (the vf remains unaware of this vlan).
+                */
+               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
                          &update_params->update_flags);
-               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
                          &update_params->update_flags);
+               update_params->def_vlan = vlan;
+               update_params->silent_removal_value =
+                       vlan & VLAN_VID_MASK;
+               update_params->silent_removal_mask = VLAN_VID_MASK;
+       }
 
-               if (vlan == 0) {
-                       /* if vlan is 0 then we want to leave the VF traffic
-                        * untagged, and leave the incoming traffic untouched
-                        * (i.e. do not remove any vlan tags).
-                        */
-                       __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                   &update_params->update_flags);
-                       __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                   &update_params->update_flags);
-               } else {
-                       /* configure the new vlan to device */
-                       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-                       ramrod_param.vlan_mac_obj = vlan_obj;
-                       ramrod_param.ramrod_flags = ramrod_flags;
-                       ramrod_param.user_req.u.vlan.vlan = vlan;
-                       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
-                       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
-                       if (rc) {
-                               BNX2X_ERR("failed to configure vlan\n");
-                               rc =  -EINVAL;
-                               goto out;
-                       }
-
-                       /* configure default vlan to vf queue and set silent
-                        * vlan removal (the vf remains unaware of this vlan).
-                        */
-                       update_params = &q_params.params.update;
-                       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                 &update_params->update_flags);
-                       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                 &update_params->update_flags);
-                       update_params->def_vlan = vlan;
-               }
+       /* Update the Queue state */
+       rc = bnx2x_queue_state_change(bp, &q_params);
+       if (rc) {
+               BNX2X_ERR("Failed to configure default VLAN\n");
+               goto out;
+       }
 
-               /* Update the Queue state */
-               rc = bnx2x_queue_state_change(bp, &q_params);
-               if (rc) {
-                       BNX2X_ERR("Failed to configure default VLAN\n");
-                       goto out;
-               }
 
-               /* clear the flag indicating that this VF needs its vlan
-                * (will only be set if the HV configured the Vlan before vf was
-                * up and we were called because the VF came up later
-                */
+       /* clear the flag indicating that this VF needs its vlan
+        * (will only be set if the HV configured the Vlan before vf was
+        * up and we were called because the VF came up later
+        */
 out:
-               vf->cfg_flags &= ~VF_CFG_VLAN;
-               bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
-       }
+       vf->cfg_flags &= ~VF_CFG_VLAN;
+       bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+
        return rc;
 }
 
@@ -3605,7 +3650,7 @@ enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
 
        /* the mac address in bulletin board is valid and is new */
        if (bulletin.valid_bitmap & 1 << MAC_ADDR_VALID &&
-           memcmp(bulletin.mac, bp->old_bulletin.mac, ETH_ALEN)) {
+           !ether_addr_equal(bulletin.mac, bp->old_bulletin.mac)) {
                /* update new mac to net device */
                memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN);
        }
index 1ff6a9366629ed88fe79a079391c92e95d1e9baf..d9fcca1b5a9db2365773c48c4d9a3ad28462d797 100644 (file)
@@ -74,6 +74,7 @@ struct bnx2x_vf_queue {
        /* VLANs object */
        struct bnx2x_vlan_mac_obj       vlan_obj;
        atomic_t vlan_count;            /* 0 means vlan-0 is set  ~ untagged */
+       unsigned long accept_flags;     /* last accept flags configured */
 
        /* Queue Slow-path State object */
        struct bnx2x_queue_sp_obj       sp_obj;
@@ -268,6 +269,7 @@ struct bnx2x_virtf {
        int leading_rss;
 
        /* MCAST object */
+       int mcast_list_len;
        struct bnx2x_mcast_obj          mcast_obj;
 
        /* RSS configuration object */
@@ -663,11 +665,6 @@ int bnx2x_vfop_mac_list_cmd(struct bnx2x *bp,
                            struct bnx2x_vfop_filters *macs,
                            int qid, bool drv_only);
 
-int bnx2x_vfop_vlan_set_cmd(struct bnx2x *bp,
-                           struct bnx2x_virtf *vf,
-                           struct bnx2x_vfop_cmd *cmd,
-                           int qid, u16 vid, bool add);
-
 int bnx2x_vfop_vlan_list_cmd(struct bnx2x *bp,
                             struct bnx2x_virtf *vf,
                             struct bnx2x_vfop_cmd *cmd,
@@ -725,13 +722,6 @@ void bnx2x_vf_enable_access(struct bnx2x *bp, u8 abs_vfid);
 /* Handles an FLR (or VF_DISABLE) notification form the MCP */
 void bnx2x_vf_handle_flr_event(struct bnx2x *bp);
 
-void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
-                  u16 length);
-void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
-                    u16 type, u16 length);
-void bnx2x_vfpf_finalize(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv);
-void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list);
-
 bool bnx2x_tlv_supported(u16 tlvtype);
 
 u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
@@ -748,7 +738,6 @@ int bnx2x_vfpf_init(struct bnx2x *bp);
 void bnx2x_vfpf_close_vf(struct bnx2x *bp);
 int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                       bool is_leading);
-int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx);
 int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set);
 int bnx2x_vfpf_config_rss(struct bnx2x *bp,
                          struct bnx2x_config_rss_params *params);
@@ -812,7 +801,6 @@ static inline int bnx2x_vfpf_release(struct bnx2x *bp) {return 0; }
 static inline int bnx2x_vfpf_init(struct bnx2x *bp) {return 0; }
 static inline void bnx2x_vfpf_close_vf(struct bnx2x *bp) {}
 static inline int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp, bool is_leading) {return 0; }
-static inline int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx) {return 0; }
 static inline int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr,
                                        u8 vf_qid, bool set) {return 0; }
 static inline int bnx2x_vfpf_config_rss(struct bnx2x *bp,
index efa8a151d78907d4b17d5f5dd07eaed9b1f2c02c..3fa6c2a2a5a9f46ba82c19103c114649af4da238 100644 (file)
 #include "bnx2x_cmn.h"
 #include <linux/crc32.h>
 
+static int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx);
+
 /* place a given tlv on the tlv buffer at a given offset */
-void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
-                  u16 length)
+static void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list,
+                         u16 offset, u16 type, u16 length)
 {
        struct channel_tlv *tl =
                (struct channel_tlv *)(tlvs_list + offset);
@@ -33,8 +35,8 @@ void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
 }
 
 /* Clear the mailbox and init the header of the first tlv */
-void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
-                    u16 type, u16 length)
+static void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
+                           u16 type, u16 length)
 {
        mutex_lock(&bp->vf2pf_mutex);
 
@@ -52,7 +54,8 @@ void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
 }
 
 /* releases the mailbox */
-void bnx2x_vfpf_finalize(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv)
+static void bnx2x_vfpf_finalize(struct bnx2x *bp,
+                               struct vfpf_first_tlv *first_tlv)
 {
        DP(BNX2X_MSG_IOV, "done sending [%d] tlv over vf pf channel\n",
           first_tlv->tl.type);
@@ -85,7 +88,7 @@ static void *bnx2x_search_tlv_list(struct bnx2x *bp, void *tlvs_list,
 }
 
 /* list the types and lengths of the tlvs on the buffer */
-void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list)
+static void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list)
 {
        int i = 1;
        struct channel_tlv *tlv = (struct channel_tlv *)tlvs_list;
@@ -208,7 +211,7 @@ static int bnx2x_get_vf_id(struct bnx2x *bp, u32 *vf_id)
                return -EINVAL;
        }
 
-       BNX2X_ERR("valid ME register value: 0x%08x\n", me_reg);
+       DP(BNX2X_MSG_IOV, "valid ME register value: 0x%08x\n", me_reg);
 
        *vf_id = (me_reg & ME_REG_VF_NUM_MASK) >> ME_REG_VF_NUM_SHIFT;
 
@@ -633,7 +636,7 @@ int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        return rc;
 }
 
-int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx)
+static int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx)
 {
        struct vfpf_q_op_tlv *req = &bp->vf2pf_mbox->req.q_op;
        struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
@@ -800,14 +803,18 @@ int bnx2x_vfpf_config_rss(struct bnx2x *bp,
        }
 
        if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
-               BNX2X_ERR("failed to send rss message to PF over Vf PF channel %d\n",
-                         resp->hdr.status);
-               rc = -EINVAL;
+               /* Since older drivers don't support this feature (and VF has
+                * no way of knowing other than failing this), don't propagate
+                * an error in this case.
+                */
+               DP(BNX2X_MSG_IOV,
+                  "Failed to send rss message to PF over VF-PF channel [%d]\n",
+                  resp->hdr.status);
        }
 out:
        bnx2x_vfpf_finalize(bp, &req->first_tlv);
 
-       return 0;
+       return rc;
 }
 
 int bnx2x_vfpf_set_mcast(struct net_device *dev)
@@ -1416,6 +1423,14 @@ static void bnx2x_vf_mbx_setup_q(struct bnx2x *bp, struct bnx2x_virtf *vf,
                                setup_q->rxq.cache_line_log;
                        rxq_params->sb_cq_index = setup_q->rxq.sb_index;
 
+                       /* rx setup - multicast engine */
+                       if (bnx2x_vfq_is_leading(q)) {
+                               u8 mcast_id = FW_VF_HANDLE(vf->abs_vfid);
+
+                               rxq_params->mcast_engine_id = mcast_id;
+                               __set_bit(BNX2X_Q_FLG_MCAST, &setup_p->flags);
+                       }
+
                        bnx2x_vfop_qctor_dump_rx(bp, vf, init_p, setup_p,
                                                 q->index, q->sb_idx);
                }
@@ -1598,6 +1613,8 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
 
                if (msg->flags & VFPF_SET_Q_FILTERS_RX_MASK_CHANGED) {
                        unsigned long accept = 0;
+                       struct pf_vf_bulletin_content *bulletin =
+                               BP_VF_BULLETIN(bp, vf->index);
 
                        /* covert VF-PF if mask to bnx2x accept flags */
                        if (msg->rx_mask & VFPF_RX_MASK_ACCEPT_MATCHED_UNICAST)
@@ -1617,9 +1634,11 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
                                __set_bit(BNX2X_ACCEPT_BROADCAST, &accept);
 
                        /* A packet arriving the vf's mac should be accepted
-                        * with any vlan
+                        * with any vlan, unless a vlan has already been
+                        * configured.
                         */
-                       __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
+                       if (!(bulletin->valid_bitmap & (1 << VLAN_VALID)))
+                               __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
 
                        /* set rx-mode */
                        rc = bnx2x_vfop_rxmode_cmd(bp, vf, &cmd,
@@ -1702,7 +1721,7 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
 
                /* ...and only the mac set by the ndo */
                if (filters->n_mac_vlan_filters == 1 &&
-                   memcmp(filters->filters->mac, bulletin->mac, ETH_ALEN)) {
+                   !ether_addr_equal(filters->filters->mac, bulletin->mac)) {
                        BNX2X_ERR("VF[%d] requested the addition of a mac address not matching the one configured by set_vf_mac ndo\n",
                                  vf->abs_vfid);
 
@@ -1710,6 +1729,21 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
                        goto response;
                }
        }
+       /* if vlan was set by hypervisor we don't allow guest to config vlan */
+       if (bulletin->valid_bitmap & 1 << VLAN_VALID) {
+               int i;
+
+               /* search for vlan filters */
+               for (i = 0; i < filters->n_mac_vlan_filters; i++) {
+                       if (filters->filters[i].flags &
+                           VFPF_Q_FILTER_VLAN_TAG_VALID) {
+                               BNX2X_ERR("VF[%d] attempted to configure vlan but one was already set by Hypervisor. Aborting request\n",
+                                         vf->abs_vfid);
+                               vf->op_rc = -EPERM;
+                               goto response;
+                       }
+               }
+       }
 
        /* verify vf_qid */
        if (filters->vf_qid > vf_rxq_count(vf))
@@ -1805,6 +1839,9 @@ static void bnx2x_vf_mbx_update_rss(struct bnx2x *bp, struct bnx2x_virtf *vf,
        vf_op_params->rss_result_mask = rss_tlv->rss_result_mask;
 
        /* flags handled individually for backward/forward compatability */
+       vf_op_params->rss_flags = 0;
+       vf_op_params->ramrod_flags = 0;
+
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_DISABLED)
                __set_bit(BNX2X_RSS_MODE_DISABLED, &vf_op_params->rss_flags);
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_REGULAR)
index f58a8b80302d9b2088ce139688b76e3a9181bb42..fcf9105a5476123c0e5d4e7a4095f05d6c95774e 100644 (file)
@@ -5220,6 +5220,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
                cnic_ring_ctl(dev, cid, cli, 1);
                *cid_ptr = cid >> 4;
                *(cid_ptr + 1) = cid * bp->db_size;
+               *(cid_ptr + 2) = UIO_USE_TX_DOORBELL;
        }
 }
 
index 0121a5d551922266935a2a1a68e92d3ed3a7dc93..0d6b13f854d959ab0cdaf101192dfe2c4930c372 100644 (file)
@@ -186,6 +186,8 @@ struct kcq_info {
        u16             (*hw_idx)(u16);
 };
 
+#define UIO_USE_TX_DOORBELL 0x017855DB
+
 struct cnic_uio_dev {
        struct uio_info         cnic_uinfo;
        u32                     uio_dev;
index ebbfe25acaa6e0fc927938bd54150435a1feedb5..8cf6b1926069d2c541b8b6888eced6463b887aa4 100644 (file)
@@ -14,8 +14,8 @@
 
 #include "bnx2x/bnx2x_mfw_req.h"
 
-#define CNIC_MODULE_VERSION    "2.5.18"
-#define CNIC_MODULE_RELDATE    "Sept 01, 2013"
+#define CNIC_MODULE_VERSION    "2.5.19"
+#define CNIC_MODULE_RELDATE    "December 19, 2013"
 
 #define CNIC_ULP_RDMA          0
 #define CNIC_ULP_ISCSI         1
index a8def93f6b6b7a1cf5b02bfa988a6c701a7797d9..c37e9f27ff6da2234ed3557a95a13b96e6a39250 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/brcmphy.h>
+#include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
@@ -94,10 +95,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define DRV_MODULE_NAME                "tg3"
 #define TG3_MAJ_NUM                    3
-#define TG3_MIN_NUM                    135
+#define TG3_MIN_NUM                    136
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "Nov 14, 2013"
+#define DRV_MODULE_RELDATE     "Jan 03, 2014"
 
 #define RESET_KIND_SHUTDOWN    0
 #define RESET_KIND_INIT                1
@@ -208,6 +209,9 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define TG3_RAW_IP_ALIGN 2
 
+#define TG3_MAX_UCAST_ADDR(tp) (tg3_flag((tp), ENABLE_ASF) ? 2 : 3)
+#define TG3_UCAST_ADDR_IDX(tp) (tg3_flag((tp), ENABLE_ASF) ? 2 : 1)
+
 #define TG3_FW_UPDATE_TIMEOUT_SEC      5
 #define TG3_FW_UPDATE_FREQ_SEC         (TG3_FW_UPDATE_TIMEOUT_SEC / 2)
 
@@ -3948,32 +3952,41 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
        return 0;
 }
 
+/* tp->lock is held. */
+static void __tg3_set_one_mac_addr(struct tg3 *tp, u8 *mac_addr, int index)
+{
+       u32 addr_high, addr_low;
+
+       addr_high = ((mac_addr[0] << 8) | mac_addr[1]);
+       addr_low = ((mac_addr[2] << 24) | (mac_addr[3] << 16) |
+                   (mac_addr[4] <<  8) | mac_addr[5]);
+
+       if (index < 4) {
+               tw32(MAC_ADDR_0_HIGH + (index * 8), addr_high);
+               tw32(MAC_ADDR_0_LOW + (index * 8), addr_low);
+       } else {
+               index -= 4;
+               tw32(MAC_EXTADDR_0_HIGH + (index * 8), addr_high);
+               tw32(MAC_EXTADDR_0_LOW + (index * 8), addr_low);
+       }
+}
 
 /* tp->lock is held. */
 static void __tg3_set_mac_addr(struct tg3 *tp, bool skip_mac_1)
 {
-       u32 addr_high, addr_low;
+       u32 addr_high;
        int i;
 
-       addr_high = ((tp->dev->dev_addr[0] << 8) |
-                    tp->dev->dev_addr[1]);
-       addr_low = ((tp->dev->dev_addr[2] << 24) |
-                   (tp->dev->dev_addr[3] << 16) |
-                   (tp->dev->dev_addr[4] <<  8) |
-                   (tp->dev->dev_addr[5] <<  0));
        for (i = 0; i < 4; i++) {
                if (i == 1 && skip_mac_1)
                        continue;
-               tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
-               tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
+               __tg3_set_one_mac_addr(tp, tp->dev->dev_addr, i);
        }
 
        if (tg3_asic_rev(tp) == ASIC_REV_5703 ||
            tg3_asic_rev(tp) == ASIC_REV_5704) {
-               for (i = 0; i < 12; i++) {
-                       tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
-                       tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
-               }
+               for (i = 4; i < 16; i++)
+                       __tg3_set_one_mac_addr(tp, tp->dev->dev_addr, i);
        }
 
        addr_high = (tp->dev->dev_addr[0] +
@@ -7625,7 +7638,7 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
 {
        u32 base = (u32) mapping & 0xffffffff;
 
-       return (base > 0xffffdcc0) && (base + len + 8 < base);
+       return base + len + 8 < base;
 }
 
 /* Test for TSO DMA buffers that cross into regions which are within MSS bytes
@@ -8928,6 +8941,49 @@ static void tg3_restore_pci_state(struct tg3 *tp)
        }
 }
 
+static void tg3_override_clk(struct tg3 *tp)
+{
+       u32 val;
+
+       switch (tg3_asic_rev(tp)) {
+       case ASIC_REV_5717:
+               val = tr32(TG3_CPMU_CLCK_ORIDE_ENABLE);
+               tw32(TG3_CPMU_CLCK_ORIDE_ENABLE, val |
+                    TG3_CPMU_MAC_ORIDE_ENABLE);
+               break;
+
+       case ASIC_REV_5719:
+       case ASIC_REV_5720:
+               tw32(TG3_CPMU_CLCK_ORIDE, CPMU_CLCK_ORIDE_MAC_ORIDE_EN);
+               break;
+
+       default:
+               return;
+       }
+}
+
+static void tg3_restore_clk(struct tg3 *tp)
+{
+       u32 val;
+
+       switch (tg3_asic_rev(tp)) {
+       case ASIC_REV_5717:
+               val = tr32(TG3_CPMU_CLCK_ORIDE_ENABLE);
+               tw32(TG3_CPMU_CLCK_ORIDE_ENABLE,
+                    val & ~TG3_CPMU_MAC_ORIDE_ENABLE);
+               break;
+
+       case ASIC_REV_5719:
+       case ASIC_REV_5720:
+               val = tr32(TG3_CPMU_CLCK_ORIDE);
+               tw32(TG3_CPMU_CLCK_ORIDE, val & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN);
+               break;
+
+       default:
+               return;
+       }
+}
+
 /* tp->lock is held. */
 static int tg3_chip_reset(struct tg3 *tp)
 {
@@ -9016,6 +9072,13 @@ static int tg3_chip_reset(struct tg3 *tp)
                     tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU);
        }
 
+       /* Set the clock to the highest frequency to avoid timeouts. With link
+        * aware mode, the clock speed could be slow and bootcode does not
+        * complete within the expected time. Override the clock to allow the
+        * bootcode to finish sooner and then restore it.
+        */
+       tg3_override_clk(tp);
+
        /* Manage gphy power for all CPMU absent PCIe devices. */
        if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, CPMU_PRESENT))
                val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
@@ -9154,10 +9217,7 @@ static int tg3_chip_reset(struct tg3 *tp)
                tw32(0x7c00, val | (1 << 25));
        }
 
-       if (tg3_asic_rev(tp) == ASIC_REV_5720) {
-               val = tr32(TG3_CPMU_CLCK_ORIDE);
-               tw32(TG3_CPMU_CLCK_ORIDE, val & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN);
-       }
+       tg3_restore_clk(tp);
 
        /* Reprobe ASF enable state.  */
        tg3_flag_clear(tp, ENABLE_ASF);
@@ -9189,6 +9249,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 
 static void tg3_get_nstats(struct tg3 *, struct rtnl_link_stats64 *);
 static void tg3_get_estats(struct tg3 *, struct tg3_ethtool_stats *);
+static void __tg3_set_rx_mode(struct net_device *);
 
 /* tp->lock is held. */
 static int tg3_halt(struct tg3 *tp, int kind, bool silent)
@@ -9249,6 +9310,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
        }
        spin_lock_bh(&tp->lock);
        __tg3_set_mac_addr(tp, skip_mac_1);
+       __tg3_set_rx_mode(dev);
        spin_unlock_bh(&tp->lock);
 
        return err;
@@ -9637,6 +9699,20 @@ static void __tg3_set_rx_mode(struct net_device *dev)
                tw32(MAC_HASH_REG_3, mc_filter[3]);
        }
 
+       if (netdev_uc_count(dev) > TG3_MAX_UCAST_ADDR(tp)) {
+               rx_mode |= RX_MODE_PROMISC;
+       } else if (!(dev->flags & IFF_PROMISC)) {
+               /* Add all entries into to the mac addr filter list */
+               int i = 0;
+               struct netdev_hw_addr *ha;
+
+               netdev_for_each_uc_addr(ha, dev) {
+                       __tg3_set_one_mac_addr(tp, ha->addr,
+                                              i + TG3_UCAST_ADDR_IDX(tp));
+                       i++;
+               }
+       }
+
        if (rx_mode != tp->rx_mode) {
                tp->rx_mode = rx_mode;
                tw32_f(MAC_RX_MODE, rx_mode);
@@ -10884,6 +10960,13 @@ static void tg3_timer(unsigned long __opaque)
                } else if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
                           tg3_flag(tp, 5780_CLASS)) {
                        tg3_serdes_parallel_detect(tp);
+               } else if (tg3_flag(tp, POLL_CPMU_LINK)) {
+                       u32 cpmu = tr32(TG3_CPMU_STATUS);
+                       bool link_up = !((cpmu & TG3_CPMU_STATUS_LINK_MASK) ==
+                                        TG3_CPMU_STATUS_LINK_MASK);
+
+                       if (link_up != tp->link_up)
+                               tg3_setup_phy(tp, false);
                }
 
                tp->timer_counter = tp->timer_multiplier;
@@ -16690,6 +16773,9 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
        else
                tg3_flag_clear(tp, POLL_SERDES);
 
+       if (tg3_flag(tp, ENABLE_APE) && tg3_flag(tp, ENABLE_ASF))
+               tg3_flag_set(tp, POLL_CPMU_LINK);
+
        tp->rx_offset = NET_SKB_PAD + NET_IP_ALIGN;
        tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD;
        if (tg3_asic_rev(tp) == ASIC_REV_5701 &&
@@ -17611,6 +17697,7 @@ static int tg3_init_one(struct pci_dev *pdev,
                features |= NETIF_F_LOOPBACK;
 
        dev->hw_features |= features;
+       dev->priv_flags |= IFF_UNICAST_FLT;
 
        if (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A1 &&
            !tg3_flag(tp, TSO_CAPABLE) &&
index e4da9d7834ce330ca895bbd2391776255f03bd4f..ef472385bce47dcea87f43e48f202ffabbddf16d 100644 (file)
 #define TG3_CPMU_CLCK_ORIDE            0x00003624
 #define  CPMU_CLCK_ORIDE_MAC_ORIDE_EN   0x80000000
 
+#define TG3_CPMU_CLCK_ORIDE_ENABLE     0x00003628
+#define  TG3_CPMU_MAC_ORIDE_ENABLE      (1 << 13)
+
 #define TG3_CPMU_STATUS                        0x0000362c
 #define  TG3_CPMU_STATUS_FMSK_5717      0x20000000
 #define  TG3_CPMU_STATUS_FMSK_5719      0xc0000000
 #define  TG3_CPMU_STATUS_FSHFT_5719     30
+#define  TG3_CPMU_STATUS_LINK_MASK      0x180000
 
 #define TG3_CPMU_CLCK_STAT             0x00003630
 #define  CPMU_CLCK_STAT_MAC_CLCK_MASK   0x001f0000
@@ -3017,6 +3021,7 @@ enum TG3_FLAGS {
        TG3_FLAG_ENABLE_ASF,
        TG3_FLAG_ASPM_WORKAROUND,
        TG3_FLAG_POLL_SERDES,
+       TG3_FLAG_POLL_CPMU_LINK,
        TG3_FLAG_MBOX_WRITE_REORDER,
        TG3_FLAG_PCIX_TARGET_HWBUG,
        TG3_FLAG_WOL_SPEED_100MB,
index d31524f9d0621d7edd9ce10d3b838cacdb88b89f..5f24a9ffcfaafeb319af6e9f1ad7864168203097 100644 (file)
@@ -3071,11 +3071,11 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 
                dma_addr = skb_frag_dma_map(&bnad->pcidev->dev, frag,
                                            0, size, DMA_TO_DEVICE);
-               unmap->vectors[vect_id].dma_len = size;
+               dma_unmap_len_set(&unmap->vectors[vect_id], dma_len, size);
                BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
                txqent->vector[vect_id].length = htons(size);
                dma_unmap_addr_set(&unmap->vectors[vect_id], dma_addr,
-                                               dma_addr);
+                                  dma_addr);
                head_unmap->nvecs++;
        }
 
index 76ae09999b5b86bd15c71da88368eb0a9dea63a7..c0a9dd55f4e55215bb0e42902c12c97b241d0d3f 100644 (file)
@@ -182,7 +182,7 @@ static struct net_device *get_iff_from_mac(struct adapter *adapter,
        for_each_port(adapter, i) {
                struct net_device *dev = adapter->port[i];
 
-               if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) {
+               if (ether_addr_equal(dev->dev_addr, mac)) {
                        rcu_read_lock();
                        if (vlan && vlan != VLAN_VID_MASK) {
                                dev = __vlan_find_dev_deep(dev, htons(ETH_P_8021Q), vlan);
index 8d53438638b20f9dffa3b96c332751aeaf111dcf..5f226eda8cd68751aa7360534f74f59604f88374 100644 (file)
@@ -429,7 +429,7 @@ found:
                } else {
                        e->state = neigh->nud_state & NUD_CONNECTED ?
                            L2T_STATE_VALID : L2T_STATE_STALE;
-                       if (memcmp(e->dmac, neigh->ha, 6))
+                       if (!ether_addr_equal(e->dmac, neigh->ha))
                                setup_l2e_send_pending(dev, NULL, e);
                }
        }
index 6c9308850453bf1ecd21173afa1d1cf11681c8c7..16782b2cff495fcc508e5d3b96530f1a3386940c 100644 (file)
 #include "cxgb4_uld.h"
 
 #define T4FW_VERSION_MAJOR 0x01
-#define T4FW_VERSION_MINOR 0x06
-#define T4FW_VERSION_MICRO 0x18
+#define T4FW_VERSION_MINOR 0x09
+#define T4FW_VERSION_MICRO 0x17
 #define T4FW_VERSION_BUILD 0x00
 
 #define T5FW_VERSION_MAJOR 0x01
-#define T5FW_VERSION_MINOR 0x08
-#define T5FW_VERSION_MICRO 0x1C
+#define T5FW_VERSION_MINOR 0x09
+#define T5FW_VERSION_MICRO 0x17
 #define T5FW_VERSION_BUILD 0x00
 
 #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
@@ -228,6 +228,25 @@ struct tp_params {
 
        uint32_t dack_re;            /* DACK timer resolution */
        unsigned short tx_modq[NCHAN];  /* channel to modulation queue map */
+
+       u32 vlan_pri_map;               /* cached TP_VLAN_PRI_MAP */
+       u32 ingress_config;             /* cached TP_INGRESS_CONFIG */
+
+       /* TP_VLAN_PRI_MAP Compressed Filter Tuple field offsets.  This is a
+        * subset of the set of fields which may be present in the Compressed
+        * Filter Tuple portion of filters and TCP TCB connections.  The
+        * fields which are present are controlled by the TP_VLAN_PRI_MAP.
+        * Since a variable number of fields may or may not be present, their
+        * shifted field positions within the Compressed Filter Tuple may
+        * vary, or not even be present if the field isn't selected in
+        * TP_VLAN_PRI_MAP.  Since some of these fields are needed in various
+        * places we store their offsets here, or a -1 if the field isn't
+        * present.
+        */
+       int vlan_shift;
+       int vnic_shift;
+       int port_shift;
+       int protocol_shift;
 };
 
 struct vpd_params {
@@ -919,13 +938,14 @@ int t4_seeprom_wp(struct adapter *adapter, bool enable);
 int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
 int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
 unsigned int t4_flash_cfg_addr(struct adapter *adapter);
-int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
 int t4_get_fw_version(struct adapter *adapter, u32 *vers);
 int t4_get_tp_version(struct adapter *adapter, u32 *vers);
 int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
               const u8 *fw_data, unsigned int fw_size,
               struct fw_hdr *card_fw, enum dev_state state, int *reset);
 int t4_prep_adapter(struct adapter *adapter);
+int t4_init_tp_params(struct adapter *adap);
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
 void t4_fatal_err(struct adapter *adapter);
 int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
@@ -958,13 +978,6 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
 int t4_fw_bye(struct adapter *adap, unsigned int mbox);
 int t4_early_init(struct adapter *adap, unsigned int mbox);
 int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset);
-int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force);
-int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset);
-int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
-                 const u8 *fw_data, unsigned int size, int force);
-int t4_fw_config_file(struct adapter *adap, unsigned int mbox,
-                     unsigned int mtype, unsigned int maddr,
-                     u32 *finiver, u32 *finicsum, u32 *cfcsum);
 int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
                          unsigned int cache_line_size);
 int t4_fw_initialize(struct adapter *adap, unsigned int mbox);
index d6b12e035a7d9f27d84d397dc2921713c7fed46f..fff02ed1295e5ef7bab408cbe19c46dbd5eedd52 100644 (file)
@@ -2986,7 +2986,14 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
                stid += t->stid_base;
-               t->stids_in_use++;
+               /* IPv6 requires max of 520 bits or 16 cells in TCAM
+                * This is equivalent to 4 TIDs. With CLIP enabled it
+                * needs 2 TIDs.
+                */
+               if (family == PF_INET)
+                       t->stids_in_use++;
+               else
+                       t->stids_in_use += 4;
        }
        spin_unlock_bh(&t->stid_lock);
        return stid;
@@ -3012,7 +3019,8 @@ int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
        }
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
-               stid += t->stid_base;
+               stid -= t->nstids;
+               stid += t->sftid_base;
                t->stids_in_use++;
        }
        spin_unlock_bh(&t->stid_lock);
@@ -3024,14 +3032,24 @@ EXPORT_SYMBOL(cxgb4_alloc_sftid);
  */
 void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        spin_lock_bh(&t->stid_lock);
        if (family == PF_INET)
                __clear_bit(stid, t->stid_bmap);
        else
                bitmap_release_region(t->stid_bmap, stid, 2);
        t->stid_tab[stid].data = NULL;
-       t->stids_in_use--;
+       if (family == PF_INET)
+               t->stids_in_use--;
+       else
+               t->stids_in_use -= 4;
        spin_unlock_bh(&t->stid_lock);
 }
 EXPORT_SYMBOL(cxgb4_free_stid);
@@ -3134,6 +3152,7 @@ static int tid_init(struct tid_info *t)
        size_t size;
        unsigned int stid_bmap_size;
        unsigned int natids = t->natids;
+       struct adapter *adap = container_of(t, struct adapter, tids);
 
        stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
        size = t->ntids * sizeof(*t->tid_tab) +
@@ -3167,6 +3186,11 @@ static int tid_init(struct tid_info *t)
                t->afree = t->atid_tab;
        }
        bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
+       /* Reserve stid 0 for T4/T5 adapters */
+       if (!t->stid_base &&
+           (is_t4(adap->params.chip) || is_t5(adap->params.chip)))
+               __set_bit(0, t->stid_bmap);
+
        return 0;
 }
 
@@ -3731,7 +3755,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
        lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
                        t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
                        (adap->fn * 4));
-       lli.filt_mode = adap->filter_mode;
+       lli.filt_mode = adap->params.tp.vlan_pri_map;
        /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
        for (i = 0; i < NCHAN; i++)
                lli.tx_modq[i] = i;
@@ -4179,7 +4203,7 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        /* Check to make sure the filter requested is writable ...
@@ -4205,12 +4229,17 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
                        f->fs.val.lip[i] = val[i];
                        f->fs.mask.lip[i] = ~0;
                }
-               if (adap->filter_mode & F_PORT) {
+               if (adap->params.tp.vlan_pri_map & F_PORT) {
                        f->fs.val.iport = port;
                        f->fs.mask.iport = mask;
                }
        }
 
+       if (adap->params.tp.vlan_pri_map & F_PROTOCOL) {
+               f->fs.val.proto = IPPROTO_TCP;
+               f->fs.mask.proto = ~0;
+       }
+
        f->fs.dirsteer = 1;
        f->fs.iq = queue;
        /* Mark filter as locked */
@@ -4237,7 +4266,7 @@ int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        f = &adap->tids.ftid_tab[stid];
@@ -5092,7 +5121,7 @@ static int adap_init0(struct adapter *adap)
        enum dev_state state;
        u32 params[7], val[7];
        struct fw_caps_config_cmd caps_cmd;
-       int reset = 1, j;
+       int reset = 1;
 
        /*
         * Contact FW, advertising Master capability (and potentially forcing
@@ -5434,21 +5463,11 @@ static int adap_init0(struct adapter *adap)
        /*
         * These are finalized by FW initialization, load their values now.
         */
-       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
-       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
-       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
        t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
        t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
                     adap->params.b_wnd);
 
-       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
-       for (j = 0; j < NCHAN; j++)
-               adap->params.tp.tx_modq[j] = j;
-
-       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
-                        &adap->filter_mode, 1,
-                        TP_VLAN_PRI_MAP);
-
+       t4_init_tp_params(adap);
        adap->flags |= FW_OK;
        return 0;
 
index 6f21f2451c3052a24ecd2e8d8d16ee9bdf9996fe..4dd0a82533e442f8b330c5ede554359ea450a087 100644 (file)
@@ -131,7 +131,14 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)
 
 static inline void *lookup_stid(const struct tid_info *t, unsigned int stid)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL;
 }
 
index 29878098101eb07771626399a1c5050a9544d055..cb05be905defdceb0e2d0b76386dcd224169b5b0 100644 (file)
@@ -45,6 +45,7 @@
 #include "l2t.h"
 #include "t4_msg.h"
 #include "t4fw_api.h"
+#include "t4_regs.h"
 
 #define VLAN_NONE 0xfff
 
@@ -411,6 +412,40 @@ done:
 }
 EXPORT_SYMBOL(cxgb4_l2t_get);
 
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t)
+{
+       struct adapter *adap = netdev2adap(dev);
+       struct tp_params *tp = &adap->params.tp;
+       u64 ntuple = 0;
+
+       /* Initialize each of the fields which we care about which are present
+        * in the Compressed Filter Tuple.
+        */
+       if (tp->vlan_shift >= 0 && l2t->vlan != VLAN_NONE)
+               ntuple |= (F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift;
+
+       if (tp->port_shift >= 0)
+               ntuple |= (u64)l2t->lport << tp->port_shift;
+
+       if (tp->protocol_shift >= 0)
+               ntuple |= (u64)IPPROTO_TCP << tp->protocol_shift;
+
+       if (tp->vnic_shift >= 0) {
+               u32 viid = cxgb4_port_viid(dev);
+               u32 vf = FW_VIID_VIN_GET(viid);
+               u32 pf = FW_VIID_PFN_GET(viid);
+               u32 vld = FW_VIID_VIVLD_GET(viid);
+
+               ntuple |= (u64)(V_FT_VNID_ID_VF(vf) |
+                               V_FT_VNID_ID_PF(pf) |
+                               V_FT_VNID_ID_VLD(vld)) << tp->vnic_shift;
+       }
+
+       return ntuple;
+}
+EXPORT_SYMBOL(cxgb4_select_ntuple);
+
 /*
  * Called when address resolution fails for an L2T entry to handle packets
  * on the arpq head.  If a packet specifies a failure handler it is invoked,
index 108c0f1fce1c4e5776b687538d741cd6f771a909..85eb5c71358d80ad91e21df648289047165dbf39 100644 (file)
@@ -98,7 +98,8 @@ int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb,
 struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
                                const struct net_device *physdev,
                                unsigned int priority);
-
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t);
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
 struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
 int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
index 42745438c1e016ca00e420a58373422734e91e47..47ffa64fcf19e89a495191252006cb21eb40d993 100644 (file)
@@ -2583,7 +2583,7 @@ static int t4_sge_init_soft(struct adapter *adap)
        #undef READ_FL_BUF
 
        if (fl_small_pg != PAGE_SIZE ||
-           (fl_large_pg != 0 && (fl_large_pg <= fl_small_pg ||
+           (fl_large_pg != 0 && (fl_large_pg < fl_small_pg ||
                                  (fl_large_pg & (fl_large_pg-1)) != 0))) {
                dev_err(adap->pdev_dev, "bad SGE FL page buffer sizes [%d, %d]\n",
                        fl_small_pg, fl_large_pg);
index 74a6fce5a15a6914faf74bbf903dcc76ec717775..a3964753935c06e320cc5ddd6001310e064925ba 100644 (file)
@@ -38,6 +38,8 @@
 #include "t4_regs.h"
 #include "t4fw_api.h"
 
+static int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
+                        const u8 *fw_data, unsigned int size, int force);
 /**
  *     t4_wait_op_done_val - wait until an operation is completed
  *     @adapter: the adapter performing the operation
@@ -1069,62 +1071,6 @@ unsigned int t4_flash_cfg_addr(struct adapter *adapter)
                return FLASH_CFG_START;
 }
 
-/**
- *     t4_load_cfg - download config file
- *     @adap: the adapter
- *     @cfg_data: the cfg text file to write
- *     @size: text file size
- *
- *     Write the supplied config text file to the card's serial flash.
- */
-int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
-{
-       int ret, i, n;
-       unsigned int addr;
-       unsigned int flash_cfg_start_sec;
-       unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
-
-       addr = t4_flash_cfg_addr(adap);
-       flash_cfg_start_sec = addr / SF_SEC_SIZE;
-
-       if (size > FLASH_CFG_MAX_SIZE) {
-               dev_err(adap->pdev_dev, "cfg file too large, max is %u bytes\n",
-                       FLASH_CFG_MAX_SIZE);
-               return -EFBIG;
-       }
-
-       i = DIV_ROUND_UP(FLASH_CFG_MAX_SIZE,    /* # of sectors spanned */
-                        sf_sec_size);
-       ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec,
-                                    flash_cfg_start_sec + i - 1);
-       /*
-        * If size == 0 then we're simply erasing the FLASH sectors associated
-        * with the on-adapter Firmware Configuration File.
-        */
-       if (ret || size == 0)
-               goto out;
-
-       /* this will write to the flash up to SF_PAGE_SIZE at a time */
-       for (i = 0; i < size; i += SF_PAGE_SIZE) {
-               if ((size - i) <  SF_PAGE_SIZE)
-                       n = size - i;
-               else
-                       n = SF_PAGE_SIZE;
-               ret = t4_write_flash(adap, addr, n, cfg_data);
-               if (ret)
-                       goto out;
-
-               addr += SF_PAGE_SIZE;
-               cfg_data += SF_PAGE_SIZE;
-       }
-
-out:
-       if (ret)
-               dev_err(adap->pdev_dev, "config file %s failed %d\n",
-                       (size == 0 ? "clear" : "download"), ret);
-       return ret;
-}
-
 /**
  *     t4_load_fw - download firmware
  *     @adap: the adapter
@@ -2810,7 +2756,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)
  *     be doing.  The only way out of this state is to RESTART the firmware
  *     ...
  */
-int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
+static int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
 {
        int ret = 0;
 
@@ -2875,7 +2821,7 @@ int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
  *         the chip since older firmware won't recognize the PCIE_FW.HALT
  *         flag and automatically RESET itself on startup.
  */
-int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset)
+static int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset)
 {
        if (reset) {
                /*
@@ -2938,8 +2884,8 @@ int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset)
  *     positive errno indicates that the adapter is ~probably~ intact, a
  *     negative errno indicates that things are looking bad ...
  */
-int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
-                 const u8 *fw_data, unsigned int size, int force)
+static int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
+                        const u8 *fw_data, unsigned int size, int force)
 {
        const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data;
        int reset, ret;
@@ -2964,78 +2910,6 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
        return t4_fw_restart(adap, mbox, reset);
 }
 
-
-/**
- *     t4_fw_config_file - setup an adapter via a Configuration File
- *     @adap: the adapter
- *     @mbox: mailbox to use for the FW command
- *     @mtype: the memory type where the Configuration File is located
- *     @maddr: the memory address where the Configuration File is located
- *     @finiver: return value for CF [fini] version
- *     @finicsum: return value for CF [fini] checksum
- *     @cfcsum: return value for CF computed checksum
- *
- *     Issue a command to get the firmware to process the Configuration
- *     File located at the specified mtype/maddress.  If the Configuration
- *     File is processed successfully and return value pointers are
- *     provided, the Configuration File "[fini] section version and
- *     checksum values will be returned along with the computed checksum.
- *     It's up to the caller to decide how it wants to respond to the
- *     checksums not matching but it recommended that a prominant warning
- *     be emitted in order to help people rapidly identify changed or
- *     corrupted Configuration Files.
- *
- *     Also note that it's possible to modify things like "niccaps",
- *     "toecaps",etc. between processing the Configuration File and telling
- *     the firmware to use the new configuration.  Callers which want to
- *     do this will need to "hand-roll" their own CAPS_CONFIGS commands for
- *     Configuration Files if they want to do this.
- */
-int t4_fw_config_file(struct adapter *adap, unsigned int mbox,
-                     unsigned int mtype, unsigned int maddr,
-                     u32 *finiver, u32 *finicsum, u32 *cfcsum)
-{
-       struct fw_caps_config_cmd caps_cmd;
-       int ret;
-
-       /*
-        * Tell the firmware to process the indicated Configuration File.
-        * If there are no errors and the caller has provided return value
-        * pointers for the [fini] section version, checksum and computed
-        * checksum, pass those back to the caller.
-        */
-       memset(&caps_cmd, 0, sizeof(caps_cmd));
-       caps_cmd.op_to_write =
-               htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
-                     FW_CMD_REQUEST |
-                     FW_CMD_READ);
-       caps_cmd.cfvalid_to_len16 =
-               htonl(FW_CAPS_CONFIG_CMD_CFVALID |
-                     FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) |
-                     FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) |
-                     FW_LEN16(caps_cmd));
-       ret = t4_wr_mbox(adap, mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd);
-       if (ret < 0)
-               return ret;
-
-       if (finiver)
-               *finiver = ntohl(caps_cmd.finiver);
-       if (finicsum)
-               *finicsum = ntohl(caps_cmd.finicsum);
-       if (cfcsum)
-               *cfcsum = ntohl(caps_cmd.cfcsum);
-
-       /*
-        * And now tell the firmware to use the configuration we just loaded.
-        */
-       caps_cmd.op_to_write =
-               htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
-                     FW_CMD_REQUEST |
-                     FW_CMD_WRITE);
-       caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
-       return t4_wr_mbox(adap, mbox, &caps_cmd, sizeof(caps_cmd), NULL);
-}
-
 /**
  *     t4_fixup_host_params - fix up host-dependent parameters
  *     @adap: the adapter
@@ -3808,6 +3682,109 @@ int t4_prep_adapter(struct adapter *adapter)
        return 0;
 }
 
+/**
+ *      t4_init_tp_params - initialize adap->params.tp
+ *      @adap: the adapter
+ *
+ *      Initialize various fields of the adapter's TP Parameters structure.
+ */
+int t4_init_tp_params(struct adapter *adap)
+{
+       int chan;
+       u32 v;
+
+       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
+       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
+       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
+
+       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
+       for (chan = 0; chan < NCHAN; chan++)
+               adap->params.tp.tx_modq[chan] = chan;
+
+       /* Cache the adapter's Compressed Filter Mode and global Incress
+        * Configuration.
+        */
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.vlan_pri_map, 1,
+                        TP_VLAN_PRI_MAP);
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.ingress_config, 1,
+                        TP_INGRESS_CONFIG);
+
+       /* Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
+        * shift positions of several elements of the Compressed Filter Tuple
+        * for this adapter which we need frequently ...
+        */
+       adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);
+       adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
+       adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);
+       adap->params.tp.protocol_shift = t4_filter_field_shift(adap,
+                                                              F_PROTOCOL);
+
+       /* If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
+        * represents the presense of an Outer VLAN instead of a VNIC ID.
+        */
+       if ((adap->params.tp.ingress_config & F_VNIC) == 0)
+               adap->params.tp.vnic_shift = -1;
+
+       return 0;
+}
+
+/**
+ *      t4_filter_field_shift - calculate filter field shift
+ *      @adap: the adapter
+ *      @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
+ *
+ *      Return the shift position of a filter field within the Compressed
+ *      Filter Tuple.  The filter field is specified via its selection bit
+ *      within TP_VLAN_PRI_MAL (filter mode).  E.g. F_VLAN.
+ */
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
+{
+       unsigned int filter_mode = adap->params.tp.vlan_pri_map;
+       unsigned int sel;
+       int field_shift;
+
+       if ((filter_mode & filter_sel) == 0)
+               return -1;
+
+       for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) {
+               switch (filter_mode & sel) {
+               case F_FCOE:
+                       field_shift += W_FT_FCOE;
+                       break;
+               case F_PORT:
+                       field_shift += W_FT_PORT;
+                       break;
+               case F_VNIC_ID:
+                       field_shift += W_FT_VNIC_ID;
+                       break;
+               case F_VLAN:
+                       field_shift += W_FT_VLAN;
+                       break;
+               case F_TOS:
+                       field_shift += W_FT_TOS;
+                       break;
+               case F_PROTOCOL:
+                       field_shift += W_FT_PROTOCOL;
+                       break;
+               case F_ETHERTYPE:
+                       field_shift += W_FT_ETHERTYPE;
+                       break;
+               case F_MACMATCH:
+                       field_shift += W_FT_MACMATCH;
+                       break;
+               case F_MPSHITTYPE:
+                       field_shift += W_FT_MPSHITTYPE;
+                       break;
+               case F_FRAGMENTATION:
+                       field_shift += W_FT_FRAGMENTATION;
+                       break;
+               }
+       }
+       return field_shift;
+}
+
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
        u8 addr[6];
index 0a8205d69d2c290aae4dbec30245c9dc3e18bd39..4082522d81408bf0a23cff8eaf9700bef14533a9 100644 (file)
 
 #define A_TP_TX_SCHED_PCMD 0x25
 
+#define S_VNIC    11
+#define V_VNIC(x) ((x) << S_VNIC)
+#define F_VNIC    V_VNIC(1U)
+
+#define S_FRAGMENTATION    9
+#define V_FRAGMENTATION(x) ((x) << S_FRAGMENTATION)
+#define F_FRAGMENTATION    V_FRAGMENTATION(1U)
+
+#define S_MPSHITTYPE    8
+#define V_MPSHITTYPE(x) ((x) << S_MPSHITTYPE)
+#define F_MPSHITTYPE    V_MPSHITTYPE(1U)
+
+#define S_MACMATCH    7
+#define V_MACMATCH(x) ((x) << S_MACMATCH)
+#define F_MACMATCH    V_MACMATCH(1U)
+
+#define S_ETHERTYPE    6
+#define V_ETHERTYPE(x) ((x) << S_ETHERTYPE)
+#define F_ETHERTYPE    V_ETHERTYPE(1U)
+
+#define S_PROTOCOL    5
+#define V_PROTOCOL(x) ((x) << S_PROTOCOL)
+#define F_PROTOCOL    V_PROTOCOL(1U)
+
+#define S_TOS    4
+#define V_TOS(x) ((x) << S_TOS)
+#define F_TOS    V_TOS(1U)
+
+#define S_VLAN    3
+#define V_VLAN(x) ((x) << S_VLAN)
+#define F_VLAN    V_VLAN(1U)
+
+#define S_VNIC_ID    2
+#define V_VNIC_ID(x) ((x) << S_VNIC_ID)
+#define F_VNIC_ID    V_VNIC_ID(1U)
+
 #define S_PORT    1
 #define V_PORT(x) ((x) << S_PORT)
 #define F_PORT    V_PORT(1U)
 
+#define S_FCOE    0
+#define V_FCOE(x) ((x) << S_FCOE)
+#define F_FCOE    V_FCOE(1U)
+
 #define NUM_MPS_CLS_SRAM_L_INSTANCES 336
 #define NUM_MPS_T5_CLS_SRAM_L_INSTANCES 512
 
 #define V_CHIPID(x) ((x) << S_CHIPID)
 #define G_CHIPID(x) (((x) >> S_CHIPID) & M_CHIPID)
 
+/* TP_VLAN_PRI_MAP controls which subset of fields will be present in the
+ * Compressed Filter Tuple for LE filters.  Each bit set in TP_VLAN_PRI_MAP
+ * selects for a particular field being present.  These fields, when present
+ * in the Compressed Filter Tuple, have the following widths in bits.
+ */
+#define W_FT_FCOE                       1
+#define W_FT_PORT                       3
+#define W_FT_VNIC_ID                    17
+#define W_FT_VLAN                       17
+#define W_FT_TOS                        8
+#define W_FT_PROTOCOL                   8
+#define W_FT_ETHERTYPE                  16
+#define W_FT_MACMATCH                   9
+#define W_FT_MPSHITTYPE                 3
+#define W_FT_FRAGMENTATION              1
+
+/* Some of the Compressed Filter Tuple fields have internal structure.  These
+ * bit shifts/masks describe those structures.  All shifts are relative to the
+ * base position of the fields within the Compressed Filter Tuple
+ */
+#define S_FT_VLAN_VLD                   16
+#define V_FT_VLAN_VLD(x)                ((x) << S_FT_VLAN_VLD)
+#define F_FT_VLAN_VLD                   V_FT_VLAN_VLD(1U)
+
+#define S_FT_VNID_ID_VF                 0
+#define V_FT_VNID_ID_VF(x)              ((x) << S_FT_VNID_ID_VF)
+
+#define S_FT_VNID_ID_PF                 7
+#define V_FT_VNID_ID_PF(x)              ((x) << S_FT_VNID_ID_PF)
+
+#define S_FT_VNID_ID_VLD                16
+#define V_FT_VNID_ID_VLD(x)             ((x) << S_FT_VNID_ID_VLD)
+
 #endif /* __T4_REGS_H */
index 61362450d05b4f83daeacf9a0c54ebed35e2da4c..f412d0fa0850c720849301b46584a208bfd79b26 100644 (file)
@@ -268,7 +268,6 @@ int t4vf_wait_dev_ready(struct adapter *);
 int t4vf_port_init(struct adapter *, int);
 
 int t4vf_fw_reset(struct adapter *);
-int t4vf_query_params(struct adapter *, unsigned int, const u32 *, u32 *);
 int t4vf_set_params(struct adapter *, unsigned int, const u32 *, const u32 *);
 
 int t4vf_get_sge_params(struct adapter *);
index d958c44341b5cb299d704600494de5be9d15bb72..25dfeb8f28ed015c6c49f12e163809daa8e1976a 100644 (file)
@@ -363,8 +363,8 @@ int t4vf_fw_reset(struct adapter *adapter)
  *     Reads the values of firmware or device parameters.  Up to 7 parameters
  *     can be queried at once.
  */
-int t4vf_query_params(struct adapter *adapter, unsigned int nparams,
-                     const u32 *params, u32 *vals)
+static int t4vf_query_params(struct adapter *adapter, unsigned int nparams,
+                            const u32 *params, u32 *vals)
 {
        int i, ret;
        struct fw_params_cmd cmd, rpl;
index 43464f0a4f99c14b08a0fb26c75ffa25ae5b0f1d..e6a83198c3dda2e8a97083de61a05e5b2e333cee 100644 (file)
@@ -162,7 +162,7 @@ static int enic_are_pp_different(struct enic_port_profile *pp1,
        return strcmp(pp1->name, pp2->name) | !!memcmp(pp1->instance_uuid,
                pp2->instance_uuid, PORT_UUID_MAX) |
                !!memcmp(pp1->host_uuid, pp2->host_uuid, PORT_UUID_MAX) |
-               !!memcmp(pp1->mac_addr, pp2->mac_addr, ETH_ALEN);
+               !ether_addr_equal(pp1->mac_addr, pp2->mac_addr);
 }
 
 static int enic_pp_preassociate(struct enic *enic, int vf,
index a5397b130724faa9bb4fb9d54881226eb03695bd..aa4ee385091faa850c0ddd9e6f89146be4c401cf 100644 (file)
@@ -1192,9 +1192,6 @@ static int uli526x_suspend(struct pci_dev *pdev, pm_message_t state)
 
        ULI526X_DBUG(0, "uli526x_suspend", 0);
 
-       if (!netdev_priv(dev))
-               return 0;
-
        pci_save_state(pdev);
 
        if (!netif_running(dev))
@@ -1228,9 +1225,6 @@ static int uli526x_resume(struct pci_dev *pdev)
 
        ULI526X_DBUG(0, "uli526x_resume", 0);
 
-       if (!netdev_priv(dev))
-               return 0;
-
        pci_restore_state(pdev);
 
        if (!netif_running(dev))
index 5878df619b531ad0b3ea96167f53e8909ff9fd21..4ccaf9af6fc90cde0d9d13490fa5753e480c543e 100644 (file)
@@ -104,6 +104,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE3_MAX_RSS_QS         16
 #define BE3_MAX_TX_QS          16
 #define BE3_MAX_EVT_QS         16
+#define BE3_SRIOV_MAX_EVT_QS   8
 
 #define MAX_RX_QS              32
 #define MAX_EVT_QS             32
@@ -480,7 +481,7 @@ struct be_adapter {
        struct list_head entry;
 
        u32 flash_status;
-       struct completion flash_compl;
+       struct completion et_cmd_compl;
 
        struct be_resources res;        /* resources available for the func */
        u16 num_vfs;                    /* Number of VFs provisioned by PF */
index e0e8bc1ef14c47e93336df2c784d1ff14e6b4143..94c35c8d799d9f1e4f4b9fd78121600ad600505e 100644 (file)
@@ -141,11 +141,17 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
                subsystem = resp_hdr->subsystem;
        }
 
+       if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
+           subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
+               complete(&adapter->et_cmd_compl);
+               return 0;
+       }
+
        if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
             (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
            (subsystem == CMD_SUBSYSTEM_COMMON)) {
                adapter->flash_status = compl_status;
-               complete(&adapter->flash_compl);
+               complete(&adapter->et_cmd_compl);
        }
 
        if (compl_status == MCC_STATUS_SUCCESS) {
@@ -2017,6 +2023,9 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
                        0x3ea83c02, 0x4a110304};
        int status;
 
+       if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
+               return 0;
+
        if (mutex_lock_interruptible(&adapter->mbox_lock))
                return -1;
 
@@ -2160,7 +2169,7 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
                                         msecs_to_jiffies(60000)))
                status = -1;
        else
@@ -2255,8 +2264,8 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
-                       msecs_to_jiffies(40000)))
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
+                                        msecs_to_jiffies(40000)))
                status = -1;
        else
                status = adapter->flash_status;
@@ -2367,6 +2376,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_loopback_test *req;
+       struct be_cmd_resp_loopback_test *resp;
        int status;
 
        spin_lock_bh(&adapter->mcc_lock);
@@ -2381,8 +2391,8 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
                        OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, NULL);
-       req->hdr.timeout = cpu_to_le32(4);
 
+       req->hdr.timeout = cpu_to_le32(15);
        req->pattern = cpu_to_le64(pattern);
        req->src_port = cpu_to_le32(port_num);
        req->dest_port = cpu_to_le32(port_num);
@@ -2390,12 +2400,15 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
        req->num_pkts = cpu_to_le32(num_pkts);
        req->loopback_type = cpu_to_le32(loopback_type);
 
-       status = be_mcc_notify_wait(adapter);
-       if (!status) {
-               struct be_cmd_resp_loopback_test *resp = embedded_payload(wrb);
-               status = le32_to_cpu(resp->status);
-       }
+       be_mcc_notify(adapter);
+
+       spin_unlock_bh(&adapter->mcc_lock);
 
+       wait_for_completion(&adapter->et_cmd_compl);
+       resp = embedded_payload(wrb);
+       status = le32_to_cpu(resp->status);
+
+       return status;
 err:
        spin_unlock_bh(&adapter->mcc_lock);
        return status;
index f67586a766d26e9c4eba9a42e61fdd1f3b73993f..3acf137b57840556ec66b08971028c76d05bd394 100644 (file)
@@ -287,7 +287,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
        /* The MAC change did not happen, either due to lack of privilege
         * or PF didn't pre-provision.
         */
-       if (memcmp(addr->sa_data, mac, ETH_ALEN)) {
+       if (!ether_addr_equal(addr->sa_data, mac)) {
                status = -EPERM;
                goto err;
        }
@@ -2744,13 +2744,16 @@ static int be_rx_qs_create(struct be_adapter *adapter)
                if (!BEx_chip(adapter))
                        adapter->rss_flags |= RSS_ENABLE_UDP_IPV4 |
                                                RSS_ENABLE_UDP_IPV6;
+       } else {
+               /* Disable RSS, if only default RX Q is created */
+               adapter->rss_flags = RSS_ENABLE_NONE;
+       }
 
-               rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
-                                      128);
-               if (rc) {
-                       adapter->rss_flags = 0;
-                       return rc;
-               }
+       rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
+                              128);
+       if (rc) {
+               adapter->rss_flags = RSS_ENABLE_NONE;
+               return rc;
        }
 
        /* First time posting */
@@ -3124,11 +3127,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
 {
        struct pci_dev *pdev = adapter->pdev;
        bool use_sriov = false;
+       int max_vfs;
 
-       if (BE3_chip(adapter) && sriov_want(adapter)) {
-               int max_vfs;
+       max_vfs = pci_sriov_get_totalvfs(pdev);
 
-               max_vfs = pci_sriov_get_totalvfs(pdev);
+       if (BE3_chip(adapter) && sriov_want(adapter)) {
                res->max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
                use_sriov = res->max_vfs;
        }
@@ -3159,7 +3162,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
                                           BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
        res->max_rx_qs = res->max_rss_qs + 1;
 
-       res->max_evt_qs = be_physfn(adapter) ? BE3_MAX_EVT_QS : 1;
+       if (be_physfn(adapter))
+               res->max_evt_qs = (max_vfs > 0) ?
+                                       BE3_SRIOV_MAX_EVT_QS : BE3_MAX_EVT_QS;
+       else
+               res->max_evt_qs = 1;
 
        res->if_cap_flags = BE_IF_CAP_FLAGS_WANT;
        if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS))
@@ -4205,7 +4212,7 @@ static int be_ctrl_init(struct be_adapter *adapter)
        spin_lock_init(&adapter->mcc_lock);
        spin_lock_init(&adapter->mcc_cq_lock);
 
-       init_completion(&adapter->flash_compl);
+       init_completion(&adapter->et_cmd_compl);
        pci_save_state(adapter->pdev);
        return 0;
 
index 05cd81aa98135e6401d5d3b230f0b7d85c538a0d..6530177d53e74e5630f637a19cdcd3a85327eef9 100644 (file)
@@ -428,6 +428,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* If this was the last BD in the ring, start at the beginning again. */
        bdp = fec_enet_get_nextdesc(bdp, fep);
 
+       skb_tx_timestamp(skb);
+
        fep->cur_tx = bdp;
 
        if (fep->cur_tx == fep->dirty_tx)
@@ -436,8 +438,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* Trigger transmission start */
        writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
index 5548b6d00c31fe6282f108aa48bdbf45fc0c5eba..72291a8904a90118f88913af0e3c453d9ce3ffff 100644 (file)
@@ -435,11 +435,6 @@ static void hw_add_addr_in_hash(struct ucc_geth_private *ugeth,
                     QE_CR_PROTOCOL_ETHERNET, 0);
 }
 
-static inline int compare_addr(u8 **addr1, u8 **addr2)
-{
-       return memcmp(addr1, addr2, ETH_ALEN);
-}
-
 #ifdef DEBUG
 static void get_statistics(struct ucc_geth_private *ugeth,
                           struct ucc_geth_tx_firmware_statistics *
index 41a2fa2fc67dff1ff1c03f9fc6e09234e4c8897e..333bb54d0bdf688d99dcee54b1091ca485efa08f 100644 (file)
@@ -243,6 +243,7 @@ config IXGBEVF
 
 config I40E
        tristate "Intel(R) Ethernet Controller XL710 Family support"
+       select PTP_1588_CLOCK
        depends on PCI
        ---help---
          This driver supports Intel(R) Ethernet Controller XL710 Family of
@@ -259,4 +260,36 @@ config I40E
          To compile this driver as a module, choose M here. The module
          will be called i40e.
 
+config I40E_VXLAN
+       bool "Virtual eXtensible Local Area Network Support"
+       default n
+       depends on I40E && VXLAN && !(I40E=y && VXLAN=m)
+       ---help---
+         This allows one to create VXLAN virtual interfaces that provide
+         Layer 2 Networks over Layer 3 Networks. VXLAN is often used
+         to tunnel virtual network infrastructure in virtualized environments.
+         Say Y here if you want to use Virtual eXtensible Local Area Network
+         (VXLAN) in the driver.
+
+         If unsure, say N.
+
+config I40EVF
+       tristate "Intel(R) XL710 X710 Virtual Function Ethernet support"
+       depends on PCI_MSI
+       ---help---
+         This driver supports Intel(R) XL710 and X710 virtual functions.
+         For more information on how to identify your adapter, go to the
+         Adapter & Driver ID Guide at:
+
+         <http://support.intel.com/support/network/sb/CS-008441.htm>
+
+         For general information and support, go to the Intel support
+         website at:
+
+         <http://support.intel.com>
+
+         To compile this driver as a module, choose M here. The module
+         will be called i40evf.  MSI-X interrupt support is required
+         for this driver to work correctly.
+
 endif # NET_VENDOR_INTEL
index 5bae933efc7c95dab0c97cd22a6c479c6497d941..cdbbca8a3755b723bbb484886a94c23d62c5950a 100644 (file)
@@ -11,3 +11,4 @@ obj-$(CONFIG_IXGBE) += ixgbe/
 obj-$(CONFIG_IXGBEVF) += ixgbevf/
 obj-$(CONFIG_I40E) += i40e/
 obj-$(CONFIG_IXGB) += ixgb/
+obj-$(CONFIG_I40EVF) += i40evf/
index 895450e9bb3cfe81d22f19148b4a52d9fc14352a..ff2d806eaef71bc2a7a861a8971c228cd6856e2a 100644 (file)
@@ -718,8 +718,11 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
        e1000_release_phy_80003es2lan(hw);
 
        /* Disable IBIST slave mode (far-end loopback) */
-       e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-                                       &kum_reg_data);
+       ret_val =
+           e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+                                           &kum_reg_data);
+       if (ret_val)
+               return ret_val;
        kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
        e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
                                         kum_reg_data);
index 051d1583e21130dfddac70cb42c16e66a249bda8..d6570b2d5a6bafea704a4238570dfa00582c0e92 100644 (file)
@@ -6184,7 +6184,7 @@ static int __e1000_resume(struct pci_dev *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 static int e1000_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -6203,7 +6203,7 @@ static int e1000_resume(struct device *dev)
 
        return __e1000_resume(pdev);
 }
-#endif /* CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_RUNTIME
 static int e1000_runtime_suspend(struct device *dev)
index da2be59505c06226b4cd79f9e8cc120945ca1d17..20e71f4ca4261f99694b04eccd3647906326239d 100644 (file)
@@ -1757,19 +1757,23 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                 * it across the board.
                 */
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
-               if (ret_val)
+               if (ret_val) {
                        /* If the first read fails, another entity may have
                         * ownership of the resources, wait and try again to
                         * see if they have relinquished the resources yet.
                         */
-                       udelay(usec_interval);
+                       if (usec_interval >= 1000)
+                               msleep(usec_interval / 1000);
+                       else
+                               udelay(usec_interval);
+               }
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
                if (ret_val)
                        break;
                if (phy_status & BMSR_LSTATUS)
                        break;
                if (usec_interval >= 1000)
-                       mdelay(usec_interval / 1000);
+                       msleep(usec_interval / 1000);
                else
                        udelay(usec_interval);
        }
index 479b2c4e552d165c0470fccd008fd392e3a95e0f..e4d2e27078a7fc3e13c5eadbc871e5fd45c23e2b 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel Ethernet Controller XL710 Family Linux Driver
-# Copyright(c) 2013 Intel Corporation.
+# Copyright(c) 2013 - 2014 Intel Corporation.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
 # 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, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# 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".
@@ -41,4 +40,5 @@ i40e-objs := i40e_main.o \
        i40e_debugfs.o  \
        i40e_diag.o     \
        i40e_txrx.o     \
+       i40e_ptp.o      \
        i40e_virtchnl_pf.o
index 40706c15cdc37d7f51bfcf033207280738422fde..c05984d72cfbb11547e5a2bcd0efd9ccd0fa14a2 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -29,6 +28,7 @@
 #define _I40E_H_
 
 #include <net/tcp.h>
+#include <net/udp.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -50,6 +50,9 @@
 #include <net/ip6_checksum.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
+#include <linux/clocksource.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
 #include "i40e_type.h"
 #include "i40e_prototype.h"
 #include "i40e_virtchnl.h"
@@ -64,7 +67,7 @@
 #define I40E_MAX_NPAR_QPS     32
 
 #define I40E_MAX_NUM_DESCRIPTORS      4096
-#define I40E_MAX_REGISTER     0x0038FFFF
+#define I40E_MAX_REGISTER     0x800000
 #define I40E_DEFAULT_NUM_DESCRIPTORS  512
 #define I40E_REQ_DESCRIPTOR_MULTIPLE  32
 #define I40E_MIN_NUM_DESCRIPTORS      64
@@ -88,7 +91,7 @@
 
 /* The values in here are decimal coded as hex as is the case in the NVM map*/
 #define I40E_CURRENT_NVM_VERSION_HI 0x2
-#define I40E_CURRENT_NVM_VERSION_LO 0x1
+#define I40E_CURRENT_NVM_VERSION_LO 0x30
 
 
 /* magic for getting defines into strings */
@@ -205,7 +208,13 @@ struct i40e_pf {
        u16 rss_size_max;          /* HW defined max RSS queues */
        u16 fdir_pf_filter_count;  /* num of guaranteed filters for this PF */
        u8 atr_sample_rate;
+       bool wol_en;
 
+#ifdef CONFIG_I40E_VXLAN
+       __be16  vxlan_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
+       u16 pending_vxlan_bitmap;
+
+#endif
        enum i40e_interrupt_policy int_policy;
        u16 rx_itr_default;
        u16 tx_itr_default;
@@ -223,24 +232,24 @@ struct i40e_pf {
 #define I40E_FLAG_RX_1BUF_ENABLED              (u64)(1 << 4)
 #define I40E_FLAG_RX_PS_ENABLED                (u64)(1 << 5)
 #define I40E_FLAG_RSS_ENABLED                  (u64)(1 << 6)
-#define I40E_FLAG_MQ_ENABLED                   (u64)(1 << 7)
-#define I40E_FLAG_VMDQ_ENABLED                 (u64)(1 << 8)
-#define I40E_FLAG_FDIR_REQUIRES_REINIT         (u64)(1 << 9)
-#define I40E_FLAG_NEED_LINK_UPDATE             (u64)(1 << 10)
-#define I40E_FLAG_IN_NETPOLL                   (u64)(1 << 13)
-#define I40E_FLAG_16BYTE_RX_DESC_ENABLED       (u64)(1 << 14)
-#define I40E_FLAG_CLEAN_ADMINQ                 (u64)(1 << 15)
-#define I40E_FLAG_FILTER_SYNC                  (u64)(1 << 16)
-#define I40E_FLAG_PROCESS_MDD_EVENT            (u64)(1 << 18)
-#define I40E_FLAG_PROCESS_VFLR_EVENT           (u64)(1 << 19)
-#define I40E_FLAG_SRIOV_ENABLED                (u64)(1 << 20)
-#define I40E_FLAG_DCB_ENABLED                  (u64)(1 << 21)
-#define I40E_FLAG_FDIR_ENABLED                 (u64)(1 << 22)
-#define I40E_FLAG_FDIR_ATR_ENABLED             (u64)(1 << 23)
-#define I40E_FLAG_MFP_ENABLED                  (u64)(1 << 27)
-
-       u16 num_tx_queues;
-       u16 num_rx_queues;
+#define I40E_FLAG_VMDQ_ENABLED                 (u64)(1 << 7)
+#define I40E_FLAG_FDIR_REQUIRES_REINIT         (u64)(1 << 8)
+#define I40E_FLAG_NEED_LINK_UPDATE             (u64)(1 << 9)
+#define I40E_FLAG_IN_NETPOLL                   (u64)(1 << 12)
+#define I40E_FLAG_16BYTE_RX_DESC_ENABLED       (u64)(1 << 13)
+#define I40E_FLAG_CLEAN_ADMINQ                 (u64)(1 << 14)
+#define I40E_FLAG_FILTER_SYNC                  (u64)(1 << 15)
+#define I40E_FLAG_PROCESS_MDD_EVENT            (u64)(1 << 17)
+#define I40E_FLAG_PROCESS_VFLR_EVENT           (u64)(1 << 18)
+#define I40E_FLAG_SRIOV_ENABLED                (u64)(1 << 19)
+#define I40E_FLAG_DCB_ENABLED                  (u64)(1 << 20)
+#define I40E_FLAG_FDIR_ENABLED                 (u64)(1 << 21)
+#define I40E_FLAG_FDIR_ATR_ENABLED             (u64)(1 << 22)
+#define I40E_FLAG_PTP                          (u64)(1 << 25)
+#define I40E_FLAG_MFP_ENABLED                  (u64)(1 << 26)
+#ifdef CONFIG_I40E_VXLAN
+#define I40E_FLAG_VXLAN_FILTER_SYNC            (u64)(1 << 27)
+#endif
 
        bool stat_offsets_loaded;
        struct i40e_hw_port_stats stats;
@@ -297,6 +306,20 @@ struct i40e_pf {
        u32     fcoe_hmc_filt_num;
        u32     fcoe_hmc_cntx_num;
        struct i40e_filter_control_settings filter_settings;
+
+       struct ptp_clock *ptp_clock;
+       struct ptp_clock_info ptp_caps;
+       struct sk_buff *ptp_tx_skb;
+       struct work_struct ptp_tx_work;
+       struct hwtstamp_config tstamp_config;
+       unsigned long ptp_tx_start;
+       unsigned long last_rx_ptp_check;
+       spinlock_t tmreg_lock; /* Used to protect the device time registers. */
+       u64 ptp_base_adj;
+       u32 tx_hwtstamp_timeouts;
+       u32 rx_hwtstamp_cleared;
+       bool ptp_tx;
+       bool ptp_rx;
 };
 
 struct i40e_mac_filter {
@@ -511,13 +534,6 @@ struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi);
 int i40e_fetch_switch_configuration(struct i40e_pf *pf,
                                    bool printconfig);
 
-/* needed by i40e_main.c */
-void i40e_add_fdir_filter(struct i40e_fdir_data fdir_data,
-                         struct i40e_ring *tx_ring);
-void i40e_add_remove_filter(struct i40e_fdir_data fdir_data,
-                           struct i40e_ring *tx_ring);
-void i40e_update_fdir_filter(struct i40e_fdir_data fdir_data,
-                            struct i40e_ring *tx_ring);
 int i40e_program_fdir_filter(struct i40e_fdir_data *fdir_data,
                             struct i40e_pf *pf, bool add);
 
@@ -533,6 +549,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
 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);
+int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable);
 int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count);
 struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid,
                                u16 downlink_seid, u8 enabled_tc);
@@ -554,6 +571,7 @@ static inline void i40e_dbg_init(void) {}
 static inline void i40e_dbg_exit(void) {}
 #endif /* CONFIG_DEBUG_FS*/
 void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector);
+void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf);
 void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf);
 int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
 void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
@@ -566,4 +584,12 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
                                      bool is_vf, bool is_netdev);
 void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
 
+void i40e_ptp_rx_hang(struct i40e_vsi *vsi);
+void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf);
+void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index);
+void i40e_ptp_set_increment(struct i40e_pf *pf);
+int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
+int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
+void i40e_ptp_init(struct i40e_pf *pf);
+void i40e_ptp_stop(struct i40e_pf *pf);
 #endif /* _I40E_H_ */
index c7e286621a9451c4c9b3f2b4ac029f711fd7991a..a50e6b3479ae9c779475681634535f1c8181f309 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -66,9 +65,8 @@ static void i40e_adminq_init_regs(struct i40e_hw *hw)
 static i40e_status i40e_alloc_adminq_asq_ring(struct i40e_hw *hw)
 {
        i40e_status ret_code;
-       struct i40e_virt_mem mem;
 
-       ret_code = i40e_allocate_dma_mem(hw, &hw->aq.asq_mem,
+       ret_code = i40e_allocate_dma_mem(hw, &hw->aq.asq.desc_buf,
                                         i40e_mem_atq_ring,
                                         (hw->aq.num_asq_entries *
                                         sizeof(struct i40e_aq_desc)),
@@ -76,21 +74,14 @@ static i40e_status i40e_alloc_adminq_asq_ring(struct i40e_hw *hw)
        if (ret_code)
                return ret_code;
 
-       hw->aq.asq.desc = hw->aq.asq_mem.va;
-       hw->aq.asq.dma_addr = hw->aq.asq_mem.pa;
-
-       ret_code = i40e_allocate_virt_mem(hw, &mem,
+       ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.cmd_buf,
                                          (hw->aq.num_asq_entries *
                                          sizeof(struct i40e_asq_cmd_details)));
        if (ret_code) {
-               i40e_free_dma_mem(hw, &hw->aq.asq_mem);
-               hw->aq.asq_mem.va = NULL;
-               hw->aq.asq_mem.pa = 0;
+               i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
                return ret_code;
        }
 
-       hw->aq.asq.details = mem.va;
-
        return ret_code;
 }
 
@@ -102,16 +93,11 @@ static i40e_status i40e_alloc_adminq_arq_ring(struct i40e_hw *hw)
 {
        i40e_status ret_code;
 
-       ret_code = i40e_allocate_dma_mem(hw, &hw->aq.arq_mem,
+       ret_code = i40e_allocate_dma_mem(hw, &hw->aq.arq.desc_buf,
                                         i40e_mem_arq_ring,
                                         (hw->aq.num_arq_entries *
                                         sizeof(struct i40e_aq_desc)),
                                         I40E_ADMINQ_DESC_ALIGNMENT);
-       if (ret_code)
-               return ret_code;
-
-       hw->aq.arq.desc = hw->aq.arq_mem.va;
-       hw->aq.arq.dma_addr = hw->aq.arq_mem.pa;
 
        return ret_code;
 }
@@ -125,14 +111,7 @@ static i40e_status i40e_alloc_adminq_arq_ring(struct i40e_hw *hw)
  **/
 static void i40e_free_adminq_asq(struct i40e_hw *hw)
 {
-       struct i40e_virt_mem mem;
-
-       i40e_free_dma_mem(hw, &hw->aq.asq_mem);
-       hw->aq.asq_mem.va = NULL;
-       hw->aq.asq_mem.pa = 0;
-       mem.va = hw->aq.asq.details;
-       i40e_free_virt_mem(hw, &mem);
-       hw->aq.asq.details = NULL;
+       i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
 }
 
 /**
@@ -144,20 +123,17 @@ static void i40e_free_adminq_asq(struct i40e_hw *hw)
  **/
 static void i40e_free_adminq_arq(struct i40e_hw *hw)
 {
-       i40e_free_dma_mem(hw, &hw->aq.arq_mem);
-       hw->aq.arq_mem.va = NULL;
-       hw->aq.arq_mem.pa = 0;
+       i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
 }
 
 /**
  *  i40e_alloc_arq_bufs - Allocate pre-posted buffers for the receive queue
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  **/
 static i40e_status i40e_alloc_arq_bufs(struct i40e_hw *hw)
 {
        i40e_status ret_code;
        struct i40e_aq_desc *desc;
-       struct i40e_virt_mem mem;
        struct i40e_dma_mem *bi;
        int i;
 
@@ -166,11 +142,11 @@ static i40e_status i40e_alloc_arq_bufs(struct i40e_hw *hw)
         */
 
        /* buffer_info structures do not need alignment */
-       ret_code = i40e_allocate_virt_mem(hw, &mem, (hw->aq.num_arq_entries *
-                                         sizeof(struct i40e_dma_mem)));
+       ret_code = i40e_allocate_virt_mem(hw, &hw->aq.arq.dma_head,
+               (hw->aq.num_arq_entries * sizeof(struct i40e_dma_mem)));
        if (ret_code)
                goto alloc_arq_bufs;
-       hw->aq.arq.r.arq_bi = (struct i40e_dma_mem *)mem.va;
+       hw->aq.arq.r.arq_bi = (struct i40e_dma_mem *)hw->aq.arq.dma_head.va;
 
        /* allocate the mapped buffers */
        for (i = 0; i < hw->aq.num_arq_entries; i++) {
@@ -212,29 +188,27 @@ unwind_alloc_arq_bufs:
        i--;
        for (; i >= 0; i--)
                i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
-       mem.va = hw->aq.arq.r.arq_bi;
-       i40e_free_virt_mem(hw, &mem);
+       i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
 
        return ret_code;
 }
 
 /**
  *  i40e_alloc_asq_bufs - Allocate empty buffer structs for the send queue
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  **/
 static i40e_status i40e_alloc_asq_bufs(struct i40e_hw *hw)
 {
        i40e_status ret_code;
-       struct i40e_virt_mem mem;
        struct i40e_dma_mem *bi;
        int i;
 
        /* No mapped memory needed yet, just the buffer info structures */
-       ret_code = i40e_allocate_virt_mem(hw, &mem, (hw->aq.num_asq_entries *
-                                         sizeof(struct i40e_dma_mem)));
+       ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.dma_head,
+               (hw->aq.num_asq_entries * sizeof(struct i40e_dma_mem)));
        if (ret_code)
                goto alloc_asq_bufs;
-       hw->aq.asq.r.asq_bi = (struct i40e_dma_mem *)mem.va;
+       hw->aq.asq.r.asq_bi = (struct i40e_dma_mem *)hw->aq.asq.dma_head.va;
 
        /* allocate the mapped buffers */
        for (i = 0; i < hw->aq.num_asq_entries; i++) {
@@ -254,35 +228,36 @@ unwind_alloc_asq_bufs:
        i--;
        for (; i >= 0; i--)
                i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
-       mem.va = hw->aq.asq.r.asq_bi;
-       i40e_free_virt_mem(hw, &mem);
+       i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
 
        return ret_code;
 }
 
 /**
  *  i40e_free_arq_bufs - Free receive queue buffer info elements
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  **/
 static void i40e_free_arq_bufs(struct i40e_hw *hw)
 {
-       struct i40e_virt_mem mem;
        int i;
 
+       /* free descriptors */
        for (i = 0; i < hw->aq.num_arq_entries; i++)
                i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
 
-       mem.va = hw->aq.arq.r.arq_bi;
-       i40e_free_virt_mem(hw, &mem);
+       /* free the descriptor memory */
+       i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
+
+       /* free the dma header */
+       i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
 }
 
 /**
  *  i40e_free_asq_bufs - Free send queue buffer info elements
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  **/
 static void i40e_free_asq_bufs(struct i40e_hw *hw)
 {
-       struct i40e_virt_mem mem;
        int i;
 
        /* only unmap if the address is non-NULL */
@@ -290,14 +265,19 @@ static void i40e_free_asq_bufs(struct i40e_hw *hw)
                if (hw->aq.asq.r.asq_bi[i].pa)
                        i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
 
-       /* now free the buffer info list */
-       mem.va = hw->aq.asq.r.asq_bi;
-       i40e_free_virt_mem(hw, &mem);
+       /* free the buffer info list */
+       i40e_free_virt_mem(hw, &hw->aq.asq.cmd_buf);
+
+       /* free the descriptor memory */
+       i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
+
+       /* free the dma header */
+       i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
 }
 
 /**
  *  i40e_config_asq_regs - configure ASQ registers
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  *
  *  Configure base address and length registers for the transmit queue
  **/
@@ -305,14 +285,18 @@ static void i40e_config_asq_regs(struct i40e_hw *hw)
 {
        if (hw->mac.type == I40E_MAC_VF) {
                /* configure the transmit queue */
-               wr32(hw, I40E_VF_ATQBAH1, upper_32_bits(hw->aq.asq.dma_addr));
-               wr32(hw, I40E_VF_ATQBAL1, lower_32_bits(hw->aq.asq.dma_addr));
+               wr32(hw, I40E_VF_ATQBAH1,
+                   upper_32_bits(hw->aq.asq.desc_buf.pa));
+               wr32(hw, I40E_VF_ATQBAL1,
+                   lower_32_bits(hw->aq.asq.desc_buf.pa));
                wr32(hw, I40E_VF_ATQLEN1, (hw->aq.num_asq_entries |
                                          I40E_VF_ATQLEN1_ATQENABLE_MASK));
        } else {
                /* configure the transmit queue */
-               wr32(hw, I40E_PF_ATQBAH, upper_32_bits(hw->aq.asq.dma_addr));
-               wr32(hw, I40E_PF_ATQBAL, lower_32_bits(hw->aq.asq.dma_addr));
+               wr32(hw, I40E_PF_ATQBAH,
+                   upper_32_bits(hw->aq.asq.desc_buf.pa));
+               wr32(hw, I40E_PF_ATQBAL,
+                   lower_32_bits(hw->aq.asq.desc_buf.pa));
                wr32(hw, I40E_PF_ATQLEN, (hw->aq.num_asq_entries |
                                          I40E_PF_ATQLEN_ATQENABLE_MASK));
        }
@@ -320,7 +304,7 @@ static void i40e_config_asq_regs(struct i40e_hw *hw)
 
 /**
  *  i40e_config_arq_regs - ARQ register configuration
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  *
  * Configure base address and length registers for the receive (event queue)
  **/
@@ -328,14 +312,18 @@ static void i40e_config_arq_regs(struct i40e_hw *hw)
 {
        if (hw->mac.type == I40E_MAC_VF) {
                /* configure the receive queue */
-               wr32(hw, I40E_VF_ARQBAH1, upper_32_bits(hw->aq.arq.dma_addr));
-               wr32(hw, I40E_VF_ARQBAL1, lower_32_bits(hw->aq.arq.dma_addr));
+               wr32(hw, I40E_VF_ARQBAH1,
+                   upper_32_bits(hw->aq.arq.desc_buf.pa));
+               wr32(hw, I40E_VF_ARQBAL1,
+                   lower_32_bits(hw->aq.arq.desc_buf.pa));
                wr32(hw, I40E_VF_ARQLEN1, (hw->aq.num_arq_entries |
                                          I40E_VF_ARQLEN1_ARQENABLE_MASK));
        } else {
                /* configure the receive queue */
-               wr32(hw, I40E_PF_ARQBAH, upper_32_bits(hw->aq.arq.dma_addr));
-               wr32(hw, I40E_PF_ARQBAL, lower_32_bits(hw->aq.arq.dma_addr));
+               wr32(hw, I40E_PF_ARQBAH,
+                   upper_32_bits(hw->aq.arq.desc_buf.pa));
+               wr32(hw, I40E_PF_ARQBAL,
+                   lower_32_bits(hw->aq.arq.desc_buf.pa));
                wr32(hw, I40E_PF_ARQLEN, (hw->aq.num_arq_entries |
                                          I40E_PF_ARQLEN_ARQENABLE_MASK));
        }
@@ -346,7 +334,7 @@ static void i40e_config_arq_regs(struct i40e_hw *hw)
 
 /**
  *  i40e_init_asq - main initialization routine for ASQ
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  *
  *  This is the main initialization routine for the Admin Send Queue
  *  Prior to calling this function, drivers *MUST* set the following fields
@@ -403,7 +391,7 @@ init_adminq_exit:
 
 /**
  *  i40e_init_arq - initialize ARQ
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  *
  *  The main initialization routine for the Admin Receive (Event) Queue.
  *  Prior to calling this function, drivers *MUST* set the following fields
@@ -460,7 +448,7 @@ init_adminq_exit:
 
 /**
  *  i40e_shutdown_asq - shutdown the ASQ
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  *
  *  The main shutdown routine for the Admin Send Queue
  **/
@@ -483,8 +471,6 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
 
        /* free ring buffers */
        i40e_free_asq_bufs(hw);
-       /* free the ring descriptors */
-       i40e_free_adminq_asq(hw);
 
        mutex_unlock(&hw->aq.asq_mutex);
 
@@ -493,7 +479,7 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
 
 /**
  *  i40e_shutdown_arq - shutdown ARQ
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  *
  *  The main shutdown routine for the Admin Receive Queue
  **/
@@ -516,8 +502,6 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
 
        /* free ring buffers */
        i40e_free_arq_bufs(hw);
-       /* free the ring descriptors */
-       i40e_free_adminq_arq(hw);
 
        mutex_unlock(&hw->aq.arq_mutex);
 
@@ -526,7 +510,7 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
 
 /**
  *  i40e_init_adminq - main initialization routine for Admin Queue
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  *
  *  Prior to calling this function, drivers *MUST* set the following fields
  *  in the hw->aq structure:
@@ -587,16 +571,21 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
        if (ret_code != I40E_SUCCESS)
                goto init_adminq_free_arq;
 
-       if (hw->aq.api_maj_ver != I40E_FW_API_VERSION_MAJOR ||
-           hw->aq.api_min_ver != I40E_FW_API_VERSION_MINOR) {
-               ret_code = I40E_ERR_FIRMWARE_API_VERSION;
-               goto init_adminq_free_arq;
-       }
+       /* get the NVM version info */
        i40e_read_nvm_word(hw, I40E_SR_NVM_IMAGE_VERSION, &hw->nvm.version);
        i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_LO, &eetrack_lo);
        i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_HI, &eetrack_hi);
        hw->nvm.eetrack = (eetrack_hi << 16) | eetrack_lo;
 
+       if (hw->aq.api_maj_ver != I40E_FW_API_VERSION_MAJOR ||
+           hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR) {
+               ret_code = I40E_ERR_FIRMWARE_API_VERSION;
+               goto init_adminq_free_arq;
+       }
+
+       /* pre-emptive resource lock release */
+       i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
+
        ret_code = i40e_aq_set_hmc_resource_profile(hw,
                                                    I40E_HMC_PROFILE_DEFAULT,
                                                    0,
@@ -618,12 +607,15 @@ init_adminq_exit:
 
 /**
  *  i40e_shutdown_adminq - shutdown routine for the Admin Queue
- *  @hw:     pointer to the hardware structure
+ *  @hw: pointer to the hardware structure
  **/
 i40e_status i40e_shutdown_adminq(struct i40e_hw *hw)
 {
        i40e_status ret_code = 0;
 
+       if (i40e_check_asq_alive(hw))
+               i40e_aq_queue_shutdown(hw, true);
+
        i40e_shutdown_asq(hw);
        i40e_shutdown_arq(hw);
 
@@ -634,7 +626,7 @@ i40e_status i40e_shutdown_adminq(struct i40e_hw *hw)
 
 /**
  *  i40e_clean_asq - cleans Admin send queue
- *  @asq: pointer to the adminq send ring
+ *  @hw: pointer to the hardware structure
  *
  *  returns the number of free desc
  **/
@@ -682,7 +674,7 @@ static bool i40e_asq_done(struct i40e_hw *hw)
        /* AQ designers suggest use of head for better
         * timing reliability than DD bit
         */
-       return (rd32(hw, hw->aq.asq.head) == hw->aq.asq.next_to_use);
+       return rd32(hw, hw->aq.asq.head) == hw->aq.asq.next_to_use;
 
 }
 
@@ -692,7 +684,7 @@ static bool i40e_asq_done(struct i40e_hw *hw)
  *  @desc: prefilled descriptor describing the command (non DMA mem)
  *  @buff: buffer to use for indirect commands
  *  @buff_size: size of buffer for indirect commands
- *  @opaque: pointer to info to be used in async cleanup
+ *  @cmd_details: pointer to command details structure
  *
  *  This is the main send command driver routine for the Admin Queue send
  *  queue.  It runs the queue, cleans the queue, etc
@@ -872,7 +864,7 @@ void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
        /* zero out the desc */
        memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
        desc->opcode = cpu_to_le16(opcode);
-       desc->flags = cpu_to_le16(I40E_AQ_FLAG_EI | I40E_AQ_FLAG_SI);
+       desc->flags = cpu_to_le16(I40E_AQ_FLAG_SI);
 }
 
 /**
@@ -930,7 +922,7 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
                           "AQRX: Event received with error 0x%X.\n",
                           hw->aq.arq_last_status);
        } else {
-               memcpy(&e->desc, desc, sizeof(struct i40e_aq_desc));
+               e->desc = *desc;
                datalen = le16_to_cpu(desc->datalen);
                e->msg_size = min(datalen, e->msg_size);
                if (e->msg_buf != NULL && (e->msg_size != 0))
@@ -943,6 +935,11 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
         * size
         */
        bi = &hw->aq.arq.r.arq_bi[ntc];
+       memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
+
+       desc->flags = cpu_to_le16(I40E_AQ_FLAG_BUF);
+       if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
+               desc->flags |= cpu_to_le16(I40E_AQ_FLAG_LB);
        desc->datalen = cpu_to_le16((u16)bi->size);
        desc->params.external.addr_high = cpu_to_le32(upper_32_bits(bi->pa));
        desc->params.external.addr_low = cpu_to_le32(lower_32_bits(bi->pa));
@@ -967,20 +964,14 @@ clean_arq_element_out:
 
 static void i40e_resume_aq(struct i40e_hw *hw)
 {
-       u32 reg = 0;
-
        /* Registers are reset after PF reset */
        hw->aq.asq.next_to_use = 0;
        hw->aq.asq.next_to_clean = 0;
 
        i40e_config_asq_regs(hw);
-       reg = hw->aq.num_asq_entries | I40E_PF_ATQLEN_ATQENABLE_MASK;
-       wr32(hw, hw->aq.asq.len, reg);
 
        hw->aq.arq.next_to_use = 0;
        hw->aq.arq.next_to_clean = 0;
 
        i40e_config_arq_regs(hw);
-       reg = hw->aq.num_arq_entries | I40E_PF_ATQLEN_ATQENABLE_MASK;
-       wr32(hw, hw->aq.arq.len, reg);
 }
index f8c2c44e233d4cc14a5386083d6daf961c64bc82..993f7685a9111694726c1a9bee44f3653651df72 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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 "i40e_adminq_cmd.h"
 
 #define I40E_ADMINQ_DESC(R, i)   \
-       (&(((struct i40e_aq_desc *)((R).desc))[i]))
+       (&(((struct i40e_aq_desc *)((R).desc_buf.va))[i]))
 
 #define I40E_ADMINQ_DESC_ALIGNMENT 4096
 
 struct i40e_adminq_ring {
-       void *desc;             /* Descriptor ring memory */
-       void *details;          /* ASQ details */
+       struct i40e_virt_mem dma_head;  /* space for dma structures */
+       struct i40e_dma_mem desc_buf;   /* descriptor ring memory */
+       struct i40e_virt_mem cmd_buf;   /* command buffer memory */
 
        union {
                struct i40e_dma_mem *asq_bi;
                struct i40e_dma_mem *arq_bi;
        } r;
 
-       u64 dma_addr;           /* Physical address of the ring */
        u16 count;              /* Number of descriptors */
        u16 rx_buf_len;         /* Admin Receive Queue buffer length */
 
@@ -70,7 +69,7 @@ struct i40e_asq_cmd_details {
 };
 
 #define I40E_ADMINQ_DETAILS(R, i)   \
-       (&(((struct i40e_asq_cmd_details *)((R).details))[i]))
+       (&(((struct i40e_asq_cmd_details *)((R).cmd_buf.va))[i]))
 
 /* ARQ event information */
 struct i40e_arq_event_info {
@@ -95,9 +94,6 @@ struct i40e_adminq_info {
        struct mutex asq_mutex; /* Send queue lock */
        struct mutex arq_mutex; /* Receive queue lock */
 
-       struct i40e_dma_mem asq_mem;    /* send queue dynamic memory */
-       struct i40e_dma_mem arq_mem;    /* receive queue dynamic memory */
-
        /* last status values on send and receive queues */
        enum i40e_admin_queue_err asq_last_status;
        enum i40e_admin_queue_err arq_last_status;
index e61ebdd5a5f933222fe2675e6b5ba8bba3bf87d4..c009eb47058ab1331df34e15be2e95cea22d4e86 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -35,7 +34,7 @@
  */
 
 #define I40E_FW_API_VERSION_MAJOR  0x0001
-#define I40E_FW_API_VERSION_MINOR  0x0000
+#define I40E_FW_API_VERSION_MINOR  0x0001
 
 struct i40e_aq_desc {
        __le16 flags;
@@ -137,10 +136,13 @@ enum i40e_admin_queue_opc {
        i40e_aqc_opc_set_ns_proxy_entry     = 0x0105,
 
        /* LAA */
-       i40e_aqc_opc_mng_laa                = 0x0106,
+       i40e_aqc_opc_mng_laa                = 0x0106,   /* AQ obsolete */
        i40e_aqc_opc_mac_address_read       = 0x0107,
        i40e_aqc_opc_mac_address_write      = 0x0108,
 
+       /* PXE */
+       i40e_aqc_opc_clear_pxe_mode         = 0x0110,
+
        /* internal switch commands */
        i40e_aqc_opc_get_switch_config         = 0x0200,
        i40e_aqc_opc_add_statistics            = 0x0201,
@@ -317,13 +319,15 @@ struct i40e_aqc_get_version {
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_get_version);
 
-/* Send driver version (direct 0x0002) */
+/* Send driver version (indirect 0x0002) */
 struct i40e_aqc_driver_version {
        u8     driver_major_ver;
        u8     driver_minor_ver;
        u8     driver_build_ver;
        u8     driver_subbuild_ver;
-       u8     reserved[12];
+       u8     reserved[4];
+       __le32 address_high;
+       __le32 address_low;
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_driver_version);
@@ -479,7 +483,7 @@ struct i40e_aqc_mng_laa {
        u8     reserved2[6];
 };
 
-/* Manage MAC Address Read Command (0x0107) */
+/* Manage MAC Address Read Command (indirect 0x0107) */
 struct i40e_aqc_mac_address_read {
        __le16  command_flags;
 #define I40E_AQC_LAN_ADDR_VALID   0x10
@@ -517,6 +521,16 @@ struct i40e_aqc_mac_address_write {
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_write);
 
+/* PXE commands (0x011x) */
+
+/* Clear PXE Command and response  (direct 0x0110) */
+struct i40e_aqc_clear_pxe {
+       u8      rx_cnt;
+       u8      reserved[15];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_clear_pxe);
+
 /* Switch configuration commands (0x02xx) */
 
 /* Used by many indirect commands that only pass an seid and a buffer in the
@@ -639,13 +653,15 @@ struct i40e_aqc_switch_resource_alloc_element_resp {
        u8     reserved2[6];
 };
 
-/* Add VSI (indirect 0x210)
+/* Add VSI (indirect 0x0210)
  *    this indirect command uses struct i40e_aqc_vsi_properties_data
  *    as the indirect buffer (128 bytes)
  *
- * Update VSI (indirect 0x211) Get VSI (indirect 0x0212)
- *    use the generic i40e_aqc_switch_seid descriptor format
- *    use the same completion and data structure as Add VSI
+ * Update VSI (indirect 0x211)
+ *     uses the same data structure as Add VSI
+ *
+ * Get VSI (indirect 0x0212)
+ *     uses the same completion and data structure as Add VSI
  */
 struct i40e_aqc_add_get_update_vsi {
        __le16 uplink_seid;
@@ -1185,27 +1201,40 @@ struct i40e_aqc_add_remove_cloud_filters_element_data {
 #define I40E_AQC_ADD_CLOUD_FILTER_SHIFT                 0
 #define I40E_AQC_ADD_CLOUD_FILTER_MASK                  (0x3F << \
                                        I40E_AQC_ADD_CLOUD_FILTER_SHIFT)
+/* 0x0000 reserved */
 #define I40E_AQC_ADD_CLOUD_FILTER_OIP                   0x0001
-#define I40E_AQC_ADD_CLOUD_FILTER_OIP_GRE               0x0002
+/* 0x0002 reserved */
 #define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN            0x0003
-#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_GRE        0x0004
+#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID     0x0004
+/* 0x0005 reserved */
 #define I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID           0x0006
-#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_VNL        0x0007
+/* 0x0007 reserved */
 /* 0x0008 reserved */
 #define I40E_AQC_ADD_CLOUD_FILTER_OMAC                  0x0009
 #define I40E_AQC_ADD_CLOUD_FILTER_IMAC                  0x000A
+#define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC      0x000B
+#define I40E_AQC_ADD_CLOUD_FILTER_IIP                   0x000C
+
 #define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE               0x0080
 #define I40E_AQC_ADD_CLOUD_VNK_SHIFT                    6
 #define I40E_AQC_ADD_CLOUD_VNK_MASK                     0x00C0
 #define I40E_AQC_ADD_CLOUD_FLAGS_IPV4                   0
 #define I40E_AQC_ADD_CLOUD_FLAGS_IPV6                   0x0100
-       __le32 key_low;
-       __le32 key_high;
+
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT               9
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK                0x1E00
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN               0
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC          1
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE                 2
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP                  3
+
+       __le32 tenant_id;
+       u8     reserved[4];
        __le16 queue_number;
 #define I40E_AQC_ADD_CLOUD_QUEUE_SHIFT                  0
 #define I40E_AQC_ADD_CLOUD_QUEUE_MASK                   (0x3F << \
                                        I40E_AQC_ADD_CLOUD_QUEUE_SHIFT)
-       u8     reserved[14];
+       u8     reserved2[14];
        /* response section */
        u8     allocation_result;
 #define I40E_AQC_ADD_CLOUD_FILTER_SUCCESS         0x0
@@ -1548,7 +1577,7 @@ struct i40e_aqc_module_desc {
 
 struct i40e_aq_get_phy_abilities_resp {
        __le32 phy_type;       /* bitmap using the above enum for offsets */
-       u8     link_speed;     /* bitmap using the above enum */
+       u8     link_speed;     /* bitmap using the above enum bit patterns */
        u8     abilities;
 #define I40E_AQ_PHY_FLAG_PAUSE_TX         0x01
 #define I40E_AQ_PHY_FLAG_PAUSE_RX         0x02
@@ -1582,6 +1611,10 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */
        __le32 phy_type;
        u8     link_speed;
        u8     abilities;
+/* bits 0-2 use the values from get_phy_abilities_resp */
+#define I40E_AQ_PHY_ENABLE_LINK                0x08
+#define I40E_AQ_PHY_ENABLE_AN          0x10
+#define I40E_AQ_PHY_ENABLE_ATOMIC_LINK 0x20
        __le16 eee_capability;
        __le32 eeer;
        u8     low_power_ctrl;
@@ -1915,21 +1948,39 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start);
 struct i40e_aqc_add_udp_tunnel {
        __le16 udp_port;
        u8     header_len; /* in DWords, 1 to 15 */
-       u8     protocol_index;
-#define I40E_AQC_TUNNEL_TYPE_MAC    0x0
-#define I40E_AQC_TUNNEL_TYPE_UDP    0x1
-       u8     reserved[12];
+       u8     protocol_type;
+#define I40E_AQC_TUNNEL_TYPE_TEREDO    0x0
+#define I40E_AQC_TUNNEL_TYPE_VXLAN     0x2
+#define I40E_AQC_TUNNEL_TYPE_NGE       0x3
+       u8     variable_udp_length;
+#define I40E_AQC_TUNNEL_FIXED_UDP_LENGTH       0x0
+#define I40E_AQC_TUNNEL_VARIABLE_UDP_LENGTH    0x1
+       u8     udp_key_index;
+#define I40E_AQC_TUNNEL_KEY_INDEX_VXLAN                        0x0
+#define I40E_AQC_TUNNEL_KEY_INDEX_NGE                  0x1
+#define I40E_AQC_TUNNEL_KEY_INDEX_PROPRIETARY_UDP      0x2
+       u8     reserved[10];
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel);
 
+struct i40e_aqc_add_udp_tunnel_completion {
+       __le16 udp_port;
+       u8     filter_entry_index;
+       u8     multiple_pfs;
+#define I40E_AQC_SINGLE_PF     0x0
+#define I40E_AQC_MULTIPLE_PFS  0x1
+       u8     total_filters;
+       u8     reserved[11];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel_completion);
+
 /* remove UDP Tunnel command (0x0B01) */
 struct i40e_aqc_remove_udp_tunnel {
        u8     reserved[2];
        u8     index; /* 0 to 15 */
-       u8     pf_filters;
-       u8     total_filters;
-       u8     reserved2[11];
+       u8     reserved2[13];
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_udp_tunnel);
@@ -1937,28 +1988,32 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_udp_tunnel);
 struct i40e_aqc_del_udp_tunnel_completion {
        __le16 udp_port;
        u8     index; /* 0 to 15 */
-       u8     multiple_entries;
-       u8     tunnels_used;
-       u8     reserved;
-       u8     tunnels_free;
-       u8     reserved1[9];
+       u8     multiple_pfs;
+       u8     total_filters_used;
+       u8     reserved1[11];
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_del_udp_tunnel_completion);
 
 /* tunnel key structure 0x0B10 */
+
 struct i40e_aqc_tunnel_key_structure {
-       __le16     key1_off;
-       __le16     key1_len;
-       __le16     key2_off;
-       __le16     key2_len;
-       __le16     flags;
+       u8      key1_off;
+       u8      key2_off;
+       u8      key1_len;  /* 0 to 15 */
+       u8      key2_len;  /* 0 to 15 */
+       u8      flags;
 #define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01
 /* response flags */
 #define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS    0x01
 #define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED   0x02
 #define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03
-       u8         resreved[6];
+       u8      network_key_index;
+#define I40E_AQC_NETWORK_KEY_INDEX_VXLAN               0x0
+#define I40E_AQC_NETWORK_KEY_INDEX_NGE                 0x1
+#define I40E_AQC_NETWORK_KEY_INDEX_FLEX_MAC_IN_UDP     0x2
+#define I40E_AQC_NETWORK_KEY_INDEX_GRE                 0x3
+       u8      reserved[10];
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_tunnel_key_structure);
@@ -2052,6 +2107,7 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_reg);
 #define I40E_AQ_CLUSTER_ID_DCB         8
 #define I40E_AQ_CLUSTER_ID_EMP_MEM     9
 #define I40E_AQ_CLUSTER_ID_PKT_BUF     10
+#define I40E_AQ_CLUSTER_ID_ALTRAM      11
 
 struct i40e_aqc_debug_dump_internals {
        u8     cluster_id;
index 3b1cc214f9dc432b5ad163194be3e09815e68a53..926811ad44ac2acdb3300a83b629596f39f54d1d 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
index 8b6d56a82fced548dcda40d87352116c5b878b98..0b5a75c40978632f70b37fd3891dd71f6f655d38 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -75,7 +74,8 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw)
 /**
  * i40e_debug_aq
  * @hw: debug mask related to admin queue
- * @cap: pointer to adminq command descriptor
+ * @mask: debug mask
+ * @desc: pointer to admin queue descriptor
  * @buffer: pointer to command buffer
  *
  * Dumps debug log about adminq command with descriptor contents.
@@ -125,6 +125,44 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
        }
 }
 
+/**
+ * i40e_check_asq_alive
+ * @hw: pointer to the hw struct
+ *
+ * Returns true if Queue is enabled else false.
+ **/
+bool i40e_check_asq_alive(struct i40e_hw *hw)
+{
+       return !!(rd32(hw, hw->aq.asq.len) & I40E_PF_ATQLEN_ATQENABLE_MASK);
+}
+
+/**
+ * i40e_aq_queue_shutdown
+ * @hw: pointer to the hw struct
+ * @unloading: is the driver unloading itself
+ *
+ * Tell the Firmware that we're shutting down the AdminQ and whether
+ * or not the driver is unloading as well.
+ **/
+i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw,
+                                            bool unloading)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_queue_shutdown *cmd =
+               (struct i40e_aqc_queue_shutdown *)&desc.params.raw;
+       i40e_status status;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_queue_shutdown);
+
+       if (unloading)
+               cmd->driver_unloading = cpu_to_le32(I40E_AQ_DRIVER_UNLOADING);
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL);
+
+       return status;
+}
+
+
 /**
  * i40e_init_shared_code - Initialize the shared code
  * @hw: pointer to hardware structure
@@ -142,14 +180,6 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw)
        i40e_status status = 0;
        u32 reg;
 
-       hw->phy.get_link_info = true;
-
-       /* Determine port number */
-       reg = rd32(hw, I40E_PFGEN_PORTNUM);
-       reg = ((reg & I40E_PFGEN_PORTNUM_PORT_NUM_MASK) >>
-              I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT);
-       hw->port = (u8)reg;
-
        i40e_set_mac_type(hw);
 
        switch (hw->mac.type) {
@@ -160,6 +190,21 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw)
                break;
        }
 
+       hw->phy.get_link_info = true;
+
+       /* Determine port number */
+       reg = rd32(hw, I40E_PFGEN_PORTNUM);
+       reg = ((reg & I40E_PFGEN_PORTNUM_PORT_NUM_MASK) >>
+              I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT);
+       hw->port = (u8)reg;
+
+       /* Determine the PF number based on the PCI fn */
+       reg = rd32(hw, I40E_GLPCI_CAPSUP);
+       if (reg & I40E_GLPCI_CAPSUP_ARI_EN_MASK)
+               hw->pf_id = (u8)((hw->bus.device << 3) | hw->bus.func);
+       else
+               hw->pf_id = (u8)hw->bus.func;
+
        status = i40e_init_nvm(hw);
        return status;
 }
@@ -210,8 +255,11 @@ i40e_status i40e_aq_mac_address_write(struct i40e_hw *hw,
        i40e_fill_default_direct_cmd_desc(&desc,
                                          i40e_aqc_opc_mac_address_write);
        cmd_data->command_flags = cpu_to_le16(flags);
-       memcpy(&cmd_data->mac_sal, &mac_addr[0], 4);
-       memcpy(&cmd_data->mac_sah, &mac_addr[4], 2);
+       cmd_data->mac_sah = cpu_to_le16((u16)mac_addr[0] << 8 | mac_addr[1]);
+       cmd_data->mac_sal = cpu_to_le32(((u32)mac_addr[2] << 24) |
+                                       ((u32)mac_addr[3] << 16) |
+                                       ((u32)mac_addr[4] << 8) |
+                                       mac_addr[5]);
 
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
@@ -239,33 +287,6 @@ i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr)
        return status;
 }
 
-/**
- * i40e_validate_mac_addr - Validate MAC address
- * @mac_addr: pointer to MAC address
- *
- * Tests a MAC address to ensure it is a valid Individual Address
- **/
-i40e_status i40e_validate_mac_addr(u8 *mac_addr)
-{
-       i40e_status status = 0;
-
-       /* Make sure it is not a multicast address */
-       if (I40E_IS_MULTICAST(mac_addr)) {
-               hw_dbg(hw, "MAC address is multicast\n");
-               status = I40E_ERR_INVALID_MAC_ADDR;
-       /* Not a broadcast address */
-       } else if (I40E_IS_BROADCAST(mac_addr)) {
-               hw_dbg(hw, "MAC address is broadcast\n");
-               status = I40E_ERR_INVALID_MAC_ADDR;
-       /* Reject the zero address */
-       } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
-                  mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
-               hw_dbg(hw, "MAC address is all zeros\n");
-               status = I40E_ERR_INVALID_MAC_ADDR;
-       }
-       return status;
-}
-
 /**
  * i40e_get_media_type - Gets media type
  * @hw: pointer to the hardware structure
@@ -324,6 +345,7 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
 i40e_status i40e_pf_reset(struct i40e_hw *hw)
 {
        u32 cnt = 0;
+       u32 cnt1 = 0;
        u32 reg = 0;
        u32 grst_del;
 
@@ -344,12 +366,24 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)
                return I40E_ERR_RESET_FAILED;
        }
 
-       /* Determine the PF number based on the PCI fn */
-       reg = rd32(hw, I40E_GLPCI_CAPSUP);
-       if (reg & I40E_GLPCI_CAPSUP_ARI_EN_MASK)
-               hw->pf_id = (u8)((hw->bus.device << 3) | hw->bus.func);
-       else
-               hw->pf_id = (u8)hw->bus.func;
+       /* Now Wait for the FW to be ready */
+       for (cnt1 = 0; cnt1 < I40E_PF_RESET_WAIT_COUNT; cnt1++) {
+               reg = rd32(hw, I40E_GLNVM_ULD);
+               reg &= (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK |
+                       I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK);
+               if (reg == (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK |
+                           I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK)) {
+                       hw_dbg(hw, "Core and Global modules ready %d\n", cnt1);
+                       break;
+               }
+               usleep_range(10000, 20000);
+       }
+       if (!(reg & (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK |
+                    I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK))) {
+               hw_dbg(hw, "wait for FW Reset complete timedout\n");
+               hw_dbg(hw, "I40E_GLNVM_ULD = 0x%x\n", reg);
+               return I40E_ERR_RESET_FAILED;
+       }
 
        /* If there was a Global Reset in progress when we got here,
         * we don't need to do the PF Reset
@@ -375,6 +409,7 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)
        }
 
        i40e_clear_pxe_mode(hw);
+
        return 0;
 }
 
@@ -400,6 +435,38 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw)
        }
 }
 
+/**
+ * i40e_led_is_mine - helper to find matching led
+ * @hw: pointer to the hw struct
+ * @idx: index into GPIO registers
+ *
+ * returns: 0 if no match, otherwise the value of the GPIO_CTL register
+ */
+static u32 i40e_led_is_mine(struct i40e_hw *hw, int idx)
+{
+       u32 gpio_val = 0;
+       u32 port;
+
+       if (!hw->func_caps.led[idx])
+               return 0;
+
+       gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx));
+       port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >>
+               I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
+
+       /* if PRT_NUM_NA is 1 then this LED is not port specific, OR
+        * if it is not our port then ignore
+        */
+       if ((gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK) ||
+           (port != hw->port))
+               return 0;
+
+       return gpio_val;
+}
+
+#define I40E_LED0 22
+#define I40E_LINK_ACTIVITY 0xC
+
 /**
  * i40e_led_get - return current on/off mode
  * @hw: pointer to the hw struct
@@ -411,24 +478,20 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw)
  **/
 u32 i40e_led_get(struct i40e_hw *hw)
 {
-       u32 gpio_val = 0;
        u32 mode = 0;
-       u32 port;
        int i;
 
-       for (i = 0; i < I40E_HW_CAP_MAX_GPIO; i++) {
-               if (!hw->func_caps.led[i])
-                       continue;
-
-               gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(i));
-               port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK)
-                       >> I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
+       /* as per the documentation GPIO 22-29 are the LED
+        * GPIO pins named LED0..LED7
+        */
+       for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) {
+               u32 gpio_val = i40e_led_is_mine(hw, i);
 
-               if (port != hw->port)
+               if (!gpio_val)
                        continue;
 
-               mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK)
-                               >> I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT;
+               mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) >>
+                       I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT;
                break;
        }
 
@@ -438,60 +501,45 @@ u32 i40e_led_get(struct i40e_hw *hw)
 /**
  * i40e_led_set - set new on/off mode
  * @hw: pointer to the hw struct
- * @mode: 0=off, else on (see EAS for mode details)
+ * @mode: 0=off, 0xf=on (else see manual for mode details)
+ * @blink: true if the LED should blink when on, false if steady
+ *
+ * if this function is used to turn on the blink it should
+ * be used to disable the blink when restoring the original state.
  **/
-void i40e_led_set(struct i40e_hw *hw, u32 mode)
+void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink)
 {
-       u32 gpio_val = 0;
-       u32 led_mode = 0;
-       u32 port;
        int i;
 
-       for (i = 0; i < I40E_HW_CAP_MAX_GPIO; i++) {
-               if (!hw->func_caps.led[i])
-                       continue;
+       if (mode & 0xfffffff0)
+               hw_dbg(hw, "invalid mode passed in %X\n", mode);
 
-               gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(i));
-               port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK)
-                       >> I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
+       /* as per the documentation GPIO 22-29 are the LED
+        * GPIO pins named LED0..LED7
+        */
+       for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) {
+               u32 gpio_val = i40e_led_is_mine(hw, i);
 
-               if (port != hw->port)
+               if (!gpio_val)
                        continue;
 
-               led_mode = (mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) &
-                           I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;
                gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;
-               gpio_val |= led_mode;
+               /* this & is a bit of paranoia, but serves as a range check */
+               gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) &
+                            I40E_GLGEN_GPIO_CTL_LED_MODE_MASK);
+
+               if (mode == I40E_LINK_ACTIVITY)
+                       blink = false;
+
+               gpio_val |= (blink ? 1 : 0) <<
+                           I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT;
+
                wr32(hw, I40E_GLGEN_GPIO_CTL(i), gpio_val);
+               break;
        }
 }
 
 /* Admin command wrappers */
-/**
- * i40e_aq_queue_shutdown
- * @hw: pointer to the hw struct
- * @unloading: is the driver unloading itself
- *
- * Tell the Firmware that we're shutting down the AdminQ and whether
- * or not the driver is unloading as well.
- **/
-i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw,
-                                            bool unloading)
-{
-       struct i40e_aq_desc desc;
-       struct i40e_aqc_queue_shutdown *cmd =
-               (struct i40e_aqc_queue_shutdown *)&desc.params.raw;
-       i40e_status status;
-
-       i40e_fill_default_direct_cmd_desc(&desc,
-                                         i40e_aqc_opc_queue_shutdown);
-
-       if (unloading)
-               cmd->driver_unloading = cpu_to_le32(I40E_AQ_DRIVER_UNLOADING);
-       status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL);
-
-       return status;
-}
 
 /**
  * i40e_aq_set_link_restart_an
@@ -552,8 +600,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
                goto aq_get_link_info_exit;
 
        /* save off old link status information */
-       memcpy(&hw->phy.link_info_old, hw_link_info,
-              sizeof(struct i40e_link_status));
+       hw->phy.link_info_old = *hw_link_info;
 
        /* update link status */
        hw_link_info->phy_type = (enum i40e_aq_phy_type)resp->phy_type;
@@ -583,7 +630,7 @@ aq_get_link_info_exit:
 /**
  * i40e_aq_add_vsi
  * @hw: pointer to the hw struct
- * @vsi: pointer to a vsi context struct
+ * @vsi_ctx: pointer to a vsi context struct
  * @cmd_details: pointer to command details structure or NULL
  *
  * Add a VSI context to the hardware.
@@ -635,7 +682,8 @@ aq_add_vsi_exit:
  * @cmd_details: pointer to command details structure or NULL
  **/
 i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
-                               u16 seid, bool set, struct i40e_asq_cmd_details *cmd_details)
+                               u16 seid, bool set,
+                               struct i40e_asq_cmd_details *cmd_details)
 {
        struct i40e_aq_desc desc;
        struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
@@ -729,7 +777,7 @@ i40e_status i40e_aq_set_vsi_broadcast(struct i40e_hw *hw,
 /**
  * i40e_get_vsi_params - get VSI configuration info
  * @hw: pointer to the hw struct
- * @vsi: pointer to a vsi context struct
+ * @vsi_ctx: pointer to a vsi context struct
  * @cmd_details: pointer to command details structure or NULL
  **/
 i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw,
@@ -737,8 +785,8 @@ i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw,
                                struct i40e_asq_cmd_details *cmd_details)
 {
        struct i40e_aq_desc desc;
-       struct i40e_aqc_switch_seid *cmd =
-               (struct i40e_aqc_switch_seid *)&desc.params.raw;
+       struct i40e_aqc_add_get_update_vsi *cmd =
+               (struct i40e_aqc_add_get_update_vsi *)&desc.params.raw;
        struct i40e_aqc_add_get_update_vsi_completion *resp =
                (struct i40e_aqc_add_get_update_vsi_completion *)
                &desc.params.raw;
@@ -747,7 +795,7 @@ i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw,
        i40e_fill_default_direct_cmd_desc(&desc,
                                          i40e_aqc_opc_get_vsi_parameters);
 
-       cmd->seid = cpu_to_le16(vsi_ctx->seid);
+       cmd->uplink_seid = cpu_to_le16(vsi_ctx->seid);
 
        desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
        if (sizeof(vsi_ctx->info) > I40E_AQ_LARGE_BUF)
@@ -771,7 +819,7 @@ aq_get_vsi_params_exit:
 /**
  * i40e_aq_update_vsi_params
  * @hw: pointer to the hw struct
- * @vsi: pointer to a vsi context struct
+ * @vsi_ctx: pointer to a vsi context struct
  * @cmd_details: pointer to command details structure or NULL
  *
  * Update a VSI context.
@@ -781,13 +829,13 @@ i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw,
                                struct i40e_asq_cmd_details *cmd_details)
 {
        struct i40e_aq_desc desc;
-       struct i40e_aqc_switch_seid *cmd =
-               (struct i40e_aqc_switch_seid *)&desc.params.raw;
+       struct i40e_aqc_add_get_update_vsi *cmd =
+               (struct i40e_aqc_add_get_update_vsi *)&desc.params.raw;
        i40e_status status;
 
        i40e_fill_default_direct_cmd_desc(&desc,
                                          i40e_aqc_opc_update_vsi_parameters);
-       cmd->seid = cpu_to_le16(vsi_ctx->seid);
+       cmd->uplink_seid = cpu_to_le16(vsi_ctx->seid);
 
        desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
        if (sizeof(vsi_ctx->info) > I40E_AQ_LARGE_BUF)
@@ -874,7 +922,6 @@ i40e_status i40e_aq_get_firmware_version(struct i40e_hw *hw,
 /**
  * i40e_aq_send_driver_version
  * @hw: pointer to the hw struct
- * @event: driver event: driver ok, start or stop
  * @dv: driver's major, minor version
  * @cmd_details: pointer to command details structure or NULL
  *
@@ -992,10 +1039,10 @@ i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid,
  * @hw: pointer to the hw struct
  * @veb_seid: the SEID of the VEB to query
  * @switch_id: the uplink switch id
- * @floating_veb: set to true if the VEB is floating
+ * @floating: set to true if the VEB is floating
  * @statistic_index: index of the stats counter block for this VEB
  * @vebs_used: number of VEB's used by function
- * @vebs_unallocated: total VEB's not reserved by any function
+ * @vebs_free: total VEB's not reserved by any function
  * @cmd_details: pointer to command details structure or NULL
  *
  * This retrieves the parameters for a particular VEB, specified by
@@ -1132,6 +1179,8 @@ i40e_status i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 seid,
  * i40e_aq_send_msg_to_vf
  * @hw: pointer to the hardware structure
  * @vfid: vf id to send msg
+ * @v_opcode: opcodes for VF-PF communication
+ * @v_retval: return error code
  * @msg: pointer to the msg buffer
  * @msglen: msg length
  * @cmd_details: pointer to command details
@@ -1670,6 +1719,64 @@ i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
        return status;
 }
 
+/**
+ * i40e_aq_add_udp_tunnel
+ * @hw: pointer to the hw struct
+ * @udp_port: the UDP port to add
+ * @header_len: length of the tunneling header length in DWords
+ * @protocol_index: protocol index type
+ * @filter_index: pointer to filter index
+ * @cmd_details: pointer to command details structure or NULL
+ **/
+i40e_status i40e_aq_add_udp_tunnel(struct i40e_hw *hw,
+                               u16 udp_port, u8 header_len,
+                               u8 protocol_index, u8 *filter_index,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_add_udp_tunnel *cmd =
+               (struct i40e_aqc_add_udp_tunnel *)&desc.params.raw;
+       struct i40e_aqc_del_udp_tunnel_completion *resp =
+               (struct i40e_aqc_del_udp_tunnel_completion *)&desc.params.raw;
+       i40e_status status;
+
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_udp_tunnel);
+
+       cmd->udp_port = cpu_to_le16(udp_port);
+       cmd->header_len = header_len;
+       cmd->protocol_type = protocol_index;
+
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       if (!status)
+               *filter_index = resp->index;
+
+       return status;
+}
+
+/**
+ * i40e_aq_del_udp_tunnel
+ * @hw: pointer to the hw struct
+ * @index: filter index
+ * @cmd_details: pointer to command details structure or NULL
+ **/
+i40e_status i40e_aq_del_udp_tunnel(struct i40e_hw *hw, u8 index,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_remove_udp_tunnel *cmd =
+               (struct i40e_aqc_remove_udp_tunnel *)&desc.params.raw;
+       i40e_status status;
+
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_del_udp_tunnel);
+
+       cmd->index = index;
+
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       return status;
+}
+
 /**
  * i40e_aq_delete_element - Delete switch element
  * @hw: pointer to the hw struct
@@ -2029,3 +2136,47 @@ i40e_status i40e_set_filter_control(struct i40e_hw *hw,
 
        return 0;
 }
+/**
+ * i40e_set_pci_config_data - store PCI bus info
+ * @hw: pointer to hardware structure
+ * @link_status: the link status word from PCI config space
+ *
+ * Stores the PCI bus info (speed, width, type) within the i40e_hw structure
+ **/
+void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status)
+{
+       hw->bus.type = i40e_bus_type_pci_express;
+
+       switch (link_status & PCI_EXP_LNKSTA_NLW) {
+       case PCI_EXP_LNKSTA_NLW_X1:
+               hw->bus.width = i40e_bus_width_pcie_x1;
+               break;
+       case PCI_EXP_LNKSTA_NLW_X2:
+               hw->bus.width = i40e_bus_width_pcie_x2;
+               break;
+       case PCI_EXP_LNKSTA_NLW_X4:
+               hw->bus.width = i40e_bus_width_pcie_x4;
+               break;
+       case PCI_EXP_LNKSTA_NLW_X8:
+               hw->bus.width = i40e_bus_width_pcie_x8;
+               break;
+       default:
+               hw->bus.width = i40e_bus_width_unknown;
+               break;
+       }
+
+       switch (link_status & PCI_EXP_LNKSTA_CLS) {
+       case PCI_EXP_LNKSTA_CLS_2_5GB:
+               hw->bus.speed = i40e_bus_speed_2500;
+               break;
+       case PCI_EXP_LNKSTA_CLS_5_0GB:
+               hw->bus.speed = i40e_bus_speed_5000;
+               break;
+       case PCI_EXP_LNKSTA_CLS_8_0GB:
+               hw->bus.speed = i40e_bus_speed_8000;
+               break;
+       default:
+               hw->bus.speed = i40e_bus_speed_unknown;
+               break;
+       }
+}
index e201060fe368a8b88dcb8bc6de978113b895b520..36a5cc89bf0b63a9aa3081f4fdeedc5ef923ec4e 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -192,12 +191,12 @@ static ssize_t i40e_dbg_dump_write(struct file *filp,
 
                        len = (sizeof(struct i40e_aq_desc)
                                        * pf->hw.aq.num_asq_entries);
-                       memcpy(p, pf->hw.aq.asq.desc, len);
+                       memcpy(p, pf->hw.aq.asq.desc_buf.va, len);
                        p += len;
 
                        len = (sizeof(struct i40e_aq_desc)
                                        * pf->hw.aq.num_arq_entries);
-                       memcpy(p, pf->hw.aq.arq.desc, len);
+                       memcpy(p, pf->hw.aq.arq.desc_buf.va, len);
                        p += len;
 
                        i40e_dbg_dump_data_len = buflen;
@@ -516,10 +515,10 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
                         rx_ring->stats.bytes,
                         rx_ring->rx_stats.non_eop_descs);
                dev_info(&pf->pdev->dev,
-                        "    rx_rings[%i]: rx_stats: alloc_rx_page_failed = %lld, alloc_rx_buff_failed = %lld\n",
+                        "    rx_rings[%i]: rx_stats: alloc_page_failed = %lld, alloc_buff_failed = %lld\n",
                         i,
-                        rx_ring->rx_stats.alloc_rx_page_failed,
-                       rx_ring->rx_stats.alloc_rx_buff_failed);
+                        rx_ring->rx_stats.alloc_page_failed,
+                        rx_ring->rx_stats.alloc_buff_failed);
                dev_info(&pf->pdev->dev,
                         "    rx_rings[%i]: size = %i, dma = 0x%08lx\n",
                         i, rx_ring->size,
@@ -533,6 +532,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
                struct i40e_ring *tx_ring = ACCESS_ONCE(vsi->tx_rings[i]);
                if (!tx_ring)
                        continue;
+
                dev_info(&pf->pdev->dev,
                         "    tx_rings[%i]: desc = %p\n",
                         i, tx_ring->desc);
@@ -1083,7 +1083,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                vsi = i40e_dbg_find_vsi(pf, vsi_seid);
                if (!vsi) {
                        dev_info(&pf->pdev->dev,
-                                "add relay: vsi VSI %d not found\n", vsi_seid);
+                                "add relay: VSI %d not found\n", vsi_seid);
                        goto command_write_done;
                }
 
@@ -1522,6 +1522,118 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                } else {
                        dev_info(&pf->pdev->dev, "clear_stats vsi [seid] or clear_stats pf\n");
                }
+       } else if (strncmp(cmd_buf, "send aq_cmd", 11) == 0) {
+               struct i40e_aq_desc *desc;
+               i40e_status ret;
+
+               desc = kzalloc(sizeof(struct i40e_aq_desc), GFP_KERNEL);
+               if (!desc)
+                       goto command_write_done;
+               cnt = sscanf(&cmd_buf[11],
+                            "%hx %hx %hx %hx %x %x %x %x %x %x",
+                            &desc->flags,
+                            &desc->opcode, &desc->datalen, &desc->retval,
+                            &desc->cookie_high, &desc->cookie_low,
+                            &desc->params.internal.param0,
+                            &desc->params.internal.param1,
+                            &desc->params.internal.param2,
+                            &desc->params.internal.param3);
+               if (cnt != 10) {
+                       dev_info(&pf->pdev->dev,
+                                "send aq_cmd: bad command string, cnt=%d\n",
+                                cnt);
+                       kfree(desc);
+                       desc = NULL;
+                       goto command_write_done;
+               }
+               ret = i40e_asq_send_command(&pf->hw, desc, NULL, 0, NULL);
+               if (!ret) {
+                       dev_info(&pf->pdev->dev, "AQ command sent Status : Success\n");
+               } else if (ret == I40E_ERR_ADMIN_QUEUE_ERROR) {
+                       dev_info(&pf->pdev->dev,
+                                "AQ command send failed Opcode %x AQ Error: %d\n",
+                                desc->opcode, pf->hw.aq.asq_last_status);
+               } else {
+                       dev_info(&pf->pdev->dev,
+                                "AQ command send failed Opcode %x Status: %d\n",
+                                desc->opcode, ret);
+               }
+               dev_info(&pf->pdev->dev,
+                        "AQ desc WB 0x%04x 0x%04x 0x%04x 0x%04x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                        desc->flags, desc->opcode, desc->datalen, desc->retval,
+                        desc->cookie_high, desc->cookie_low,
+                        desc->params.internal.param0,
+                        desc->params.internal.param1,
+                        desc->params.internal.param2,
+                        desc->params.internal.param3);
+               kfree(desc);
+               desc = NULL;
+       } else if (strncmp(cmd_buf, "send indirect aq_cmd", 20) == 0) {
+               struct i40e_aq_desc *desc;
+               i40e_status ret;
+               u16 buffer_len;
+               u8 *buff;
+
+               desc = kzalloc(sizeof(struct i40e_aq_desc), GFP_KERNEL);
+               if (!desc)
+                       goto command_write_done;
+               cnt = sscanf(&cmd_buf[20],
+                            "%hx %hx %hx %hx %x %x %x %x %x %x %hd",
+                            &desc->flags,
+                            &desc->opcode, &desc->datalen, &desc->retval,
+                            &desc->cookie_high, &desc->cookie_low,
+                            &desc->params.internal.param0,
+                            &desc->params.internal.param1,
+                            &desc->params.internal.param2,
+                            &desc->params.internal.param3,
+                            &buffer_len);
+               if (cnt != 11) {
+                       dev_info(&pf->pdev->dev,
+                                "send indirect aq_cmd: bad command string, cnt=%d\n",
+                                cnt);
+                       kfree(desc);
+                       desc = NULL;
+                       goto command_write_done;
+               }
+               /* Just stub a buffer big enough in case user messed up */
+               if (buffer_len == 0)
+                       buffer_len = 1280;
+
+               buff = kzalloc(buffer_len, GFP_KERNEL);
+               if (!buff) {
+                       kfree(desc);
+                       desc = NULL;
+                       goto command_write_done;
+               }
+               desc->flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
+               ret = i40e_asq_send_command(&pf->hw, desc, buff,
+                                           buffer_len, NULL);
+               if (!ret) {
+                       dev_info(&pf->pdev->dev, "AQ command sent Status : Success\n");
+               } else if (ret == I40E_ERR_ADMIN_QUEUE_ERROR) {
+                       dev_info(&pf->pdev->dev,
+                                "AQ command send failed Opcode %x AQ Error: %d\n",
+                                desc->opcode, pf->hw.aq.asq_last_status);
+               } else {
+                       dev_info(&pf->pdev->dev,
+                                "AQ command send failed Opcode %x Status: %d\n",
+                                desc->opcode, ret);
+               }
+               dev_info(&pf->pdev->dev,
+                        "AQ desc WB 0x%04x 0x%04x 0x%04x 0x%04x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                        desc->flags, desc->opcode, desc->datalen, desc->retval,
+                        desc->cookie_high, desc->cookie_low,
+                        desc->params.internal.param0,
+                        desc->params.internal.param1,
+                        desc->params.internal.param2,
+                        desc->params.internal.param3);
+               print_hex_dump(KERN_INFO, "AQ buffer WB: ",
+                              DUMP_PREFIX_OFFSET, 16, 1,
+                              buff, buffer_len, true);
+               kfree(buff);
+               buff = NULL;
+               kfree(desc);
+               desc = NULL;
        } else if ((strncmp(cmd_buf, "add fd_filter", 13) == 0) ||
                   (strncmp(cmd_buf, "rem fd_filter", 13) == 0)) {
                struct i40e_fdir_data fd_data;
@@ -1740,10 +1852,10 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                        dev_info(&pf->pdev->dev,
                                 "Read NVM module=0x%x offset=0x%x words=%d\n",
                                 module, offset, buffer_len);
-                       if (buffer_len)
+                       if (bytes)
                                print_hex_dump(KERN_INFO, "NVM Dump: ",
                                        DUMP_PREFIX_OFFSET, 16, 2,
-                                       buff, buffer_len, true);
+                                       buff, bytes, true);
                }
                kfree(buff);
                buff = NULL;
@@ -1773,6 +1885,8 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                dev_info(&pf->pdev->dev, "  pfr\n");
                dev_info(&pf->pdev->dev, "  corer\n");
                dev_info(&pf->pdev->dev, "  globr\n");
+               dev_info(&pf->pdev->dev, "  send aq_cmd <flags> <opcode> <datalen> <retval> <cookie_h> <cookie_l> <param0> <param1> <param2> <param3>\n");
+               dev_info(&pf->pdev->dev, "  send indirect aq_cmd <flags> <opcode> <datalen> <retval> <cookie_h> <cookie_l> <param0> <param1> <param2> <param3> <buffer_len>\n");
                dev_info(&pf->pdev->dev, "  add fd_filter <dest q_index> <flex_off> <pctype> <dest_vsi> <dest_ctl> <fd_status> <cnt_index> <fd_id> <packet_len> <packet>\n");
                dev_info(&pf->pdev->dev, "  rem fd_filter <dest q_index> <flex_off> <pctype> <dest_vsi> <dest_ctl> <fd_status> <cnt_index> <fd_id> <packet_len> <packet>\n");
                dev_info(&pf->pdev->dev, "  lldp start\n");
index 98c1ef563bf03e0ff0176521d86af12b46daad78..b2380daef8c142941f0bda2b7d11620f7de75ad5 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -70,9 +69,9 @@ struct i40e_diag_reg_test_info i40e_reg_list[] = {
        /* offset               mask         elements   stride */
        {I40E_QTX_CTL(0),       0x0000FFBF,   4, I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
        {I40E_PFINT_ITR0(0),    0x00000FFF,   3, I40E_PFINT_ITR0(1) - I40E_PFINT_ITR0(0)},
-       {I40E_PFINT_ITRN(0, 0), 0x00000FFF,  64, I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)},
-       {I40E_PFINT_ITRN(1, 0), 0x00000FFF,  64, I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)},
-       {I40E_PFINT_ITRN(2, 0), 0x00000FFF,  64, I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)},
+       {I40E_PFINT_ITRN(0, 0), 0x00000FFF,   8, I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)},
+       {I40E_PFINT_ITRN(1, 0), 0x00000FFF,   8, I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)},
+       {I40E_PFINT_ITRN(2, 0), 0x00000FFF,   8, I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)},
        {I40E_PFINT_STAT_CTL0,  0x0000000C,   1, 0},
        {I40E_PFINT_LNKLST0,    0x00001FFF,   1, 0},
        {I40E_PFINT_LNKLSTN(0), 0x000007FF,  64, I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)},
index d1fc68cd6c942b3e4f84302d71415b2e13132aa0..0b5911652084709e2c8ce1b25da296bfe487c81b 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
index d6681f6bf2913d586e09e51f44e06a18741ec107..7b87d5115816699ef17f28814b7f204a8eed39c9 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -109,6 +108,8 @@ static struct i40e_stats i40e_gstrings_stats[] = {
        I40E_PF_STAT("rx_oversize", stats.rx_oversize),
        I40E_PF_STAT("rx_jabber", stats.rx_jabber),
        I40E_PF_STAT("VF_admin_queue_requests", vf_aq_requests),
+       I40E_PF_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
+       I40E_PF_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
 };
 
 #define I40E_QUEUE_STATS_LEN(n) \
@@ -351,38 +352,56 @@ static int i40e_get_eeprom(struct net_device *netdev,
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_hw *hw = &np->vsi->back->hw;
-       int first_word, last_word;
-       u16 i, eeprom_len;
-       u16 *eeprom_buff;
-       int ret_val = 0;
-
+       struct i40e_pf *pf = np->vsi->back;
+       int ret_val = 0, len;
+       u8 *eeprom_buff;
+       u16 i, sectors;
+       bool last;
+#define I40E_NVM_SECTOR_SIZE  4096
        if (eeprom->len == 0)
                return -EINVAL;
 
        eeprom->magic = hw->vendor_id | (hw->device_id << 16);
 
-       first_word = eeprom->offset >> 1;
-       last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-       eeprom_len = last_word - first_word + 1;
-
-       eeprom_buff = kmalloc(sizeof(u16) * eeprom_len, GFP_KERNEL);
+       eeprom_buff = kzalloc(eeprom->len, GFP_KERNEL);
        if (!eeprom_buff)
                return -ENOMEM;
 
-       ret_val = i40e_read_nvm_buffer(hw, first_word, &eeprom_len,
-                                          eeprom_buff);
-       if (eeprom_len == 0) {
-               kfree(eeprom_buff);
-               return -EACCES;
+       ret_val = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+       if (ret_val) {
+               dev_info(&pf->pdev->dev,
+                        "Failed Acquiring NVM resource for read err=%d status=0x%x\n",
+                        ret_val, hw->aq.asq_last_status);
+               goto free_buff;
        }
 
-       /* Device's eeprom is always little-endian, word addressable */
-       for (i = 0; i < eeprom_len; i++)
-               le16_to_cpus(&eeprom_buff[i]);
+       sectors = eeprom->len / I40E_NVM_SECTOR_SIZE;
+       sectors += (eeprom->len % I40E_NVM_SECTOR_SIZE) ? 1 : 0;
+       len = I40E_NVM_SECTOR_SIZE;
+       last = false;
+       for (i = 0; i < sectors; i++) {
+               if (i == (sectors - 1)) {
+                       len = eeprom->len - (I40E_NVM_SECTOR_SIZE * i);
+                       last = true;
+               }
+               ret_val = i40e_aq_read_nvm(hw, 0x0,
+                               eeprom->offset + (I40E_NVM_SECTOR_SIZE * i),
+                               len,
+                               (u8 *)eeprom_buff + (I40E_NVM_SECTOR_SIZE * i),
+                               last, NULL);
+               if (ret_val) {
+                       dev_info(&pf->pdev->dev,
+                                "read NVM failed err=%d status=0x%x\n",
+                                ret_val, hw->aq.asq_last_status);
+                       goto release_nvm;
+               }
+       }
 
-       memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
+release_nvm:
+       i40e_release_nvm(hw);
+       memcpy(bytes, (u8 *)eeprom_buff, eeprom->len);
+free_buff:
        kfree(eeprom_buff);
-
        return ret_val;
 }
 
@@ -390,8 +409,14 @@ static int i40e_get_eeprom_len(struct net_device *netdev)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_hw *hw = &np->vsi->back->hw;
-
-       return hw->nvm.sr_size * 2;
+       u32 val;
+
+       val = (rd32(hw, I40E_GLPCI_LBARCTRL)
+               & I40E_GLPCI_LBARCTRL_FL_SIZE_MASK)
+               >> I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT;
+       /* register returns value in power of 2, 64Kbyte chunks. */
+       val = (64 * 1024) * (1 << val);
+       return val;
 }
 
 static void i40e_get_drvinfo(struct net_device *netdev,
@@ -725,7 +750,36 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
 static int i40e_get_ts_info(struct net_device *dev,
                            struct ethtool_ts_info *info)
 {
-       return ethtool_op_get_ts_info(dev, info);
+       struct i40e_pf *pf = i40e_netdev_to_pf(dev);
+
+       info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+                               SOF_TIMESTAMPING_RX_SOFTWARE |
+                               SOF_TIMESTAMPING_SOFTWARE |
+                               SOF_TIMESTAMPING_TX_HARDWARE |
+                               SOF_TIMESTAMPING_RX_HARDWARE |
+                               SOF_TIMESTAMPING_RAW_HARDWARE;
+
+       if (pf->ptp_clock)
+               info->phc_index = ptp_clock_index(pf->ptp_clock);
+       else
+               info->phc_index = -1;
+
+       info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+
+       info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+                          (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
+                          (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);
+
+       return 0;
 }
 
 static int i40e_link_test(struct net_device *netdev, u64 *data)
@@ -844,8 +898,45 @@ static void i40e_diag_test(struct net_device *netdev,
 static void i40e_get_wol(struct net_device *netdev,
                         struct ethtool_wolinfo *wol)
 {
-       wol->supported = 0;
-       wol->wolopts = 0;
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+       struct i40e_hw *hw = &pf->hw;
+       u16 wol_nvm_bits;
+
+       /* NVM bit on means WoL disabled for the port */
+       i40e_read_nvm_word(hw, I40E_SR_NVM_WAKE_ON_LAN, &wol_nvm_bits);
+       if ((1 << hw->port) & wol_nvm_bits) {
+               wol->supported = 0;
+               wol->wolopts = 0;
+       } else {
+               wol->supported = WAKE_MAGIC;
+               wol->wolopts = (pf->wol_en ? WAKE_MAGIC : 0);
+       }
+}
+
+static int i40e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+       struct i40e_hw *hw = &pf->hw;
+       u16 wol_nvm_bits;
+
+       /* NVM bit on means WoL disabled for the port */
+       i40e_read_nvm_word(hw, I40E_SR_NVM_WAKE_ON_LAN, &wol_nvm_bits);
+       if (((1 << hw->port) & wol_nvm_bits))
+               return -EOPNOTSUPP;
+
+       /* only magic packet is supported */
+       if (wol->wolopts && (wol->wolopts != WAKE_MAGIC))
+               return -EOPNOTSUPP;
+
+       /* is this a new value? */
+       if (pf->wol_en != !!wol->wolopts) {
+               pf->wol_en = !!wol->wolopts;
+               device_set_wakeup_enable(&pf->pdev->dev, pf->wol_en);
+       }
+
+       return 0;
 }
 
 static int i40e_nway_reset(struct net_device *netdev)
@@ -879,13 +970,13 @@ static int i40e_set_phys_id(struct net_device *netdev,
                pf->led_status = i40e_led_get(hw);
                return blink_freq;
        case ETHTOOL_ID_ON:
-               i40e_led_set(hw, 0xF);
+               i40e_led_set(hw, 0xF, false);
                break;
        case ETHTOOL_ID_OFF:
-               i40e_led_set(hw, 0x0);
+               i40e_led_set(hw, 0x0, false);
                break;
        case ETHTOOL_ID_INACTIVE:
-               i40e_led_set(hw, pf->led_status);
+               i40e_led_set(hw, pf->led_status, false);
                break;
        }
 
@@ -1183,6 +1274,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
 }
 
 #define IP_HEADER_OFFSET 14
+#define I40E_UDPIP_DUMMY_PACKET_LEN 42
 /**
  * i40e_add_del_fdir_udpv4 - Add/Remove UDPv4 Flow Director filters for
  * a specific flow spec
@@ -1203,6 +1295,12 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
        bool err = false;
        int ret;
        int i;
+       char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
+                        0x45, 0, 0, 0x1c, 0, 0, 0x40, 0, 0x40, 0x11,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0};
+
+       memcpy(fd_data->raw_packet, packet, I40E_UDPIP_DUMMY_PACKET_LEN);
 
        ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET);
        udp = (struct udphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET
@@ -1233,6 +1331,7 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
        return err ? -EOPNOTSUPP : 0;
 }
 
+#define I40E_TCPIP_DUMMY_PACKET_LEN 54
 /**
  * i40e_add_del_fdir_tcpv4 - Add/Remove TCPv4 Flow Director filters for
  * a specific flow spec
@@ -1252,6 +1351,14 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
        struct iphdr *ip;
        bool err = false;
        int ret;
+       /* Dummy packet */
+       char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
+                        0x45, 0, 0, 0x28, 0, 0, 0x40, 0, 0x40, 0x6,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0x80, 0x11, 0x0, 0x72, 0, 0, 0, 0};
+
+       memcpy(fd_data->raw_packet, packet, I40E_TCPIP_DUMMY_PACKET_LEN);
 
        ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET);
        tcp = (struct tcphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET
@@ -1259,6 +1366,8 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
 
        ip->daddr = fsp->h_u.tcp_ip4_spec.ip4dst;
        tcp->dest = fsp->h_u.tcp_ip4_spec.pdst;
+       ip->saddr = fsp->h_u.tcp_ip4_spec.ip4src;
+       tcp->source = fsp->h_u.tcp_ip4_spec.psrc;
 
        fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN;
        ret = i40e_program_fdir_filter(fd_data, pf, add);
@@ -1273,9 +1382,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
                         fd_data->pctype, ret);
        }
 
-       ip->saddr = fsp->h_u.tcp_ip4_spec.ip4src;
-       tcp->source = fsp->h_u.tcp_ip4_spec.psrc;
-
        fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
 
        ret = i40e_program_fdir_filter(fd_data, pf, add);
@@ -1309,6 +1415,7 @@ static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
        return -EOPNOTSUPP;
 }
 
+#define I40E_IP_DUMMY_PACKET_LEN 34
 /**
  * i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for
  * a specific flow spec
@@ -1328,7 +1435,11 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
        bool err = false;
        int ret;
        int i;
+       char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
+                        0x45, 0, 0, 0x14, 0, 0, 0x40, 0, 0x40, 0x10,
+                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
+       memcpy(fd_data->raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN);
        ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET);
 
        ip->saddr = fsp->h_u.usr_ip4_spec.ip4src;
@@ -1554,7 +1665,7 @@ static int i40e_set_channels(struct net_device *dev,
         * class queue mapping
         */
        new_count = i40e_reconfig_rss_queues(pf, count);
-       if (new_count > 1)
+       if (new_count > 0)
                return 0;
        else
                return -EINVAL;
@@ -1568,6 +1679,7 @@ static const struct ethtool_ops i40e_ethtool_ops = {
        .nway_reset             = i40e_nway_reset,
        .get_link               = ethtool_op_get_link,
        .get_wol                = i40e_get_wol,
+       .set_wol                = i40e_set_wol,
        .get_eeprom_len         = i40e_get_eeprom_len,
        .get_eeprom             = i40e_get_eeprom,
        .get_ringparam          = i40e_get_ringparam,
index bcedf3fb11431dd567d62f8075b6fc1e114625a1..bf2d4cc5b56927e87a1be2cd5772198533d27afa 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -90,11 +89,9 @@ i40e_status i40e_add_sd_table_entry(struct i40e_hw *hw,
                        sd_entry->u.pd_table.pd_entry =
                                (struct i40e_hmc_pd_entry *)
                                sd_entry->u.pd_table.pd_entry_virt_mem.va;
-                       memcpy(&sd_entry->u.pd_table.pd_page_addr, &mem,
-                              sizeof(struct i40e_dma_mem));
+                       sd_entry->u.pd_table.pd_page_addr = mem;
                } else {
-                       memcpy(&sd_entry->u.bp.addr, &mem,
-                              sizeof(struct i40e_dma_mem));
+                       sd_entry->u.bp.addr = mem;
                        sd_entry->u.bp.sd_pd_index = sd_index;
                }
                /* initialize the sd entry */
@@ -165,7 +162,7 @@ i40e_status i40e_add_pd_table_entry(struct i40e_hw *hw,
                if (ret_code)
                        goto exit;
 
-               memcpy(&pd_entry->bp.addr, &mem, sizeof(struct i40e_dma_mem));
+               pd_entry->bp.addr = mem;
                pd_entry->bp.sd_pd_index = pd_index;
                pd_entry->bp.entry_type = I40E_SD_TYPE_PAGED;
                /* Set page address and valid bit */
index aacd42a261e93f6269e4db56139645fe2b98e31d..0cd4701234f8c0fc41f64e926640fca1a5ad9757 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -117,7 +116,6 @@ struct i40e_hmc_info {
  * @hw: pointer to our hw struct
  * @pa: pointer to physical address
  * @sd_index: segment descriptor index
- * @hmc_fn_id: hmc function id
  * @type: if sd entry is direct or paged
  **/
 #define I40E_SET_PF_SD_ENTRY(hw, pa, sd_index, type)                   \
@@ -139,7 +137,6 @@ struct i40e_hmc_info {
  * I40E_CLEAR_PF_SD_ENTRY - marks the sd entry as invalid in the hardware
  * @hw: pointer to our hw struct
  * @sd_index: segment descriptor index
- * @hmc_fn_id: hmc function id
  * @type: if sd entry is direct or paged
  **/
 #define I40E_CLEAR_PF_SD_ENTRY(hw, sd_index, type)                     \
@@ -160,7 +157,6 @@ struct i40e_hmc_info {
  * @hw: pointer to our hw struct
  * @sd_idx: segment descriptor index
  * @pd_idx: page descriptor index
- * @hmc_fn_id: hmc function id
  **/
 #define I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, pd_idx)                  \
        wr32((hw), I40E_PFHMC_PDINV,                                    \
index a695b91c9c79ed7dc3b3b54003595b9921edd04b..101ed41073120efbfd9f3fc5ca127b6113cea9cb 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
index f8afbcb053c539d58ea4034fed2fcd5908846193..341de925a2983181a1cd7d7f18d59996fd128158 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
index efdf8a261b9a4e4ade4fbb667efec8ea940f74a6..ad04da288f5d291a70c595b70c44875590b33b92 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -27,6 +26,9 @@
 
 /* Local includes */
 #include "i40e.h"
+#ifdef CONFIG_I40E_VXLAN
+#include <net/vxlan.h>
+#endif
 
 const char i40e_driver_name[] = "i40e";
 static const char i40e_driver_string[] =
@@ -36,7 +38,7 @@ static const char i40e_driver_string[] =
 
 #define DRV_VERSION_MAJOR 0
 #define DRV_VERSION_MINOR 3
-#define DRV_VERSION_BUILD 14
+#define DRV_VERSION_BUILD 28
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
             __stringify(DRV_VERSION_MINOR) "." \
             __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -420,7 +422,7 @@ void i40e_vsi_reset_stats(struct i40e_vsi *vsi)
        memset(&vsi->net_stats_offsets, 0, sizeof(vsi->net_stats_offsets));
        memset(&vsi->eth_stats, 0, sizeof(vsi->eth_stats));
        memset(&vsi->eth_stats_offsets, 0, sizeof(vsi->eth_stats_offsets));
-       if (vsi->rx_rings)
+       if (vsi->rx_rings && vsi->rx_rings[0]) {
                for (i = 0; i < vsi->num_queue_pairs; i++) {
                        memset(&vsi->rx_rings[i]->stats, 0 ,
                               sizeof(vsi->rx_rings[i]->stats));
@@ -431,6 +433,7 @@ void i40e_vsi_reset_stats(struct i40e_vsi *vsi)
                        memset(&vsi->tx_rings[i]->tx_stats, 0,
                               sizeof(vsi->tx_rings[i]->tx_stats));
                }
+       }
        vsi->stat_offsets_loaded = false;
 }
 
@@ -783,8 +786,8 @@ void i40e_update_stats(struct i40e_vsi *vsi)
                } while (u64_stats_fetch_retry_bh(&p->syncp, start));
                rx_b += bytes;
                rx_p += packets;
-               rx_buf += p->rx_stats.alloc_rx_buff_failed;
-               rx_page += p->rx_stats.alloc_rx_page_failed;
+               rx_buf += p->rx_stats.alloc_buff_failed;
+               rx_page += p->rx_stats.alloc_page_failed;
        }
        rcu_read_unlock();
        vsi->tx_restart = tx_restart;
@@ -1212,6 +1215,10 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
        if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
                return 0;
 
+       if (test_bit(__I40E_DOWN, &vsi->back->state) ||
+           test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
+               return -EADDRNOTAVAIL;
+
        if (vsi->type == I40E_VSI_MAIN) {
                i40e_status ret;
                ret = i40e_aq_mac_address_write(&vsi->back->hw,
@@ -1502,11 +1509,6 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                                cpu_to_le16((u16)(f->vlan ==
                                            I40E_VLAN_ANY ? 0 : f->vlan));
 
-                       /* vlan0 as wild card to allow packets from all vlans */
-                       if (f->vlan == I40E_VLAN_ANY ||
-                           (vsi->netdev && !(vsi->netdev->features &
-                                             NETIF_F_HW_VLAN_CTAG_FILTER)))
-                               cmd_flags |= I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
                        cmd_flags |= I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
                        del_list[num_del].flags = cmd_flags;
                        num_del++;
@@ -1572,12 +1574,6 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                        add_list[num_add].queue_number = 0;
 
                        cmd_flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
-
-                       /* vlan0 as wild card to allow packets from all vlans */
-                       if (f->vlan == I40E_VLAN_ANY || (vsi->netdev &&
-                           !(vsi->netdev->features &
-                                                NETIF_F_HW_VLAN_CTAG_FILTER)))
-                               cmd_flags |= I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
                        add_list[num_add].flags = cpu_to_le16(cmd_flags);
                        num_add++;
 
@@ -1643,6 +1639,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                        dev_info(&pf->pdev->dev,
                                 "set uni promisc failed, err %d, aq_err %d\n",
                                 aq_ret, pf->hw.aq.asq_last_status);
+               aq_ret = i40e_aq_set_vsi_broadcast(&vsi->back->hw,
+                                                  vsi->seid,
+                                                  cur_promisc, NULL);
+               if (aq_ret)
+                       dev_info(&pf->pdev->dev,
+                                "set brdcast promisc failed, err %d, aq_err %d\n",
+                                aq_ret, pf->hw.aq.asq_last_status);
        }
 
        clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
@@ -1694,6 +1697,27 @@ static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
        return 0;
 }
 
+/**
+ * i40e_ioctl - Access the hwtstamp interface
+ * @netdev: network interface device structure
+ * @ifr: interface request data
+ * @cmd: ioctl command
+ **/
+int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+
+       switch (cmd) {
+       case SIOCGHWTSTAMP:
+               return i40e_ptp_get_ts_config(pf, ifr);
+       case SIOCSHWTSTAMP:
+               return i40e_ptp_set_ts_config(pf, ifr);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
 /**
  * i40e_vlan_stripping_enable - Turn on vlan stripping for the VSI
  * @vsi: the vsi being adjusted
@@ -1776,7 +1800,6 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
 {
        struct i40e_mac_filter *f, *add_f;
        bool is_netdev, is_vf;
-       int ret;
 
        is_vf = (vsi->type == I40E_VSI_SRIOV);
        is_netdev = !!(vsi->netdev);
@@ -1802,13 +1825,6 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
                }
        }
 
-       ret = i40e_sync_vsi_filters(vsi);
-       if (ret) {
-               dev_info(&vsi->back->pdev->dev,
-                        "Could not sync filters for vid %d\n", vid);
-               return ret;
-       }
-
        /* Now if we add a vlan tag, make sure to check if it is the first
         * tag (i.e. a "tag" -1 does exist) and if so replace the -1 "tag"
         * with 0, so we now accept untagged and specified tagged traffic
@@ -1845,10 +1861,13 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
                                }
                        }
                }
-               ret = i40e_sync_vsi_filters(vsi);
        }
 
-       return ret;
+       if (test_bit(__I40E_DOWN, &vsi->back->state) ||
+           test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
+               return 0;
+
+       return i40e_sync_vsi_filters(vsi);
 }
 
 /**
@@ -1864,7 +1883,6 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
        struct i40e_mac_filter *f, *add_f;
        bool is_vf, is_netdev;
        int filter_count = 0;
-       int ret;
 
        is_vf = (vsi->type == I40E_VSI_SRIOV);
        is_netdev = !!(netdev);
@@ -1875,12 +1893,6 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
        list_for_each_entry(f, &vsi->mac_filter_list, list)
                i40e_del_filter(vsi, f->macaddr, vid, is_vf, is_netdev);
 
-       ret = i40e_sync_vsi_filters(vsi);
-       if (ret) {
-               dev_info(&vsi->back->pdev->dev, "Could not sync filters\n");
-               return ret;
-       }
-
        /* go through all the filters for this VSI and if there is only
         * vid == 0 it means there are no other filters, so vid 0 must
         * be replaced with -1. This signifies that we should from now
@@ -1923,6 +1935,10 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
                }
        }
 
+       if (test_bit(__I40E_DOWN, &vsi->back->state) ||
+           test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
+               return 0;
+
        return i40e_sync_vsi_filters(vsi);
 }
 
@@ -2013,8 +2029,9 @@ int i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid)
 
        vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
        vsi->info.pvid = cpu_to_le16(vid);
-       vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
-       vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
+       vsi->info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_TAGGED |
+                                   I40E_AQ_VSI_PVLAN_INSERT_PVID |
+                                   I40E_AQ_VSI_PVLAN_EMOD_STR;
 
        ctxt.seid = vsi->seid;
        memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
@@ -2037,8 +2054,9 @@ int i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid)
  **/
 void i40e_vsi_remove_pvid(struct i40e_vsi *vsi)
 {
+       i40e_vlan_stripping_disable(vsi);
+
        vsi->info.pvid = 0;
-       i40e_vlan_rx_register(vsi->netdev, vsi->netdev->features);
 }
 
 /**
@@ -2071,8 +2089,11 @@ static void i40e_vsi_free_tx_resources(struct i40e_vsi *vsi)
 {
        int i;
 
+       if (!vsi->tx_rings)
+               return;
+
        for (i = 0; i < vsi->num_queue_pairs; i++)
-               if (vsi->tx_rings[i]->desc)
+               if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc)
                        i40e_free_tx_resources(vsi->tx_rings[i]);
 }
 
@@ -2105,8 +2126,11 @@ static void i40e_vsi_free_rx_resources(struct i40e_vsi *vsi)
 {
        int i;
 
+       if (!vsi->rx_rings)
+               return;
+
        for (i = 0; i < vsi->num_queue_pairs; i++)
-               if (vsi->rx_rings[i]->desc)
+               if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc)
                        i40e_free_rx_resources(vsi->rx_rings[i]);
 }
 
@@ -2147,7 +2171,8 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
        tx_ctx.base = (ring->dma / 128);
        tx_ctx.qlen = ring->count;
        tx_ctx.fd_ena = !!(vsi->back->flags & (I40E_FLAG_FDIR_ENABLED |
-                       I40E_FLAG_FDIR_ATR_ENABLED));
+                                              I40E_FLAG_FDIR_ATR_ENABLED));
+       tx_ctx.timesync_ena = !!(vsi->back->flags & I40E_FLAG_PTP);
 
        /* As part of VSI creation/update, FW allocates certain
         * Tx arbitration queue sets for each TC enabled for
@@ -2485,6 +2510,7 @@ static void i40e_enable_misc_int_causes(struct i40e_hw *hw)
              I40E_PFINT_ICR0_ENA_GRST_MASK          |
              I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK |
              I40E_PFINT_ICR0_ENA_GPIO_MASK          |
+             I40E_PFINT_ICR0_ENA_TIMESYNC_MASK      |
              I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK  |
              I40E_PFINT_ICR0_ENA_HMC_ERR_MASK       |
              I40E_PFINT_ICR0_ENA_VFLR_MASK          |
@@ -2539,6 +2565,19 @@ static void i40e_configure_msi_and_legacy(struct i40e_vsi *vsi)
        i40e_flush(hw);
 }
 
+/**
+ * i40e_irq_dynamic_disable_icr0 - Disable default interrupt generation for icr0
+ * @pf: board private structure
+ **/
+void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf)
+{
+       struct i40e_hw *hw = &pf->hw;
+
+       wr32(hw, I40E_PFINT_DYN_CTL0,
+            I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
+       i40e_flush(hw);
+}
+
 /**
  * i40e_irq_dynamic_enable_icr0 - Enable default interrupt generation for icr0
  * @pf: board private structure
@@ -2748,20 +2787,16 @@ static irqreturn_t i40e_intr(int irq, void *data)
 {
        struct i40e_pf *pf = (struct i40e_pf *)data;
        struct i40e_hw *hw = &pf->hw;
+       irqreturn_t ret = IRQ_NONE;
        u32 icr0, icr0_remaining;
        u32 val, ena_mask;
 
        icr0 = rd32(hw, I40E_PFINT_ICR0);
-
-       val = rd32(hw, I40E_PFINT_DYN_CTL0);
-       val = val | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK;
-       wr32(hw, I40E_PFINT_DYN_CTL0, val);
+       ena_mask = rd32(hw, I40E_PFINT_ICR0_ENA);
 
        /* if sharing a legacy IRQ, we might get called w/o an intr pending */
        if ((icr0 & I40E_PFINT_ICR0_INTEVENT_MASK) == 0)
-               return IRQ_NONE;
-
-       ena_mask = rd32(hw, I40E_PFINT_ICR0_ENA);
+               goto enable_intr;
 
        /* if interrupt but no bits showing, must be SWINT */
        if (((icr0 & ~I40E_PFINT_ICR0_INTEVENT_MASK) == 0) ||
@@ -2814,6 +2849,23 @@ static irqreturn_t i40e_intr(int irq, void *data)
                        pf->empr_count++;
        }
 
+       if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK) {
+               icr0 &= ~I40E_PFINT_ICR0_HMC_ERR_MASK;
+               dev_info(&pf->pdev->dev, "HMC error interrupt\n");
+       }
+
+       if (icr0 & I40E_PFINT_ICR0_TIMESYNC_MASK) {
+               u32 prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_0);
+
+               if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK) {
+                       ena_mask &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
+                       i40e_ptp_tx_hwtstamp(pf);
+                       prttsyn_stat &= ~I40E_PRTTSYN_STAT_0_TXTIME_MASK;
+               }
+
+               wr32(hw, I40E_PRTTSYN_STAT_0, prttsyn_stat);
+       }
+
        /* If a critical error is pending we have no choice but to reset the
         * device.
         * Report and mask out any remaining unexpected interrupts.
@@ -2822,22 +2874,19 @@ static irqreturn_t i40e_intr(int irq, void *data)
        if (icr0_remaining) {
                dev_info(&pf->pdev->dev, "unhandled interrupt icr0=0x%08x\n",
                         icr0_remaining);
-               if ((icr0_remaining & I40E_PFINT_ICR0_HMC_ERR_MASK) ||
-                   (icr0_remaining & I40E_PFINT_ICR0_PE_CRITERR_MASK) ||
+               if ((icr0_remaining & I40E_PFINT_ICR0_PE_CRITERR_MASK) ||
                    (icr0_remaining & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK) ||
                    (icr0_remaining & I40E_PFINT_ICR0_ECC_ERR_MASK) ||
                    (icr0_remaining & I40E_PFINT_ICR0_MAL_DETECT_MASK)) {
-                       if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK) {
-                               dev_info(&pf->pdev->dev, "HMC error interrupt\n");
-                       } else {
-                               dev_info(&pf->pdev->dev, "device will be reset\n");
-                               set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
-                               i40e_service_event_schedule(pf);
-                       }
+                       dev_info(&pf->pdev->dev, "device will be reset\n");
+                       set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
+                       i40e_service_event_schedule(pf);
                }
                ena_mask &= ~icr0_remaining;
        }
+       ret = IRQ_HANDLED;
 
+enable_intr:
        /* re-enable interrupt causes */
        wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask);
        if (!test_bit(__I40E_DOWN, &pf->state)) {
@@ -2845,7 +2894,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
                i40e_irq_dynamic_enable_icr0(pf);
        }
 
-       return IRQ_HANDLED;
+       return ret;
 }
 
 /**
@@ -2987,28 +3036,20 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
                } while (j-- && ((tx_reg >> I40E_QTX_ENA_QENA_REQ_SHIFT)
                               ^ (tx_reg >> I40E_QTX_ENA_QENA_STAT_SHIFT)) & 1);
 
-               if (enable) {
-                       /* is STAT set ? */
-                       if ((tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) {
-                               dev_info(&pf->pdev->dev,
-                                        "Tx %d already enabled\n", i);
-                               continue;
-                       }
-               } else {
-                       /* is !STAT set ? */
-                       if (!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) {
-                               dev_info(&pf->pdev->dev,
-                                        "Tx %d already disabled\n", i);
-                               continue;
-                       }
-               }
+               /* Skip if the queue is already in the requested state */
+               if (enable && (tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
+                       continue;
+               if (!enable && !(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
+                       continue;
 
                /* turn on/off the queue */
-               if (enable)
+               if (enable) {
+                       wr32(hw, I40E_QTX_HEAD(pf_q), 0);
                        tx_reg |= I40E_QTX_ENA_QENA_REQ_MASK |
                                  I40E_QTX_ENA_QENA_STAT_MASK;
-               else
+               } else {
                        tx_reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
+               }
 
                wr32(hw, I40E_QTX_ENA(pf_q), tx_reg);
 
@@ -3107,9 +3148,9 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
  * @vsi: the VSI being configured
  * @enable: start or stop the rings
  **/
-static int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool request)
+int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool request)
 {
-       int ret;
+       int ret = 0;
 
        /* do rx first for enable and last for disable */
        if (request) {
@@ -3118,10 +3159,9 @@ static int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool request)
                        return ret;
                ret = i40e_vsi_control_tx(vsi, request);
        } else {
-               ret = i40e_vsi_control_tx(vsi, request);
-               if (ret)
-                       return ret;
-               ret = i40e_vsi_control_rx(vsi, request);
+               /* Ignore return value, we need to shutdown whatever we can */
+               i40e_vsi_control_tx(vsi, request);
+               i40e_vsi_control_rx(vsi, request);
        }
 
        return ret;
@@ -3147,7 +3187,8 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi)
                        u16 vector = i + base;
 
                        /* free only the irqs that were actually requested */
-                       if (vsi->q_vectors[i]->num_ringpairs == 0)
+                       if (!vsi->q_vectors[i] ||
+                           !vsi->q_vectors[i]->num_ringpairs)
                                continue;
 
                        /* clear the affinity_mask in the IRQ descriptor */
@@ -3974,11 +4015,11 @@ static int i40e_open(struct net_device *netdev)
                goto err_setup_rx;
 
        /* Notify the stack of the actual queue counts. */
-       err = netif_set_real_num_tx_queues(netdev, pf->num_tx_queues);
+       err = netif_set_real_num_tx_queues(netdev, vsi->num_queue_pairs);
        if (err)
                goto err_set_queues;
 
-       err = netif_set_real_num_rx_queues(netdev, pf->num_rx_queues);
+       err = netif_set_real_num_rx_queues(netdev, vsi->num_queue_pairs);
        if (err)
                goto err_set_queues;
 
@@ -3986,13 +4027,9 @@ static int i40e_open(struct net_device *netdev)
        if (err)
                goto err_up_complete;
 
-       if ((vsi->type == I40E_VSI_MAIN) || (vsi->type == I40E_VSI_VMDQ2)) {
-               err = i40e_aq_set_vsi_broadcast(&pf->hw, vsi->seid, true, NULL);
-               if (err)
-                       netdev_info(netdev,
-                                   "couldn't set broadcast err %d aq_err %d\n",
-                                   err, pf->hw.aq.asq_last_status);
-       }
+#ifdef CONFIG_I40E_VXLAN
+       vxlan_get_rx_port(netdev);
+#endif
 
        return 0;
 
@@ -4302,6 +4339,9 @@ static void i40e_link_event(struct i40e_pf *pf)
 
        if (pf->vf)
                i40e_vc_notify_link_state(pf);
+
+       if (pf->flags & I40E_FLAG_PTP)
+               i40e_ptp_set_increment(pf);
 }
 
 /**
@@ -4383,6 +4423,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
        for (i = 0; i < I40E_MAX_VEB; i++)
                if (pf->veb[i])
                        i40e_update_veb_stats(pf->veb[i]);
+
+       i40e_ptp_rx_hang(pf->vsi[pf->lan_vsi]);
 }
 
 /**
@@ -4490,6 +4532,7 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf)
                return;
 
        do {
+               event.msg_size = I40E_MAX_AQ_BUF_SIZE; /* reinit each time */
                ret = i40e_clean_arq_element(hw, &event, &pending);
                if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) {
                        dev_info(&pf->pdev->dev, "No ARQ event found\n");
@@ -4520,10 +4563,13 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf)
                        dev_info(&pf->pdev->dev, "ARQ LAN queue overflow event received\n");
                        i40e_handle_lan_overflow_event(pf, &event);
                        break;
+               case i40e_aqc_opc_send_msg_to_peer:
+                       dev_info(&pf->pdev->dev, "ARQ: Msg from other pf\n");
+                       break;
                default:
                        dev_info(&pf->pdev->dev,
-                                "ARQ Error: Unknown event %d received\n",
-                                event.desc.opcode);
+                                "ARQ Error: Unknown event 0x%04x received\n",
+                                opcode);
                        break;
                }
        } while (pending && (i++ < pf->adminq_work_limit));
@@ -4653,7 +4699,7 @@ static int i40e_get_capabilities(struct i40e_pf *pf)
                }
        } while (err);
 
-       if (pf->hw.revision_id == 0 && pf->hw.func_caps.npar_enable) {
+       if (pf->hw.revision_id == 0 && (pf->flags & I40E_FLAG_MFP_ENABLED)) {
                pf->hw.func_caps.num_msix_vectors += 1;
                pf->hw.func_caps.num_tx_qp =
                        min_t(int, pf->hw.func_caps.num_tx_qp,
@@ -4767,7 +4813,8 @@ static int i40e_prep_for_reset(struct i40e_pf *pf)
 
        dev_info(&pf->pdev->dev, "Tearing down internal switch for reset\n");
 
-       i40e_vc_notify_reset(pf);
+       if (i40e_check_asq_alive(hw))
+               i40e_vc_notify_reset(pf);
 
        /* quiesce the VSIs and their queues that are not already DOWN */
        i40e_pf_quiesce_all_vsi(pf);
@@ -4789,7 +4836,7 @@ static int i40e_prep_for_reset(struct i40e_pf *pf)
 }
 
 /**
- * i40e_reset_and_rebuild - reset and rebuid using a saved config
+ * i40e_reset_and_rebuild - reset and rebuild using a saved config
  * @pf: board private structure
  * @reinit: if the Main VSI needs to re-initialized.
  **/
@@ -5016,6 +5063,52 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
        i40e_flush(hw);
 }
 
+#ifdef CONFIG_I40E_VXLAN
+/**
+ * i40e_sync_vxlan_filters_subtask - Sync the VSI filter list with HW
+ * @pf: board private structure
+ **/
+static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf)
+{
+       const int vxlan_hdr_qwords = 4;
+       struct i40e_hw *hw = &pf->hw;
+       i40e_status ret;
+       u8 filter_index;
+       __be16 port;
+       int i;
+
+       if (!(pf->flags & I40E_FLAG_VXLAN_FILTER_SYNC))
+               return;
+
+       pf->flags &= ~I40E_FLAG_VXLAN_FILTER_SYNC;
+
+       for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
+               if (pf->pending_vxlan_bitmap & (1 << i)) {
+                       pf->pending_vxlan_bitmap &= ~(1 << i);
+                       port = pf->vxlan_ports[i];
+                       ret = port ?
+                             i40e_aq_add_udp_tunnel(hw, ntohs(port),
+                                                    vxlan_hdr_qwords,
+                                                    I40E_AQC_TUNNEL_TYPE_VXLAN,
+                                                    &filter_index, NULL)
+                             : i40e_aq_del_udp_tunnel(hw, i, NULL);
+
+                       if (ret) {
+                               dev_info(&pf->pdev->dev, "Failed to execute AQ command for %s port %d with index %d\n",
+                                        port ? "adding" : "deleting",
+                                        ntohs(port), port ? i : i);
+
+                               pf->vxlan_ports[i] = 0;
+                       } else {
+                               dev_info(&pf->pdev->dev, "%s port %d with AQ command with index %d\n",
+                                        port ? "Added" : "Deleted",
+                                        ntohs(port), port ? i : filter_index);
+                       }
+               }
+       }
+}
+
+#endif
 /**
  * i40e_service_task - Run the driver's async subtasks
  * @work: pointer to work_struct containing our data
@@ -5034,6 +5127,9 @@ static void i40e_service_task(struct work_struct *work)
        i40e_fdir_reinit_subtask(pf);
        i40e_check_hang_subtask(pf);
        i40e_sync_filters_subtask(pf);
+#ifdef CONFIG_I40E_VXLAN
+       i40e_sync_vxlan_filters_subtask(pf);
+#endif
        i40e_clean_adminq_subtask(pf);
 
        i40e_service_event_complete(pf);
@@ -5300,18 +5396,17 @@ free_vsi:
  * i40e_vsi_clear_rings - Deallocates the Rx and Tx rings for the provided VSI
  * @vsi: the VSI being cleaned
  **/
-static s32 i40e_vsi_clear_rings(struct i40e_vsi *vsi)
+static void i40e_vsi_clear_rings(struct i40e_vsi *vsi)
 {
        int i;
 
-       if (vsi->tx_rings[0])
-               for (i = 0; i < vsi->num_queue_pairs; i++) {
+       if (vsi->tx_rings && vsi->tx_rings[0]) {
+               for (i = 0; i < vsi->alloc_queue_pairs; i++) {
                        kfree_rcu(vsi->tx_rings[i], rcu);
                        vsi->tx_rings[i] = NULL;
                        vsi->rx_rings[i] = NULL;
                }
-
-       return 0;
+       }
 }
 
 /**
@@ -5324,7 +5419,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
        int i;
 
        /* Set basic values in the rings to be used later during open() */
-       for (i = 0; i < vsi->num_queue_pairs; i++) {
+       for (i = 0; i < vsi->alloc_queue_pairs; i++) {
                struct i40e_ring *tx_ring;
                struct i40e_ring *rx_ring;
 
@@ -5585,7 +5680,6 @@ static void i40e_init_interrupt_scheme(struct i40e_pf *pf)
                if (err) {
                        pf->flags &= ~(I40E_FLAG_MSIX_ENABLED      |
                                        I40E_FLAG_RSS_ENABLED      |
-                                       I40E_FLAG_MQ_ENABLED       |
                                        I40E_FLAG_DCB_ENABLED      |
                                        I40E_FLAG_SRIOV_ENABLED    |
                                        I40E_FLAG_FDIR_ENABLED     |
@@ -5659,25 +5753,6 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf)
  **/
 static int i40e_config_rss(struct i40e_pf *pf)
 {
-       const u64 default_hena =
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) |
-                       ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD);
-
        /* Set of random keys generated using kernel random number generator */
        static const u32 seed[I40E_PFQF_HKEY_MAX_INDEX + 1] = {0x41b01687,
                                0x183cfd8c, 0xce880440, 0x580cbc3c, 0x35897377,
@@ -5695,7 +5770,7 @@ static int i40e_config_rss(struct i40e_pf *pf)
        /* By default we enable TCP/UDP with IPv4/IPv6 ptypes */
        hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) |
                ((u64)rd32(hw, I40E_PFQF_HENA(1)) << 32);
-       hena |= default_hena;
+       hena |= I40E_DEFAULT_RSS_HENA;
        wr32(hw, I40E_PFQF_HENA(0), (u32)hena);
        wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
 
@@ -5740,16 +5815,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
        queue_count = rounddown_pow_of_two(queue_count);
 
        if (queue_count != pf->rss_size) {
-               if (pf->queues_left < (queue_count - pf->rss_size)) {
-                       dev_info(&pf->pdev->dev,
-                               "Not enough queues to do RSS on %d queues: remaining queues %d\n",
-                               queue_count, pf->queues_left);
-                       return pf->rss_size;
-               }
                i40e_prep_for_reset(pf);
 
-               pf->num_lan_qps += (queue_count - pf->rss_size);
-               pf->queues_left -= (queue_count - pf->rss_size);
                pf->rss_size = queue_count;
 
                i40e_reset_and_rebuild(pf, true);
@@ -5786,8 +5853,6 @@ static int i40e_sw_init(struct i40e_pf *pf)
        pf->flags = I40E_FLAG_RX_CSUM_ENABLED |
                    I40E_FLAG_MSI_ENABLED     |
                    I40E_FLAG_MSIX_ENABLED    |
-                   I40E_FLAG_RX_PS_ENABLED   |
-                   I40E_FLAG_MQ_ENABLED      |
                    I40E_FLAG_RX_1BUF_ENABLED;
 
        /* Depending on PF configurations, it is possible that the RSS
@@ -5803,6 +5868,12 @@ static int i40e_sw_init(struct i40e_pf *pf)
                pf->rss_size = 1;
        }
 
+       /* MFP mode enabled */
+       if (pf->hw.func_caps.npar_enable || pf->hw.func_caps.mfp_mode_1) {
+               pf->flags |= I40E_FLAG_MFP_ENABLED;
+               dev_info(&pf->pdev->dev, "MFP mode Enabled\n");
+       }
+
        if (pf->hw.func_caps.dcb)
                pf->num_tc_qps = I40E_DEFAULT_QUEUES_PER_TC;
        else
@@ -5831,12 +5902,6 @@ static int i40e_sw_init(struct i40e_pf *pf)
                pf->num_vmdq_qps = I40E_DEFAULT_QUEUES_PER_VMDQ;
        }
 
-       /* MFP mode enabled */
-       if (pf->hw.func_caps.npar_enable || pf->hw.func_caps.mfp_mode_1) {
-               pf->flags |= I40E_FLAG_MFP_ENABLED;
-               dev_info(&pf->pdev->dev, "MFP mode Enabled\n");
-       }
-
 #ifdef CONFIG_PCI_IOV
        if (pf->hw.func_caps.num_vfs) {
                pf->num_vf_qps = I40E_DEFAULT_QUEUES_PER_VF;
@@ -5901,6 +5966,104 @@ static int i40e_set_features(struct net_device *netdev,
        return 0;
 }
 
+#ifdef CONFIG_I40E_VXLAN
+/**
+ * i40e_get_vxlan_port_idx - Lookup a possibly offloaded for Rx UDP port
+ * @pf: board private structure
+ * @port: The UDP port to look up
+ *
+ * Returns the index number or I40E_MAX_PF_UDP_OFFLOAD_PORTS if port not found
+ **/
+static u8 i40e_get_vxlan_port_idx(struct i40e_pf *pf, __be16 port)
+{
+       u8 i;
+
+       for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
+               if (pf->vxlan_ports[i] == port)
+                       return i;
+       }
+
+       return i;
+}
+
+/**
+ * i40e_add_vxlan_port - Get notifications about VXLAN ports that come up
+ * @netdev: This physical port's netdev
+ * @sa_family: Socket Family that VXLAN is notifying us about
+ * @port: New UDP port number that VXLAN started listening to
+ **/
+static void i40e_add_vxlan_port(struct net_device *netdev,
+                               sa_family_t sa_family, __be16 port)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_vsi *vsi = np->vsi;
+       struct i40e_pf *pf = vsi->back;
+       u8 next_idx;
+       u8 idx;
+
+       if (sa_family == AF_INET6)
+               return;
+
+       idx = i40e_get_vxlan_port_idx(pf, port);
+
+       /* Check if port already exists */
+       if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
+               netdev_info(netdev, "Port %d already offloaded\n", ntohs(port));
+               return;
+       }
+
+       /* Now check if there is space to add the new port */
+       next_idx = i40e_get_vxlan_port_idx(pf, 0);
+
+       if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
+               netdev_info(netdev, "Maximum number of UDP ports reached, not adding port %d\n",
+                           ntohs(port));
+               return;
+       }
+
+       /* New port: add it and mark its index in the bitmap */
+       pf->vxlan_ports[next_idx] = port;
+       pf->pending_vxlan_bitmap |= (1 << next_idx);
+
+       pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC;
+}
+
+/**
+ * i40e_del_vxlan_port - Get notifications about VXLAN ports that go away
+ * @netdev: This physical port's netdev
+ * @sa_family: Socket Family that VXLAN is notifying us about
+ * @port: UDP port number that VXLAN stopped listening to
+ **/
+static void i40e_del_vxlan_port(struct net_device *netdev,
+                               sa_family_t sa_family, __be16 port)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_vsi *vsi = np->vsi;
+       struct i40e_pf *pf = vsi->back;
+       u8 idx;
+
+       if (sa_family == AF_INET6)
+               return;
+
+       idx = i40e_get_vxlan_port_idx(pf, port);
+
+       /* Check if port already exists */
+       if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
+               /* if port exists, set it to 0 (mark for deletion)
+                * and make it pending
+                */
+               pf->vxlan_ports[idx] = 0;
+
+               pf->pending_vxlan_bitmap |= (1 << idx);
+
+               pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC;
+       } else {
+               netdev_warn(netdev, "Port %d was not found, not deleting\n",
+                           ntohs(port));
+       }
+}
+
+#endif
 static const struct net_device_ops i40e_netdev_ops = {
        .ndo_open               = i40e_open,
        .ndo_stop               = i40e_close,
@@ -5910,6 +6073,7 @@ static const struct net_device_ops i40e_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = i40e_set_mac,
        .ndo_change_mtu         = i40e_change_mtu,
+       .ndo_do_ioctl           = i40e_ioctl,
        .ndo_tx_timeout         = i40e_tx_timeout,
        .ndo_vlan_rx_add_vid    = i40e_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = i40e_vlan_rx_kill_vid,
@@ -5922,6 +6086,10 @@ static const struct net_device_ops i40e_netdev_ops = {
        .ndo_set_vf_vlan        = i40e_ndo_set_vf_port_vlan,
        .ndo_set_vf_tx_rate     = i40e_ndo_set_vf_bw,
        .ndo_get_vf_config      = i40e_ndo_get_vf_config,
+#ifdef CONFIG_I40E_VXLAN
+       .ndo_add_vxlan_port     = i40e_add_vxlan_port,
+       .ndo_del_vxlan_port     = i40e_del_vxlan_port,
+#endif
 };
 
 /**
@@ -5932,6 +6100,7 @@ static const struct net_device_ops i40e_netdev_ops = {
  **/
 static int i40e_config_netdev(struct i40e_vsi *vsi)
 {
+       u8 brdcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
        struct i40e_pf *pf = vsi->back;
        struct i40e_hw *hw = &pf->hw;
        struct i40e_netdev_priv *np;
@@ -5981,6 +6150,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
                random_ether_addr(mac_addr);
                i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, false);
        }
+       i40e_add_filter(vsi, brdcast, I40E_VLAN_ANY, false, false);
 
        memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
        memcpy(netdev->perm_addr, mac_addr, ETH_ALEN);
@@ -6766,7 +6936,7 @@ void i40e_veb_release(struct i40e_veb *veb)
  **/
 static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi)
 {
-       bool is_default = (vsi->idx == vsi->back->lan_vsi);
+       bool is_default = false;
        bool is_cloud = false;
        int ret;
 
@@ -7084,12 +7254,6 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
                        i40e_fdir_teardown(pf);
                        return -EAGAIN;
                }
-               /* accommodate kcompat by copying the main VSI queue count
-                * into the pf, since this newer code pushes the pf queue
-                * info down a level into a VSI
-                */
-               pf->num_rx_queues = vsi->num_queue_pairs;
-               pf->num_tx_queues = vsi->num_queue_pairs;
        } else {
                /* force a reset of TC and queue layout configurations */
                u8 enabled_tc = pf->vsi[pf->lan_vsi]->tc_config.enabled_tc;
@@ -7176,6 +7340,8 @@ no_autoneg:
                                         ~I40E_PRTDCB_MFLCN_RFCE_MASK);
 
 fc_complete:
+       i40e_ptp_init(pf);
+
        return ret;
 }
 
@@ -7214,8 +7380,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
         */
        queues_left = pf->hw.func_caps.num_tx_qp;
 
-       if   (!((pf->flags & I40E_FLAG_MSIX_ENABLED)             &&
-               (pf->flags & I40E_FLAG_MQ_ENABLED))              ||
+       if   (!(pf->flags & I40E_FLAG_MSIX_ENABLED) ||
                !(pf->flags & (I40E_FLAG_RSS_ENABLED |
                I40E_FLAG_FDIR_ENABLED | I40E_FLAG_DCB_ENABLED)) ||
                (queues_left == 1)) {
@@ -7226,7 +7391,6 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
 
                /* make sure all the fancies are disabled */
                pf->flags &= ~(I40E_FLAG_RSS_ENABLED       |
-                               I40E_FLAG_MQ_ENABLED       |
                                I40E_FLAG_FDIR_ENABLED     |
                                I40E_FLAG_FDIR_ATR_ENABLED |
                                I40E_FLAG_DCB_ENABLED      |
@@ -7369,6 +7533,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct i40e_pf *pf;
        struct i40e_hw *hw;
        static u16 pfs_found;
+       u16 link_status;
        int err = 0;
        u32 len;
 
@@ -7490,6 +7655,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_pf_reset;
        }
 
+       i40e_clear_pxe_mode(hw);
        err = i40e_get_capabilities(pf);
        if (err)
                goto err_adminq_setup;
@@ -7516,7 +7682,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        i40e_get_mac_addr(hw, hw->mac.addr);
-       if (i40e_validate_mac_addr(hw->mac.addr)) {
+       if (!is_valid_ether_addr(hw->mac.addr)) {
                dev_info(&pdev->dev, "invalid MAC address %pM\n", hw->mac.addr);
                err = -EIO;
                goto err_mac_addr;
@@ -7536,6 +7702,10 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pf->flags |= I40E_FLAG_NEED_LINK_UPDATE;
        pf->link_check_timeout = jiffies;
 
+       /* WoL defaults to disabled */
+       pf->wol_en = false;
+       device_set_wakeup_enable(&pf->pdev->dev, pf->wol_en);
+
        /* set up the main switch operations */
        i40e_determine_queue_usage(pf);
        i40e_init_interrupt_scheme(pf);
@@ -7603,14 +7773,37 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        mod_timer(&pf->service_timer,
                  round_jiffies(jiffies + pf->service_timer_period));
 
+       /* Get the negotiated link width and speed from PCI config space */
+       pcie_capability_read_word(pf->pdev, PCI_EXP_LNKSTA, &link_status);
+
+       i40e_set_pci_config_data(hw, link_status);
+
+       dev_info(&pdev->dev, "PCI Express: %s %s\n",
+               (hw->bus.speed == i40e_bus_speed_8000 ? "Speed 8.0GT/s" :
+                hw->bus.speed == i40e_bus_speed_5000 ? "Speed 5.0GT/s" :
+                hw->bus.speed == i40e_bus_speed_2500 ? "Speed 2.5GT/s" :
+                "Unknown"),
+               (hw->bus.width == i40e_bus_width_pcie_x8 ? "Width x8" :
+                hw->bus.width == i40e_bus_width_pcie_x4 ? "Width x4" :
+                hw->bus.width == i40e_bus_width_pcie_x2 ? "Width x2" :
+                hw->bus.width == i40e_bus_width_pcie_x1 ? "Width x1" :
+                "Unknown"));
+
+       if (hw->bus.width < i40e_bus_width_pcie_x8 ||
+           hw->bus.speed < i40e_bus_speed_8000) {
+               dev_warn(&pdev->dev, "PCI-Express bandwidth available for this device may be insufficient for optimal performance.\n");
+               dev_warn(&pdev->dev, "Please move the device to a different PCI-e link with more lanes and/or higher transfer rate.\n");
+       }
+
        return 0;
 
        /* Unwind what we've done if something failed in the setup */
 err_vsis:
        set_bit(__I40E_DOWN, &pf->state);
-err_switch_setup:
        i40e_clear_interrupt_scheme(pf);
        kfree(pf->vsi);
+err_switch_setup:
+       i40e_reset_interrupt_capability(pf);
        del_timer_sync(&pf->service_timer);
 err_mac_addr:
 err_configure_lan_hmc:
@@ -7653,6 +7846,8 @@ static void i40e_remove(struct pci_dev *pdev)
 
        i40e_dbg_pf_exit(pf);
 
+       i40e_ptp_stop(pf);
+
        if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
                i40e_free_vfs(pf);
                pf->flags &= ~I40E_FLAG_SRIOV_ENABLED;
@@ -7696,7 +7891,6 @@ static void i40e_remove(struct pci_dev *pdev)
                         "Failed to destroy the HMC resources: %d\n", ret_code);
 
        /* shutdown the adminq */
-       i40e_aq_queue_shutdown(&pf->hw, true);
        ret_code = i40e_shutdown_adminq(&pf->hw);
        if (ret_code)
                dev_warn(&pdev->dev,
@@ -7835,6 +8029,7 @@ static void i40e_pci_error_resume(struct pci_dev *pdev)
 static void i40e_shutdown(struct pci_dev *pdev)
 {
        struct i40e_pf *pf = pci_get_drvdata(pdev);
+       struct i40e_hw *hw = &pf->hw;
 
        set_bit(__I40E_SUSPENDED, &pf->state);
        set_bit(__I40E_DOWN, &pf->state);
@@ -7842,8 +8037,11 @@ static void i40e_shutdown(struct pci_dev *pdev)
        i40e_prep_for_reset(pf);
        rtnl_unlock();
 
+       wr32(hw, I40E_PFPM_APM, (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
+       wr32(hw, I40E_PFPM_WUFC, (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
+
        if (system_state == SYSTEM_POWER_OFF) {
-               pci_wake_from_d3(pdev, false);    /* No WoL support yet */
+               pci_wake_from_d3(pdev, pf->wol_en);
                pci_set_power_state(pdev, PCI_D3hot);
        }
 }
@@ -7856,6 +8054,7 @@ static void i40e_shutdown(struct pci_dev *pdev)
 static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct i40e_pf *pf = pci_get_drvdata(pdev);
+       struct i40e_hw *hw = &pf->hw;
 
        set_bit(__I40E_SUSPENDED, &pf->state);
        set_bit(__I40E_DOWN, &pf->state);
@@ -7863,7 +8062,10 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
        i40e_prep_for_reset(pf);
        rtnl_unlock();
 
-       pci_wake_from_d3(pdev, false);    /* No WoL support yet */
+       wr32(hw, I40E_PFPM_APM, (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
+       wr32(hw, I40E_PFPM_WUFC, (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
+
+       pci_wake_from_d3(pdev, pf->wol_en);
        pci_set_power_state(pdev, PCI_D3hot);
 
        return 0;
index 97e1bb30ef8a1edae549e23e5b34875685302f1e..e12bf07fd23d91d7a96b4db89d4881774605545e 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -166,15 +165,15 @@ static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
 }
 
 /**
- *  i40e_read_nvm_srctl - Reads Shadow RAM.
+ *  i40e_read_nvm_word - Reads Shadow RAM
  *  @hw: pointer to the HW structure.
  *  @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
  *  @data: word read from the Shadow RAM.
  *
  *  Reads 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
  **/
-static i40e_status i40e_read_nvm_srctl(struct i40e_hw *hw, u16 offset,
-                                                u16 *data)
+i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
+                                        u16 *data)
 {
        i40e_status ret_code = I40E_ERR_TIMEOUT;
        u32 sr_reg;
@@ -210,29 +209,6 @@ read_nvm_exit:
        return ret_code;
 }
 
-/**
- *  i40e_read_nvm_word - Reads Shadow RAM word.
- *  @hw: pointer to the HW structure.
- *  @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
- *  @data: word read from the Shadow RAM.
- *
- *  Reads 16 bit word from the Shadow RAM. Each read is preceded
- *  with the NVM ownership taking and followed by the release.
- **/
-i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
-                                        u16 *data)
-{
-       i40e_status ret_code = 0;
-
-       ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
-       if (!ret_code) {
-               ret_code = i40e_read_nvm_srctl(hw, offset, data);
-               i40e_release_nvm(hw);
-       }
-
-       return ret_code;
-}
-
 /**
  *  i40e_read_nvm_buffer - Reads Shadow RAM buffer.
  *  @hw: pointer to the HW structure.
@@ -250,36 +226,25 @@ i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
 {
        i40e_status ret_code = 0;
        u16 index, word;
-       u32 time;
 
-       ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
-       if (!ret_code) {
-               /* Loop thru the selected region. */
-               for (word = 0; word < *words; word++) {
-                       index = offset + word;
-                       ret_code = i40e_read_nvm_srctl(hw, index, &data[word]);
-                       if (ret_code)
-                               break;
-                       /* Check if we didn't exceeded the semaphore timeout. */
-                       time = rd32(hw, I40E_GLVFGEN_TIMER);
-                       if (time >= hw->nvm.hw_semaphore_timeout) {
-                               ret_code = I40E_ERR_TIMEOUT;
-                               hw_dbg(hw, "NVM read error: timeout.\n");
-                               break;
-                       }
-               }
-               /* Update the number of words read from the Shadow RAM. */
-               *words = word;
-               /* Release the NVM ownership. */
-               i40e_release_nvm(hw);
+       /* Loop thru the selected region. */
+       for (word = 0; word < *words; word++) {
+               index = offset + word;
+               ret_code = i40e_read_nvm_word(hw, index, &data[word]);
+               if (ret_code)
+                       break;
        }
 
+       /* Update the number of words read from the Shadow RAM. */
+       *words = word;
+
        return ret_code;
 }
 
 /**
  *  i40e_calc_nvm_checksum - Calculates and returns the checksum
  *  @hw: pointer to hardware structure
+ *  @checksum: pointer to the checksum
  *
  *  This function calculate SW Checksum that covers the whole 64kB shadow RAM
  *  except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
@@ -297,14 +262,14 @@ static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
        u32 i = 0;
 
        /* read pointer to VPD area */
-       ret_code = i40e_read_nvm_srctl(hw, I40E_SR_VPD_PTR, &vpd_module);
+       ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
        if (ret_code) {
                ret_code = I40E_ERR_NVM_CHECKSUM;
                goto i40e_calc_nvm_checksum_exit;
        }
 
        /* read pointer to PCIe Alt Auto-load module */
-       ret_code = i40e_read_nvm_srctl(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
+       ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
                                       &pcie_alt_module);
        if (ret_code) {
                ret_code = I40E_ERR_NVM_CHECKSUM;
@@ -331,7 +296,7 @@ static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
                                break;
                }
 
-               ret_code = i40e_read_nvm_srctl(hw, (u16)i, &word);
+               ret_code = i40e_read_nvm_word(hw, (u16)i, &word);
                if (ret_code) {
                        ret_code = I40E_ERR_NVM_CHECKSUM;
                        goto i40e_calc_nvm_checksum_exit;
@@ -371,7 +336,7 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
        /* Do not use i40e_read_nvm_word() because we do not want to take
         * the synchronization semaphores twice here.
         */
-       i40e_read_nvm_srctl(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
+       i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
 
        /* Verify read checksum from EEPROM is the same as
         * calculated checksum
index 702c81ba86e35b7b9e5034c582dc1697417dd7cc..ecd0f0b663c97a3871edfb0c7e0bb738c02cf688 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
index 2fc9ce528d4d9a173a4d95c91cd8f446896edc71..f8c53a6ec580504b74e18b38676e828eede65fda 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -59,9 +58,12 @@ void i40e_debug_aq(struct i40e_hw *hw,
                   void *buffer);
 
 void i40e_idle_aq(struct i40e_hw *hw);
+bool i40e_check_asq_alive(struct i40e_hw *hw);
+i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw,
+                                  bool unloading);
 
 u32 i40e_led_get(struct i40e_hw *hw);
-void i40e_led_set(struct i40e_hw *hw, u32 mode);
+void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink);
 
 /* admin send queue commands */
 
@@ -69,8 +71,6 @@ i40e_status i40e_aq_get_firmware_version(struct i40e_hw *hw,
                                u16 *fw_major_version, u16 *fw_minor_version,
                                u16 *api_major_version, u16 *api_minor_version,
                                struct i40e_asq_cmd_details *cmd_details);
-i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw,
-                                            bool unloading);
 i40e_status i40e_aq_set_phy_reset(struct i40e_hw *hw,
                                struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id,
@@ -93,9 +93,9 @@ i40e_status i40e_aq_set_vsi_broadcast(struct i40e_hw *hw,
                                u16 vsi_id, bool set_filter,
                                struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
-                               u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
+               u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw,
-                               u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
+               u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw,
                                struct i40e_vsi_context *vsi_ctx,
                                struct i40e_asq_cmd_details *cmd_details);
@@ -157,6 +157,12 @@ i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
                                struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
                                struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_add_udp_tunnel(struct i40e_hw *hw,
+                               u16 udp_port, u8 header_len,
+                               u8 protocol_index, u8 *filter_index,
+                               struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_del_udp_tunnel(struct i40e_hw *hw, u8 index,
+                               struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_delete_element(struct i40e_hw *hw, u16 seid,
                                struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_mac_address_write(struct i40e_hw *hw,
@@ -199,7 +205,6 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw);
 bool i40e_get_link_status(struct i40e_hw *hw);
 i40e_status i40e_get_mac_addr(struct i40e_hw *hw,
                                                u8 *mac_addr);
-i40e_status i40e_validate_mac_addr(u8 *mac_addr);
 i40e_status i40e_read_lldp_cfg(struct i40e_hw *hw,
                                        struct i40e_lldp_variables *lldp_cfg);
 /* prototype for functions used for NVM access */
@@ -215,6 +220,7 @@ i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
                                           u16 *words, u16 *data);
 i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
                                                 u16 *checksum);
+void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
 
 /* prototype for functions used for SW locks */
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
new file mode 100644 (file)
index 0000000..e33ec6c
--- /dev/null
@@ -0,0 +1,662 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Driver
+ * Copyright(c) 2013 - 2014 Intel Corporation.
+ *
+ * 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".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#include "i40e.h"
+#include <linux/export.h>
+#include <linux/ptp_classify.h>
+
+/* The XL710 timesync is very much like Intel's 82599 design when it comes to
+ * the fundamental clock design. However, the clock operations are much simpler
+ * in the XL710 because the device supports a full 64 bits of nanoseconds.
+ * Because the field is so wide, we can forgo the cycle counter and just
+ * operate with the nanosecond field directly without fear of overflow.
+ *
+ * Much like the 82599, the update period is dependent upon the link speed:
+ * At 40Gb link or no link, the period is 1.6ns.
+ * At 10Gb link, the period is multiplied by 2. (3.2ns)
+ * At 1Gb link, the period is multiplied by 20. (32ns)
+ * 1588 functionality is not supported at 100Mbps.
+ */
+#define I40E_PTP_40GB_INCVAL 0x0199999999ULL
+#define I40E_PTP_10GB_INCVAL 0x0333333333ULL
+#define I40E_PTP_1GB_INCVAL  0x2000000000ULL
+
+#define I40E_PRTTSYN_CTL1_TSYNTYPE_V1  (0x1 << \
+                                       I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
+#define I40E_PRTTSYN_CTL1_TSYNTYPE_V2  (0x2 << \
+                                       I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
+#define I40E_PTP_TX_TIMEOUT  (HZ * 15)
+
+/**
+ * i40e_ptp_read - Read the PHC time from the device
+ * @pf: Board private structure
+ * @ts: timespec structure to hold the current time value
+ *
+ * This function reads the PRTTSYN_TIME registers and stores them in a
+ * timespec. However, since the registers are 64 bits of nanoseconds, we must
+ * convert the result to a timespec before we can return.
+ **/
+static void i40e_ptp_read(struct i40e_pf *pf, struct timespec *ts)
+{
+       struct i40e_hw *hw = &pf->hw;
+       u32 hi, lo;
+       u64 ns;
+
+       /* The timer latches on the lowest register read. */
+       lo = rd32(hw, I40E_PRTTSYN_TIME_L);
+       hi = rd32(hw, I40E_PRTTSYN_TIME_H);
+
+       ns = (((u64)hi) << 32) | lo;
+
+       *ts = ns_to_timespec(ns);
+}
+
+/**
+ * i40e_ptp_write - Write the PHC time to the device
+ * @pf: Board private structure
+ * @ts: timespec structure that holds the new time value
+ *
+ * This function writes the PRTTSYN_TIME registers with the user value. Since
+ * we receive a timespec from the stack, we must convert that timespec into
+ * nanoseconds before programming the registers.
+ **/
+static void i40e_ptp_write(struct i40e_pf *pf, const struct timespec *ts)
+{
+       struct i40e_hw *hw = &pf->hw;
+       u64 ns = timespec_to_ns(ts);
+
+       /* The timer will not update until the high register is written, so
+        * write the low register first.
+        */
+       wr32(hw, I40E_PRTTSYN_TIME_L, ns & 0xFFFFFFFF);
+       wr32(hw, I40E_PRTTSYN_TIME_H, ns >> 32);
+}
+
+/**
+ * i40e_ptp_convert_to_hwtstamp - Convert device clock to system time
+ * @hwtstamps: Timestamp structure to update
+ * @timestamp: Timestamp from the hardware
+ *
+ * We need to convert the NIC clock value into a hwtstamp which can be used by
+ * the upper level timestamping functions. Since the timestamp is simply a 64-
+ * bit nanosecond value, we can call ns_to_ktime directly to handle this.
+ **/
+static void i40e_ptp_convert_to_hwtstamp(struct skb_shared_hwtstamps *hwtstamps,
+                                        u64 timestamp)
+{
+       memset(hwtstamps, 0, sizeof(*hwtstamps));
+
+       hwtstamps->hwtstamp = ns_to_ktime(timestamp);
+}
+
+/**
+ * i40e_ptp_adjfreq - Adjust the PHC frequency
+ * @ptp: The PTP clock structure
+ * @ppb: Parts per billion adjustment from the base
+ *
+ * Adjust the frequency of the PHC by the indicated parts per billion from the
+ * base frequency.
+ **/
+static int i40e_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+       struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
+       struct i40e_hw *hw = &pf->hw;
+       u64 adj, freq, diff;
+       int neg_adj = 0;
+
+       if (ppb < 0) {
+               neg_adj = 1;
+               ppb = -ppb;
+       }
+
+       smp_mb(); /* Force any pending update before accessing. */
+       adj = ACCESS_ONCE(pf->ptp_base_adj);
+
+       freq = adj;
+       freq *= ppb;
+       diff = div_u64(freq, 1000000000ULL);
+
+       if (neg_adj)
+               adj -= diff;
+       else
+               adj += diff;
+
+       wr32(hw, I40E_PRTTSYN_INC_L, adj & 0xFFFFFFFF);
+       wr32(hw, I40E_PRTTSYN_INC_H, adj >> 32);
+
+       return 0;
+}
+
+/**
+ * i40e_ptp_adjtime - Adjust the PHC time
+ * @ptp: The PTP clock structure
+ * @delta: Offset in nanoseconds to adjust the PHC time by
+ *
+ * Adjust the frequency of the PHC by the indicated parts per billion from the
+ * base frequency.
+ **/
+static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+       struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
+       struct timespec now, then = ns_to_timespec(delta);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pf->tmreg_lock, flags);
+
+       i40e_ptp_read(pf, &now);
+       now = timespec_add(now, then);
+       i40e_ptp_write(pf, (const struct timespec *)&now);
+
+       spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+
+       return 0;
+}
+
+/**
+ * i40e_ptp_gettime - Get the time of the PHC
+ * @ptp: The PTP clock structure
+ * @ts: timespec structure to hold the current time value
+ *
+ * Read the device clock and return the correct value on ns, after converting it
+ * into a timespec struct.
+ **/
+static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+       struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pf->tmreg_lock, flags);
+       i40e_ptp_read(pf, ts);
+       spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+
+       return 0;
+}
+
+/**
+ * i40e_ptp_settime - Set the time of the PHC
+ * @ptp: The PTP clock structure
+ * @ts: timespec structure that holds the new time value
+ *
+ * Set the device clock to the user input value. The conversion from timespec
+ * to ns happens in the write function.
+ **/
+static int i40e_ptp_settime(struct ptp_clock_info *ptp,
+                           const struct timespec *ts)
+{
+       struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pf->tmreg_lock, flags);
+       i40e_ptp_write(pf, ts);
+       spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+
+       return 0;
+}
+
+/**
+ * i40e_ptp_tx_work
+ * @work: pointer to work struct
+ *
+ * This work function polls the PRTTSYN_STAT_0.TXTIME bit to determine when a
+ * Tx timestamp event has occurred, in order to pass the Tx timestamp value up
+ * the stack in the skb.
+ */
+static void i40e_ptp_tx_work(struct work_struct *work)
+{
+       struct i40e_pf *pf = container_of(work, struct i40e_pf,
+                                         ptp_tx_work);
+       struct i40e_hw *hw = &pf->hw;
+       u32 prttsyn_stat_0;
+
+       if (!pf->ptp_tx_skb)
+               return;
+
+       if (time_is_before_jiffies(pf->ptp_tx_start +
+                                  I40E_PTP_TX_TIMEOUT)) {
+               dev_kfree_skb_any(pf->ptp_tx_skb);
+               pf->ptp_tx_skb = NULL;
+               pf->tx_hwtstamp_timeouts++;
+               dev_warn(&pf->pdev->dev, "clearing Tx timestamp hang");
+               return;
+       }
+
+       prttsyn_stat_0 = rd32(hw, I40E_PRTTSYN_STAT_0);
+       if (prttsyn_stat_0 & I40E_PRTTSYN_STAT_0_TXTIME_MASK)
+               i40e_ptp_tx_hwtstamp(pf);
+       else
+               schedule_work(&pf->ptp_tx_work);
+}
+
+/**
+ * i40e_ptp_enable - Enable/disable ancillary features of the PHC subsystem
+ * @ptp: The PTP clock structure
+ * @rq: The requested feature to change
+ * @on: Enable/disable flag
+ *
+ * The XL710 does not support any of the ancillary features of the PHC
+ * subsystem, so this function may just return.
+ **/
+static int i40e_ptp_enable(struct ptp_clock_info *ptp,
+                          struct ptp_clock_request *rq, int on)
+{
+       return -EOPNOTSUPP;
+}
+
+/**
+ * i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung
+ * @vsi: The VSI with the rings relevant to 1588
+ *
+ * This watchdog task is scheduled to detect error case where hardware has
+ * dropped an Rx packet that was timestamped when the ring is full. The
+ * particular error is rare but leaves the device in a state unable to timestamp
+ * any future packets.
+ **/
+void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
+{
+       struct i40e_pf *pf = vsi->back;
+       struct i40e_hw *hw = &pf->hw;
+       struct i40e_ring *rx_ring;
+       unsigned long rx_event;
+       u32 prttsyn_stat;
+       int n;
+
+       if (pf->flags & I40E_FLAG_PTP)
+               return;
+
+       prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
+
+       /* Unless all four receive timestamp registers are latched, we are not
+        * concerned about a possible PTP Rx hang, so just update the timeout
+        * counter and exit.
+        */
+       if (!(prttsyn_stat & ((I40E_PRTTSYN_STAT_1_RXT0_MASK <<
+                              I40E_PRTTSYN_STAT_1_RXT0_SHIFT) |
+                             (I40E_PRTTSYN_STAT_1_RXT1_MASK <<
+                              I40E_PRTTSYN_STAT_1_RXT1_SHIFT) |
+                             (I40E_PRTTSYN_STAT_1_RXT2_MASK <<
+                              I40E_PRTTSYN_STAT_1_RXT2_SHIFT) |
+                             (I40E_PRTTSYN_STAT_1_RXT3_MASK <<
+                              I40E_PRTTSYN_STAT_1_RXT3_SHIFT)))) {
+               pf->last_rx_ptp_check = jiffies;
+               return;
+       }
+
+       /* Determine the most recent watchdog or rx_timestamp event. */
+       rx_event = pf->last_rx_ptp_check;
+       for (n = 0; n < vsi->num_queue_pairs; n++) {
+               rx_ring = vsi->rx_rings[n];
+               if (time_after(rx_ring->last_rx_timestamp, rx_event))
+                       rx_event = rx_ring->last_rx_timestamp;
+       }
+
+       /* Only need to read the high RXSTMP register to clear the lock */
+       if (time_is_before_jiffies(rx_event + 5 * HZ)) {
+               rd32(hw, I40E_PRTTSYN_RXTIME_H(0));
+               rd32(hw, I40E_PRTTSYN_RXTIME_H(1));
+               rd32(hw, I40E_PRTTSYN_RXTIME_H(2));
+               rd32(hw, I40E_PRTTSYN_RXTIME_H(3));
+               pf->last_rx_ptp_check = jiffies;
+               pf->rx_hwtstamp_cleared++;
+               dev_warn(&vsi->back->pdev->dev,
+                        "%s: clearing Rx timestamp hang",
+                        __func__);
+       }
+}
+
+/**
+ * i40e_ptp_tx_hwtstamp - Utility function which returns the Tx timestamp
+ * @pf: Board private structure
+ *
+ * Read the value of the Tx timestamp from the registers, convert it into a
+ * value consumable by the stack, and store that result into the shhwtstamps
+ * struct before returning it up the stack.
+ **/
+void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
+{
+       struct skb_shared_hwtstamps shhwtstamps;
+       struct i40e_hw *hw = &pf->hw;
+       u32 hi, lo;
+       u64 ns;
+
+       lo = rd32(hw, I40E_PRTTSYN_TXTIME_L);
+       hi = rd32(hw, I40E_PRTTSYN_TXTIME_H);
+
+       ns = (((u64)hi) << 32) | lo;
+
+       i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns);
+       skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps);
+       dev_kfree_skb_any(pf->ptp_tx_skb);
+       pf->ptp_tx_skb = NULL;
+}
+
+/**
+ * i40e_ptp_rx_hwtstamp - Utility function which checks for an Rx timestamp
+ * @pf: Board private structure
+ * @skb: Particular skb to send timestamp with
+ * @index: Index into the receive timestamp registers for the timestamp
+ *
+ * The XL710 receives a notification in the receive descriptor with an offset
+ * into the set of RXTIME registers where the timestamp is for that skb. This
+ * function goes and fetches the receive timestamp from that offset, if a valid
+ * one exists. The RXTIME registers are in ns, so we must convert the result
+ * first.
+ **/
+void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index)
+{
+       u32 prttsyn_stat, hi, lo;
+       struct i40e_hw *hw;
+       u64 ns;
+
+       /* Since we cannot turn off the Rx timestamp logic if the device is
+        * doing Tx timestamping, check if Rx timestamping is configured.
+        */
+       if (!pf->ptp_rx)
+               return;
+
+       hw = &pf->hw;
+
+       prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
+
+       if (!(prttsyn_stat & (1 << index)))
+               return;
+
+       lo = rd32(hw, I40E_PRTTSYN_RXTIME_L(index));
+       hi = rd32(hw, I40E_PRTTSYN_RXTIME_H(index));
+
+       ns = (((u64)hi) << 32) | lo;
+
+       i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns);
+}
+
+/**
+ * i40e_ptp_set_increment - Utility function to update clock increment rate
+ * @pf: Board private structure
+ *
+ * During a link change, the DMA frequency that drives the 1588 logic will
+ * change. In order to keep the PRTTSYN_TIME registers in units of nanoseconds,
+ * we must update the increment value per clock tick.
+ **/
+void i40e_ptp_set_increment(struct i40e_pf *pf)
+{
+       struct i40e_link_status *hw_link_info;
+       struct i40e_hw *hw = &pf->hw;
+       u64 incval;
+
+       hw_link_info = &hw->phy.link_info;
+
+       i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
+
+       switch (hw_link_info->link_speed) {
+       case I40E_LINK_SPEED_10GB:
+               incval = I40E_PTP_10GB_INCVAL;
+               break;
+       case I40E_LINK_SPEED_1GB:
+               incval = I40E_PTP_1GB_INCVAL;
+               break;
+       case I40E_LINK_SPEED_100MB:
+               dev_warn(&pf->pdev->dev,
+                        "%s: 1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n",
+                        __func__);
+               incval = 0;
+               break;
+       case I40E_LINK_SPEED_40GB:
+       default:
+               incval = I40E_PTP_40GB_INCVAL;
+               break;
+       }
+
+       /* Write the new increment value into the increment register. The
+        * hardware will not update the clock until both registers have been
+        * written.
+        */
+       wr32(hw, I40E_PRTTSYN_INC_L, incval & 0xFFFFFFFF);
+       wr32(hw, I40E_PRTTSYN_INC_H, incval >> 32);
+
+       /* Update the base adjustement value. */
+       ACCESS_ONCE(pf->ptp_base_adj) = incval;
+       smp_mb(); /* Force the above update. */
+}
+
+/**
+ * i40e_ptp_get_ts_config - ioctl interface to read the HW timestamping
+ * @pf: Board private structure
+ * @ifreq: ioctl data
+ *
+ * Obtain the current hardware timestamping settigs as requested. To do this,
+ * keep a shadow copy of the timestamp settings rather than attempting to
+ * deconstruct it from the registers.
+ **/
+int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
+{
+       struct hwtstamp_config *config = &pf->tstamp_config;
+
+       return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
+               -EFAULT : 0;
+}
+
+/**
+ * i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping
+ * @pf: Board private structure
+ * @ifreq: ioctl data
+ *
+ * Respond to the user filter requests and make the appropriate hardware
+ * changes here. The XL710 cannot support splitting of the Tx/Rx timestamping
+ * logic, so keep track in software of whether to indicate these timestamps
+ * or not.
+ *
+ * It is permissible to "upgrade" the user request to a broader filter, as long
+ * as the user receives the timestamps they care about and the user is notified
+ * the filter has been broadened.
+ **/
+int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
+{
+       struct i40e_hw *hw = &pf->hw;
+       struct hwtstamp_config *config = &pf->tstamp_config;
+       u32 pf_id, tsyntype, regval;
+
+       if (copy_from_user(config, ifr->ifr_data, sizeof(*config)))
+               return -EFAULT;
+
+       /* Reserved for future extensions. */
+       if (config->flags)
+               return -EINVAL;
+
+       /* Confirm that 1588 is supported on this PF. */
+       pf_id = (rd32(hw, I40E_PRTTSYN_CTL0) & I40E_PRTTSYN_CTL0_PF_ID_MASK) >>
+               I40E_PRTTSYN_CTL0_PF_ID_SHIFT;
+       if (hw->pf_id != pf_id)
+               return -EINVAL;
+
+       switch (config->tx_type) {
+       case HWTSTAMP_TX_OFF:
+               pf->ptp_tx = false;
+               break;
+       case HWTSTAMP_TX_ON:
+               pf->ptp_tx = true;
+               break;
+       default:
+               return -ERANGE;
+       }
+
+       switch (config->rx_filter) {
+       case HWTSTAMP_FILTER_NONE:
+               pf->ptp_rx = false;
+               tsyntype = 0;
+               break;
+       case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+       case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+       case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+               pf->ptp_rx = true;
+               tsyntype = I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK |
+                          I40E_PRTTSYN_CTL1_TSYNTYPE_V1 |
+                          I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
+               config->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_EVENT:
+       case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+       case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+       case HWTSTAMP_FILTER_PTP_V2_SYNC:
+       case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+       case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+       case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+       case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+       case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+               pf->ptp_rx = true;
+               tsyntype = I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK |
+                          I40E_PRTTSYN_CTL1_TSYNTYPE_V2 |
+                          I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
+               config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+               break;
+       case HWTSTAMP_FILTER_ALL:
+       default:
+               return -ERANGE;
+       }
+
+       /* Clear out all 1588-related registers to clear and unlatch them. */
+       rd32(hw, I40E_PRTTSYN_STAT_0);
+       rd32(hw, I40E_PRTTSYN_TXTIME_H);
+       rd32(hw, I40E_PRTTSYN_RXTIME_H(0));
+       rd32(hw, I40E_PRTTSYN_RXTIME_H(1));
+       rd32(hw, I40E_PRTTSYN_RXTIME_H(2));
+       rd32(hw, I40E_PRTTSYN_RXTIME_H(3));
+
+       /* Enable/disable the Tx timestamp interrupt based on user input. */
+       regval = rd32(hw, I40E_PRTTSYN_CTL0);
+       if (pf->ptp_tx)
+               regval |= I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK;
+       else
+               regval &= ~I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK;
+       wr32(hw, I40E_PRTTSYN_CTL0, regval);
+
+       regval = rd32(hw, I40E_PFINT_ICR0_ENA);
+       if (pf->ptp_tx)
+               regval |= I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
+       else
+               regval &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
+       wr32(hw, I40E_PFINT_ICR0_ENA, regval);
+
+       /* There is no simple on/off switch for Rx. To "disable" Rx support,
+        * ignore any received timestamps, rather than turn off the clock.
+        */
+       if (pf->ptp_rx) {
+               regval = rd32(hw, I40E_PRTTSYN_CTL1);
+               /* clear everything but the enable bit */
+               regval &= I40E_PRTTSYN_CTL1_TSYNENA_MASK;
+               /* now enable bits for desired Rx timestamps */
+               regval |= tsyntype;
+               wr32(hw, I40E_PRTTSYN_CTL1, regval);
+       }
+
+       return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
+               -EFAULT : 0;
+}
+
+/**
+ * i40e_ptp_init - Initialize the 1588 support and register the PHC
+ * @pf: Board private structure
+ *
+ * This function registers the device clock as a PHC. If it is successful, it
+ * starts the clock in the hardware.
+ **/
+void i40e_ptp_init(struct i40e_pf *pf)
+{
+       struct i40e_hw *hw = &pf->hw;
+       struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
+
+       strncpy(pf->ptp_caps.name, "i40e", sizeof(pf->ptp_caps.name));
+       pf->ptp_caps.owner = THIS_MODULE;
+       pf->ptp_caps.max_adj = 999999999;
+       pf->ptp_caps.n_ext_ts = 0;
+       pf->ptp_caps.pps = 0;
+       pf->ptp_caps.adjfreq = i40e_ptp_adjfreq;
+       pf->ptp_caps.adjtime = i40e_ptp_adjtime;
+       pf->ptp_caps.gettime = i40e_ptp_gettime;
+       pf->ptp_caps.settime = i40e_ptp_settime;
+       pf->ptp_caps.enable = i40e_ptp_enable;
+
+       /* Attempt to register the clock before enabling the hardware. */
+       pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev);
+       if (IS_ERR(pf->ptp_clock)) {
+               pf->ptp_clock = NULL;
+               dev_err(&pf->pdev->dev, "%s: ptp_clock_register failed\n",
+                       __func__);
+       } else {
+               struct timespec ts;
+               u32 regval;
+
+               spin_lock_init(&pf->tmreg_lock);
+               INIT_WORK(&pf->ptp_tx_work, i40e_ptp_tx_work);
+
+               dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__,
+                        netdev->name);
+               pf->flags |= I40E_FLAG_PTP;
+
+               /* Ensure the clocks are running. */
+               regval = rd32(hw, I40E_PRTTSYN_CTL0);
+               regval |= I40E_PRTTSYN_CTL0_TSYNENA_MASK;
+               wr32(hw, I40E_PRTTSYN_CTL0, regval);
+               regval = rd32(hw, I40E_PRTTSYN_CTL1);
+               regval |= I40E_PRTTSYN_CTL1_TSYNENA_MASK;
+               wr32(hw, I40E_PRTTSYN_CTL1, regval);
+
+               /* Set the increment value per clock tick. */
+               i40e_ptp_set_increment(pf);
+
+               /* reset the tstamp_config */
+               memset(&pf->tstamp_config, 0, sizeof(pf->tstamp_config));
+
+               /* Set the clock value. */
+               ts = ktime_to_timespec(ktime_get_real());
+               i40e_ptp_settime(&pf->ptp_caps, &ts);
+       }
+}
+
+/**
+ * i40e_ptp_stop - Disable the driver/hardware support and unregister the PHC
+ * @pf: Board private structure
+ *
+ * This function handles the cleanup work required from the initialization by
+ * clearing out the important information and unregistering the PHC.
+ **/
+void i40e_ptp_stop(struct i40e_pf *pf)
+{
+       pf->flags &= ~I40E_FLAG_PTP;
+       pf->ptp_tx = false;
+       pf->ptp_rx = false;
+
+       cancel_work_sync(&pf->ptp_tx_work);
+       if (pf->ptp_tx_skb) {
+               dev_kfree_skb_any(pf->ptp_tx_skb);
+               pf->ptp_tx_skb = NULL;
+       }
+
+       if (pf->ptp_clock) {
+               ptp_clock_unregister(pf->ptp_clock);
+               pf->ptp_clock = NULL;
+               dev_info(&pf->pdev->dev, "%s: removed PHC on %s\n", __func__,
+                        pf->vsi[pf->lan_vsi]->netdev->name);
+       }
+}
index 2394c66870f4f672aae7e223554f6ce2345847fe..1d40f425acf1833657902dce6dd7206b5493e7eb 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
 #define I40E_GLNVM_SRDATA_WRDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_WRDATA_SHIFT)
 #define I40E_GLNVM_SRDATA_RDDATA_SHIFT 16
 #define I40E_GLNVM_SRDATA_RDDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_RDDATA_SHIFT)
+#define I40E_GLNVM_ULD 0x000B6008
+#define I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT 0
+#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT 1
+#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT 2
+#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT 3
+#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT 4
+#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT 5
+#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT 6
+#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT 7
+#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT 8
+#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT 9
+#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
+
 #define I40E_GLPCI_BYTCTH 0x0009C484
 #define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT 0
 #define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
index 5e5bcddac573e5fb0cf4dc029298a2c0c403e346..5f9cac55aa55cf44737fea614a13e0f2e464bb42 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
index 01d0334fa926b3e5c73039a0fa90805b1e4c2786..a089ac19cfe94273096a5faf2f3b5e907fa51855 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -77,7 +76,6 @@ int i40e_program_fdir_filter(struct i40e_fdir_data *fdir_data,
        /* grab the next descriptor */
        i = tx_ring->next_to_use;
        fdir_desc = I40E_TX_FDIRDESC(tx_ring, i);
-       tx_buf = &tx_ring->tx_bi[i];
 
        tx_ring->next_to_use = (i + 1 < tx_ring->count) ? i + 1 : 0;
 
@@ -129,15 +127,23 @@ int i40e_program_fdir_filter(struct i40e_fdir_data *fdir_data,
        /* Now program a dummy descriptor */
        i = tx_ring->next_to_use;
        tx_desc = I40E_TX_DESC(tx_ring, i);
+       tx_buf = &tx_ring->tx_bi[i];
 
        tx_ring->next_to_use = (i + 1 < tx_ring->count) ? i + 1 : 0;
 
+       /* record length, and DMA address */
+       dma_unmap_len_set(tx_buf, len, I40E_FDIR_MAX_RAW_PACKET_LOOKUP);
+       dma_unmap_addr_set(tx_buf, dma, dma);
+
        tx_desc->buffer_addr = cpu_to_le64(dma);
        td_cmd = I40E_TXD_CMD | I40E_TX_DESC_CMD_DUMMY;
 
        tx_desc->cmd_type_offset_bsz =
                build_ctob(td_cmd, 0, I40E_FDIR_MAX_RAW_PACKET_LOOKUP, 0);
 
+       /* set the timestamp */
+       tx_buf->time_stamp = jiffies;
+
        /* Force memory writes to complete before letting h/w
         * know there are new descriptors to fetch.  (Only
         * applicable for weak-ordered memory model archs,
@@ -768,7 +774,7 @@ void i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
                        skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
                                                        rx_ring->rx_buf_len);
                        if (!skb) {
-                               rx_ring->rx_stats.alloc_rx_buff_failed++;
+                               rx_ring->rx_stats.alloc_buff_failed++;
                                goto no_buffers;
                        }
                        /* initialize queue mapping */
@@ -782,7 +788,7 @@ void i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
                                                 rx_ring->rx_buf_len,
                                                 DMA_FROM_DEVICE);
                        if (dma_mapping_error(rx_ring->dev, bi->dma)) {
-                               rx_ring->rx_stats.alloc_rx_buff_failed++;
+                               rx_ring->rx_stats.alloc_buff_failed++;
                                bi->dma = 0;
                                goto no_buffers;
                        }
@@ -792,7 +798,7 @@ void i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
                        if (!bi->page) {
                                bi->page = alloc_page(GFP_ATOMIC);
                                if (!bi->page) {
-                                       rx_ring->rx_stats.alloc_rx_page_failed++;
+                                       rx_ring->rx_stats.alloc_page_failed++;
                                        goto no_buffers;
                                }
                        }
@@ -807,7 +813,7 @@ void i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
                                                            DMA_FROM_DEVICE);
                                if (dma_mapping_error(rx_ring->dev,
                                                      bi->page_dma)) {
-                                       rx_ring->rx_stats.alloc_rx_page_failed++;
+                                       rx_ring->rx_stats.alloc_page_failed++;
                                        bi->page_dma = 0;
                                        goto no_buffers;
                                }
@@ -860,12 +866,25 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring,
  * @skb: skb currently being received and modified
  * @rx_status: status value of last descriptor in packet
  * @rx_error: error value of last descriptor in packet
+ * @rx_ptype: ptype value of last descriptor in packet
  **/
 static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
                                    struct sk_buff *skb,
                                    u32 rx_status,
-                                   u32 rx_error)
+                                   u32 rx_error,
+                                   u16 rx_ptype)
 {
+       bool ipv4_tunnel, ipv6_tunnel;
+       __wsum rx_udp_csum;
+       __sum16 csum;
+       struct iphdr *iph;
+
+       ipv4_tunnel = (rx_ptype > I40E_RX_PTYPE_GRENAT4_MAC_PAY3) &&
+                     (rx_ptype < I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4);
+       ipv6_tunnel = (rx_ptype > I40E_RX_PTYPE_GRENAT6_MAC_PAY3) &&
+                     (rx_ptype < I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4);
+
+       skb->encapsulation = ipv4_tunnel || ipv6_tunnel;
        skb->ip_summed = CHECKSUM_NONE;
 
        /* Rx csum enabled and ip headers found? */
@@ -873,13 +892,47 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
              rx_status & (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT)))
                return;
 
-       /* IP or L4 checksum error */
+       /* likely incorrect csum if alternate IP extention headers found */
+       if (rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
+               return;
+
+       /* IP or L4 or outmost IP checksum error */
        if (rx_error & ((1 << I40E_RX_DESC_ERROR_IPE_SHIFT) |
-                       (1 << I40E_RX_DESC_ERROR_L4E_SHIFT))) {
+                       (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) |
+                       (1 << I40E_RX_DESC_ERROR_EIPE_SHIFT))) {
                vsi->back->hw_csum_rx_error++;
                return;
        }
 
+       if (ipv4_tunnel &&
+           !(rx_status & (1 << I40E_RX_DESC_STATUS_UDP_0_SHIFT))) {
+               /* If VXLAN traffic has an outer UDPv4 checksum we need to check
+                * it in the driver, hardware does not do it for us.
+                * Since L3L4P bit was set we assume a valid IHL value (>=5)
+                * so the total length of IPv4 header is IHL*4 bytes
+                */
+               skb->transport_header = skb->mac_header +
+                                       sizeof(struct ethhdr) +
+                                       (ip_hdr(skb)->ihl * 4);
+
+               /* Add 4 bytes for VLAN tagged packets */
+               skb->transport_header += (skb->protocol == htons(ETH_P_8021Q) ||
+                                         skb->protocol == htons(ETH_P_8021AD))
+                                         ? VLAN_HLEN : 0;
+
+               rx_udp_csum = udp_csum(skb);
+               iph = ip_hdr(skb);
+               csum = csum_tcpudp_magic(
+                               iph->saddr, iph->daddr,
+                               (skb->len - skb_transport_offset(skb)),
+                               IPPROTO_UDP, rx_udp_csum);
+
+               if (udp_hdr(skb)->check != csum) {
+                       vsi->back->hw_csum_rx_error++;
+                       return;
+               }
+       }
+
        skb->ip_summed = CHECKSUM_UNNECESSARY;
 }
 
@@ -920,6 +973,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
        union i40e_rx_desc *rx_desc;
        u32 rx_error, rx_status;
        u64 qword;
+       u16 rx_ptype;
 
        rx_desc = I40E_RX_DESC(rx_ring, i);
        qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
@@ -940,18 +994,20 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
                skb = rx_bi->skb;
                prefetch(skb->data);
 
-               rx_packet_len = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK)
-                                             >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT;
-               rx_header_len = (qword & I40E_RXD_QW1_LENGTH_HBUF_MASK)
-                                             >> I40E_RXD_QW1_LENGTH_HBUF_SHIFT;
-               rx_sph = (qword & I40E_RXD_QW1_LENGTH_SPH_MASK)
-                                             >> I40E_RXD_QW1_LENGTH_SPH_SHIFT;
+               rx_packet_len = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) >>
+                               I40E_RXD_QW1_LENGTH_PBUF_SHIFT;
+               rx_header_len = (qword & I40E_RXD_QW1_LENGTH_HBUF_MASK) >>
+                               I40E_RXD_QW1_LENGTH_HBUF_SHIFT;
+               rx_sph = (qword & I40E_RXD_QW1_LENGTH_SPH_MASK) >>
+                        I40E_RXD_QW1_LENGTH_SPH_SHIFT;
 
-               rx_error = (qword & I40E_RXD_QW1_ERROR_MASK)
-                                             >> I40E_RXD_QW1_ERROR_SHIFT;
+               rx_error = (qword & I40E_RXD_QW1_ERROR_MASK) >>
+                          I40E_RXD_QW1_ERROR_SHIFT;
                rx_hbo = rx_error & (1 << I40E_RX_DESC_ERROR_HBO_SHIFT);
                rx_error &= ~(1 << I40E_RX_DESC_ERROR_HBO_SHIFT);
 
+               rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+                          I40E_RXD_QW1_PTYPE_SHIFT;
                rx_bi->skb = NULL;
 
                /* This memory barrier is needed to keep us from reading
@@ -1032,13 +1088,21 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
                }
 
                skb->rxhash = i40e_rx_hash(rx_ring, rx_desc);
-               i40e_rx_checksum(vsi, skb, rx_status, rx_error);
+               if (unlikely(rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK)) {
+                       i40e_ptp_rx_hwtstamp(vsi->back, skb, (rx_status &
+                                          I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
+                                          I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT);
+                       rx_ring->last_rx_timestamp = jiffies;
+               }
 
                /* probably a little skewed due to removing CRC */
                total_rx_bytes += skb->len;
                total_rx_packets++;
 
                skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+
+               i40e_rx_checksum(vsi, skb, rx_status, rx_error, rx_ptype);
+
                vlan_tag = rx_status & (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)
                         ? le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1)
                         : 0;
@@ -1061,8 +1125,8 @@ next_desc:
                /* use prefetched values */
                rx_desc = next_rxd;
                qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-               rx_status = (qword & I40E_RXD_QW1_STATUS_MASK)
-                                               >> I40E_RXD_QW1_STATUS_SHIFT;
+               rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
+                           I40E_RXD_QW1_STATUS_SHIFT;
        }
 
        rx_ring->next_to_clean = i;
@@ -1270,7 +1334,7 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
                tx_flags |= vlan_tx_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT;
                tx_flags |= I40E_TX_FLAGS_HW_VLAN;
        /* else if it is a SW VLAN, check the next protocol and store the tag */
-       } else if (protocol == __constant_htons(ETH_P_8021Q)) {
+       } else if (protocol == htons(ETH_P_8021Q)) {
                struct vlan_hdr *vhdr, _vhdr;
                vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr);
                if (!vhdr)
@@ -1335,7 +1399,7 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
                        return err;
        }
 
-       if (protocol == __constant_htons(ETH_P_IP)) {
+       if (protocol == htons(ETH_P_IP)) {
                iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb);
                tcph = skb->encapsulation ? inner_tcp_hdr(skb) : tcp_hdr(skb);
                iph->tot_len = 0;
@@ -1361,10 +1425,50 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
        cd_cmd = I40E_TX_CTX_DESC_TSO;
        cd_tso_len = skb->len - *hdr_len;
        cd_mss = skb_shinfo(skb)->gso_size;
-       *cd_type_cmd_tso_mss |= ((u64)cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT)
-                            | ((u64)cd_tso_len
-                               << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT)
-                            | ((u64)cd_mss << I40E_TXD_CTX_QW1_MSS_SHIFT);
+       *cd_type_cmd_tso_mss |= ((u64)cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |
+                               ((u64)cd_tso_len <<
+                                I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
+                               ((u64)cd_mss << I40E_TXD_CTX_QW1_MSS_SHIFT);
+       return 1;
+}
+
+/**
+ * i40e_tsyn - set up the tsyn context descriptor
+ * @tx_ring:  ptr to the ring to send
+ * @skb:      ptr to the skb we're sending
+ * @tx_flags: the collected send information
+ *
+ * Returns 0 if no Tx timestamp can happen and 1 if the timestamp will happen
+ **/
+static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
+                    u32 tx_flags, u64 *cd_type_cmd_tso_mss)
+{
+       struct i40e_pf *pf;
+
+       if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)))
+               return 0;
+
+       /* Tx timestamps cannot be sampled when doing TSO */
+       if (tx_flags & I40E_TX_FLAGS_TSO)
+               return 0;
+
+       /* only timestamp the outbound packet if the user has requested it and
+        * we are not already transmitting a packet to be timestamped
+        */
+       pf = i40e_netdev_to_pf(tx_ring->netdev);
+       if (pf->ptp_tx && !pf->ptp_tx_skb) {
+               skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+               pf->ptp_tx_skb = skb_get(skb);
+       } else {
+               return 0;
+       }
+
+       *cd_type_cmd_tso_mss |= (u64)I40E_TX_CTX_DESC_TSYN <<
+                               I40E_TXD_CTX_QW1_CMD_SHIFT;
+
+       pf->ptp_tx_start = jiffies;
+       schedule_work(&pf->ptp_tx_work);
+
        return 1;
 }
 
@@ -1662,6 +1766,7 @@ dma_error:
 static inline int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
 {
        netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+       /* Memory barrier before checking head and tail */
        smp_mb();
 
        /* Check again in a case another CPU has just made room available. */
@@ -1743,6 +1848,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
        __be16 protocol;
        u32 td_cmd = 0;
        u8 hdr_len = 0;
+       int tsyn;
        int tso;
        if (0 == i40e_xmit_descriptor_count(skb, tx_ring))
                return NETDEV_TX_BUSY;
@@ -1758,9 +1864,9 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
        first = &tx_ring->tx_bi[tx_ring->next_to_use];
 
        /* setup IPv4/IPv6 offloads */
-       if (protocol == __constant_htons(ETH_P_IP))
+       if (protocol == htons(ETH_P_IP))
                tx_flags |= I40E_TX_FLAGS_IPV4;
-       else if (protocol == __constant_htons(ETH_P_IPV6))
+       else if (protocol == htons(ETH_P_IPV6))
                tx_flags |= I40E_TX_FLAGS_IPV6;
 
        tso = i40e_tso(tx_ring, skb, tx_flags, protocol, &hdr_len,
@@ -1773,6 +1879,11 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
 
        skb_tx_timestamp(skb);
 
+       tsyn = i40e_tsyn(tx_ring, skb, tx_flags, &cd_type_cmd_tso_mss);
+
+       if (tsyn)
+               tx_flags |= I40E_TX_FLAGS_TSYN;
+
        /* always enable CRC insertion offload */
        td_cmd |= I40E_TX_DESC_CMD_ICRC;
 
index faabf22fbd202751343053daf839f7edf838191b..d5349698e513b511a8ac9e5e6c798d888cdce409 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
  *
  ******************************************************************************/
 
+#ifndef _I40E_TXRX_H_
+#define _I40E_TXRX_H_
+
 /* Interrupt Throttling and Rate Limiting (storm control) Goodies */
 
-#define I40E_MAX_ITR               0x07FF
-#define I40E_MIN_ITR               0x0001
-#define I40E_ITR_USEC_RESOLUTION   2
+#define I40E_MAX_ITR               0x0FF0  /* reg uses 2 usec resolution */
+#define I40E_MIN_ITR               0x0004  /* reg uses 2 usec resolution */
 #define I40E_MAX_IRATE             0x03F
 #define I40E_MIN_IRATE             0x001
 #define I40E_IRATE_USEC_RESOLUTION 4
@@ -66,6 +67,26 @@ enum i40e_dyn_idx_t {
 #define I40E_TX_ITR    I40E_IDX_ITR1
 #define I40E_PE_ITR    I40E_IDX_ITR2
 
+/* Supported RSS offloads */
+#define I40E_DEFAULT_RSS_HENA ( \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD))
+
 /* Supported Rx Buffer Sizes */
 #define I40E_RXBUFFER_512   512    /* Used for packet split */
 #define I40E_RXBUFFER_2048  2048
@@ -115,6 +136,7 @@ enum i40e_dyn_idx_t {
 #define I40E_TX_FLAGS_IPV6             (u32)(1 << 5)
 #define I40E_TX_FLAGS_FCCRC            (u32)(1 << 6)
 #define I40E_TX_FLAGS_FSO              (u32)(1 << 7)
+#define I40E_TX_FLAGS_TSYN             (u32)(1 << 8)
 #define I40E_TX_FLAGS_VLAN_MASK                0xffff0000
 #define I40E_TX_FLAGS_VLAN_PRIO_MASK   0xe0000000
 #define I40E_TX_FLAGS_VLAN_PRIO_SHIFT  29
@@ -152,8 +174,8 @@ struct i40e_tx_queue_stats {
 
 struct i40e_rx_queue_stats {
        u64 non_eop_descs;
-       u64 alloc_rx_page_failed;
-       u64 alloc_rx_buff_failed;
+       u64 alloc_page_failed;
+       u64 alloc_buff_failed;
 };
 
 enum i40e_ring_state_t {
@@ -227,6 +249,8 @@ struct i40e_ring {
        u8 atr_sample_rate;
        u8 atr_count;
 
+       unsigned long last_rx_timestamp;
+
        bool ring_active;               /* is ring online or not */
 
        /* stats structs */
@@ -275,3 +299,4 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring);
 void i40e_free_tx_resources(struct i40e_ring *tx_ring);
 void i40e_free_rx_resources(struct i40e_ring *rx_ring);
 int i40e_napi_poll(struct napi_struct *napi, int budget);
+#endif /* _I40E_TXRX_H_ */
index 72a6028d24e0dfe6243b271e9d814c1219fc495b..80cf24020f1704f51f084bad807675dfdda21499 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
                                         (d) == I40E_QSFP_B_DEVICE_ID  || \
                                         (d) == I40E_QSFP_C_DEVICE_ID)
 
-#define I40E_FW_API_VERSION_MAJOR  0x0001
-#define I40E_FW_API_VERSION_MINOR  0x0000
-
 #define I40E_MAX_VSI_QP                        16
 #define I40E_MAX_VF_VSI                        3
 #define I40E_MAX_CHAINED_RX_BUFFERS    5
+#define I40E_MAX_PF_UDP_OFFLOAD_PORTS  16
 
 /* Max default timeout in ms, */
 #define I40E_MAX_NVM_TIMEOUT           18000
 
-/* Check whether address is multicast.  This is little-endian specific check.*/
-#define I40E_IS_MULTICAST(address)     \
-       (bool)(((u8 *)(address))[0] & ((u8)0x01))
-
-/* Check whether an address is broadcast. */
-#define I40E_IS_BROADCAST(address)     \
-       ((((u8 *)(address))[0] == ((u8)0xff)) && \
-       (((u8 *)(address))[1] == ((u8)0xff)))
-
 /* Switch from mc to the 2usec global time (this is the GTIME resolution) */
 #define I40E_MS_TO_GTIME(time)         (((time) * 1000) / 2)
 
@@ -79,8 +67,6 @@
 struct i40e_hw;
 typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *);
 
-#define I40E_ETH_LENGTH_OF_ADDRESS     6
-
 /* Data type manipulation macros. */
 
 #define I40E_DESC_UNUSED(R)    \
@@ -91,7 +77,7 @@ typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *);
 #define I40E_QTX_CTL_VF_QUEUE  0x0
 #define I40E_QTX_CTL_PF_QUEUE  0x2
 
-/* debug masks */
+/* debug masks - set these bits in hw->debug_mask to control output */
 enum i40e_debug_mask {
        I40E_DEBUG_INIT                 = 0x00000001,
        I40E_DEBUG_RELEASE              = 0x00000002,
@@ -105,10 +91,10 @@ enum i40e_debug_mask {
        I40E_DEBUG_DCB                  = 0x00000400,
        I40E_DEBUG_DIAG                 = 0x00000800,
 
-       I40E_DEBUG_AQ_MESSAGE           = 0x01000000, /* for i40e_debug() */
+       I40E_DEBUG_AQ_MESSAGE           = 0x01000000,
        I40E_DEBUG_AQ_DESCRIPTOR        = 0x02000000,
        I40E_DEBUG_AQ_DESC_BUFFER       = 0x04000000,
-       I40E_DEBUG_AQ_COMMAND           = 0x06000000, /* for i40e_debug_aq() */
+       I40E_DEBUG_AQ_COMMAND           = 0x06000000,
        I40E_DEBUG_AQ                   = 0x0F000000,
 
        I40E_DEBUG_USER                 = 0xF0000000,
@@ -242,9 +228,9 @@ struct i40e_hw_capabilities {
 
 struct i40e_mac_info {
        enum i40e_mac_type type;
-       u8 addr[I40E_ETH_LENGTH_OF_ADDRESS];
-       u8 perm_addr[I40E_ETH_LENGTH_OF_ADDRESS];
-       u8 san_addr[I40E_ETH_LENGTH_OF_ADDRESS];
+       u8 addr[ETH_ALEN];
+       u8 perm_addr[ETH_ALEN];
+       u8 san_addr[ETH_ALEN];
        u16 max_fcoeq;
 };
 
@@ -512,7 +498,10 @@ enum i40e_rx_desc_status_bits {
        I40E_RX_DESC_STATUS_UMBCAST_SHIFT       = 9, /* 2 BITS */
        I40E_RX_DESC_STATUS_FLM_SHIFT           = 11,
        I40E_RX_DESC_STATUS_FLTSTAT_SHIFT       = 12, /* 2 BITS */
-       I40E_RX_DESC_STATUS_LPBK_SHIFT          = 14
+       I40E_RX_DESC_STATUS_LPBK_SHIFT          = 14,
+       I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT     = 15,
+       I40E_RX_DESC_STATUS_RESERVED_SHIFT      = 16, /* 2 BITS */
+       I40E_RX_DESC_STATUS_UDP_0_SHIFT         = 18
 };
 
 #define I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT   I40E_RX_DESC_STATUS_TSYNINDX_SHIFT
@@ -521,7 +510,7 @@ enum i40e_rx_desc_status_bits {
 
 #define I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT  I40E_RX_DESC_STATUS_TSYNVALID_SHIFT
 #define I40E_RXD_QW1_STATUS_TSYNVALID_MASK     (0x1UL << \
-                                            I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT)
+                                        I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT)
 
 enum i40e_rx_desc_fltstat_values {
        I40E_RX_DESC_FLTSTAT_NO_DATA    = 0,
@@ -558,28 +547,32 @@ enum i40e_rx_desc_error_l3l4e_fcoe_masks {
 
 /* Packet type non-ip values */
 enum i40e_rx_l2_ptype {
-       I40E_RX_PTYPE_L2_RESERVED               = 0,
-       I40E_RX_PTYPE_L2_MAC_PAY2               = 1,
-       I40E_RX_PTYPE_L2_TIMESYNC_PAY2          = 2,
-       I40E_RX_PTYPE_L2_FIP_PAY2               = 3,
-       I40E_RX_PTYPE_L2_OUI_PAY2               = 4,
-       I40E_RX_PTYPE_L2_MACCNTRL_PAY2          = 5,
-       I40E_RX_PTYPE_L2_LLDP_PAY2              = 6,
-       I40E_RX_PTYPE_L2_ECP_PAY2               = 7,
-       I40E_RX_PTYPE_L2_EVB_PAY2               = 8,
-       I40E_RX_PTYPE_L2_QCN_PAY2               = 9,
-       I40E_RX_PTYPE_L2_EAPOL_PAY2             = 10,
-       I40E_RX_PTYPE_L2_ARP                    = 11,
-       I40E_RX_PTYPE_L2_FCOE_PAY3              = 12,
-       I40E_RX_PTYPE_L2_FCOE_FCDATA_PAY3       = 13,
-       I40E_RX_PTYPE_L2_FCOE_FCRDY_PAY3        = 14,
-       I40E_RX_PTYPE_L2_FCOE_FCRSP_PAY3        = 15,
-       I40E_RX_PTYPE_L2_FCOE_FCOTHER_PA        = 16,
-       I40E_RX_PTYPE_L2_FCOE_VFT_PAY3          = 17,
-       I40E_RX_PTYPE_L2_FCOE_VFT_FCDATA        = 18,
-       I40E_RX_PTYPE_L2_FCOE_VFT_FCRDY         = 19,
-       I40E_RX_PTYPE_L2_FCOE_VFT_FCRSP         = 20,
-       I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER       = 21
+       I40E_RX_PTYPE_L2_RESERVED                       = 0,
+       I40E_RX_PTYPE_L2_MAC_PAY2                       = 1,
+       I40E_RX_PTYPE_L2_TIMESYNC_PAY2                  = 2,
+       I40E_RX_PTYPE_L2_FIP_PAY2                       = 3,
+       I40E_RX_PTYPE_L2_OUI_PAY2                       = 4,
+       I40E_RX_PTYPE_L2_MACCNTRL_PAY2                  = 5,
+       I40E_RX_PTYPE_L2_LLDP_PAY2                      = 6,
+       I40E_RX_PTYPE_L2_ECP_PAY2                       = 7,
+       I40E_RX_PTYPE_L2_EVB_PAY2                       = 8,
+       I40E_RX_PTYPE_L2_QCN_PAY2                       = 9,
+       I40E_RX_PTYPE_L2_EAPOL_PAY2                     = 10,
+       I40E_RX_PTYPE_L2_ARP                            = 11,
+       I40E_RX_PTYPE_L2_FCOE_PAY3                      = 12,
+       I40E_RX_PTYPE_L2_FCOE_FCDATA_PAY3               = 13,
+       I40E_RX_PTYPE_L2_FCOE_FCRDY_PAY3                = 14,
+       I40E_RX_PTYPE_L2_FCOE_FCRSP_PAY3                = 15,
+       I40E_RX_PTYPE_L2_FCOE_FCOTHER_PA                = 16,
+       I40E_RX_PTYPE_L2_FCOE_VFT_PAY3                  = 17,
+       I40E_RX_PTYPE_L2_FCOE_VFT_FCDATA                = 18,
+       I40E_RX_PTYPE_L2_FCOE_VFT_FCRDY                 = 19,
+       I40E_RX_PTYPE_L2_FCOE_VFT_FCRSP                 = 20,
+       I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER               = 21,
+       I40E_RX_PTYPE_GRENAT4_MAC_PAY3                  = 58,
+       I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4    = 87,
+       I40E_RX_PTYPE_GRENAT6_MAC_PAY3                  = 124,
+       I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4    = 153
 };
 
 struct i40e_rx_ptype_decoded {
@@ -1022,6 +1015,7 @@ struct i40e_hw_port_stats {
 #define I40E_SR_NVM_CONTROL_WORD               0x00
 #define I40E_SR_EMP_MODULE_PTR                 0x0F
 #define I40E_SR_NVM_IMAGE_VERSION              0x18
+#define I40E_SR_NVM_WAKE_ON_LAN                        0x19
 #define I40E_SR_ALTERNATE_SAN_MAC_ADDRESS_PTR  0x27
 #define I40E_SR_NVM_EETRACK_LO                 0x2D
 #define I40E_SR_NVM_EETRACK_HI                 0x2E
index cc6654f1dac7c8a8efdf6aa5f594a7cdaa97e4fa..22a1b69cd6464ff072248b59e6acf421da0215f0 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -142,7 +141,7 @@ struct i40e_virtchnl_vsi_resource {
        u16 num_queue_pairs;
        enum i40e_vsi_type vsi_type;
        u16 qset_handle;
-       u8 default_mac_addr[I40E_ETH_LENGTH_OF_ADDRESS];
+       u8 default_mac_addr[ETH_ALEN];
 };
 /* VF offload flags */
 #define I40E_VIRTCHNL_VF_OFFLOAD_L2    0x00000001
@@ -265,7 +264,7 @@ struct i40e_virtchnl_queue_select {
  */
 
 struct i40e_virtchnl_ether_addr {
-       u8 addr[I40E_ETH_LENGTH_OF_ADDRESS];
+       u8 addr[ETH_ALEN];
        u8 pad[2];
 };
 
index 68e1f8eff9b25e80358da8e7ebbe62854b74e0a0..d04a7766be30d1422392d3a74374b52133b73705 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -101,130 +100,6 @@ static u16 i40e_vc_get_pf_queue_id(struct i40e_vf *vf, u8 vsi_idx,
        return pf_queue_id;
 }
 
-/**
- * i40e_ctrl_vsi_tx_queue
- * @vf: pointer to the vf info
- * @vsi_idx: index of VSI in PF struct
- * @vsi_queue_id: vsi relative queue index
- * @ctrl: control flags
- *
- * enable/disable/enable check/disable check
- **/
-static int i40e_ctrl_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_idx,
-                                 u16 vsi_queue_id,
-                                 enum i40e_queue_ctrl ctrl)
-{
-       struct i40e_pf *pf = vf->pf;
-       struct i40e_hw *hw = &pf->hw;
-       bool writeback = false;
-       u16 pf_queue_id;
-       int ret = 0;
-       u32 reg;
-
-       pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, vsi_queue_id);
-       reg = rd32(hw, I40E_QTX_ENA(pf_queue_id));
-
-       switch (ctrl) {
-       case I40E_QUEUE_CTRL_ENABLE:
-               reg |= I40E_QTX_ENA_QENA_REQ_MASK;
-               writeback = true;
-               break;
-       case I40E_QUEUE_CTRL_ENABLECHECK:
-               ret = (reg & I40E_QTX_ENA_QENA_STAT_MASK) ? 0 : -EPERM;
-               break;
-       case I40E_QUEUE_CTRL_DISABLE:
-               reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
-               writeback = true;
-               break;
-       case I40E_QUEUE_CTRL_DISABLECHECK:
-               ret = (reg & I40E_QTX_ENA_QENA_STAT_MASK) ? -EPERM : 0;
-               break;
-       case I40E_QUEUE_CTRL_FASTDISABLE:
-               reg |= I40E_QTX_ENA_FAST_QDIS_MASK;
-               writeback = true;
-               break;
-       case I40E_QUEUE_CTRL_FASTDISABLECHECK:
-               ret = (reg & I40E_QTX_ENA_QENA_STAT_MASK) ? -EPERM : 0;
-               if (!ret) {
-                       reg &= ~I40E_QTX_ENA_FAST_QDIS_MASK;
-                       writeback = true;
-               }
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-
-       if (writeback) {
-               wr32(hw, I40E_QTX_ENA(pf_queue_id), reg);
-               i40e_flush(hw);
-       }
-
-       return ret;
-}
-
-/**
- * i40e_ctrl_vsi_rx_queue
- * @vf: pointer to the vf info
- * @vsi_idx: index of VSI in PF struct
- * @vsi_queue_id: vsi relative queue index
- * @ctrl: control flags
- *
- * enable/disable/enable check/disable check
- **/
-static int i40e_ctrl_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_idx,
-                                 u16 vsi_queue_id,
-                                 enum i40e_queue_ctrl ctrl)
-{
-       struct i40e_pf *pf = vf->pf;
-       struct i40e_hw *hw = &pf->hw;
-       bool writeback = false;
-       u16 pf_queue_id;
-       int ret = 0;
-       u32 reg;
-
-       pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, vsi_queue_id);
-       reg = rd32(hw, I40E_QRX_ENA(pf_queue_id));
-
-       switch (ctrl) {
-       case I40E_QUEUE_CTRL_ENABLE:
-               reg |= I40E_QRX_ENA_QENA_REQ_MASK;
-               writeback = true;
-               break;
-       case I40E_QUEUE_CTRL_ENABLECHECK:
-               ret = (reg & I40E_QRX_ENA_QENA_STAT_MASK) ? 0 : -EPERM;
-               break;
-       case I40E_QUEUE_CTRL_DISABLE:
-               reg &= ~I40E_QRX_ENA_QENA_REQ_MASK;
-               writeback = true;
-               break;
-       case I40E_QUEUE_CTRL_DISABLECHECK:
-               ret = (reg & I40E_QRX_ENA_QENA_STAT_MASK) ? -EPERM : 0;
-               break;
-       case I40E_QUEUE_CTRL_FASTDISABLE:
-               reg |= I40E_QRX_ENA_FAST_QDIS_MASK;
-               writeback = true;
-               break;
-       case I40E_QUEUE_CTRL_FASTDISABLECHECK:
-               ret = (reg & I40E_QRX_ENA_QENA_STAT_MASK) ? -EPERM : 0;
-               if (!ret) {
-                       reg &= ~I40E_QRX_ENA_FAST_QDIS_MASK;
-                       writeback = true;
-               }
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-
-       if (writeback) {
-               wr32(hw, I40E_QRX_ENA(pf_queue_id), reg);
-               i40e_flush(hw);
-       }
-
-       return ret;
-}
-
 /**
  * i40e_config_irq_link_list
  * @vf: pointer to the vf info
@@ -260,23 +135,17 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_idx,
                goto irq_list_done;
        }
        tempmap = vecmap->rxq_map;
-       vsi_queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (vsi_queue_id < I40E_MAX_VSI_QP) {
+       for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
                linklistmap |= (1 <<
                                (I40E_VIRTCHNL_SUPPORTED_QTYPES *
                                 vsi_queue_id));
-               vsi_queue_id =
-                   find_next_bit(&tempmap, I40E_MAX_VSI_QP, vsi_queue_id + 1);
        }
 
        tempmap = vecmap->txq_map;
-       vsi_queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (vsi_queue_id < I40E_MAX_VSI_QP) {
+       for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
                linklistmap |= (1 <<
                                (I40E_VIRTCHNL_SUPPORTED_QTYPES * vsi_queue_id
                                 + 1));
-               vsi_queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                            vsi_queue_id + 1);
        }
 
        next_q = find_first_bit(&linklistmap,
@@ -307,7 +176,8 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_idx,
                                       (I40E_MAX_VSI_QP *
                                        I40E_VIRTCHNL_SUPPORTED_QTYPES),
                                       next_q + 1);
-               if (next_q < (I40E_MAX_VSI_QP * I40E_VIRTCHNL_SUPPORTED_QTYPES)) {
+               if (next_q <
+                   (I40E_MAX_VSI_QP * I40E_VIRTCHNL_SUPPORTED_QTYPES)) {
                        vsi_queue_id = next_q / I40E_VIRTCHNL_SUPPORTED_QTYPES;
                        qtype = next_q % I40E_VIRTCHNL_SUPPORTED_QTYPES;
                        pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx,
@@ -499,7 +369,6 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
 {
        struct i40e_mac_filter *f = NULL;
        struct i40e_pf *pf = vf->pf;
-       struct i40e_hw *hw = &pf->hw;
        struct i40e_vsi *vsi;
        int ret = 0;
 
@@ -513,13 +382,30 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
                goto error_alloc_vsi_res;
        }
        if (type == I40E_VSI_SRIOV) {
+               u8 brdcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
                vf->lan_vsi_index = vsi->idx;
                vf->lan_vsi_id = vsi->id;
                dev_info(&pf->pdev->dev,
                         "LAN VSI index %d, VSI id %d\n",
                         vsi->idx, vsi->id);
+               /* If the port VLAN has been configured and then the
+                * VF driver was removed then the VSI port VLAN
+                * configuration was destroyed.  Check if there is
+                * a port VLAN and restore the VSI configuration if
+                * needed.
+                */
+               if (vf->port_vlan_id)
+                       i40e_vsi_add_pvid(vsi, vf->port_vlan_id);
                f = i40e_add_filter(vsi, vf->default_lan_addr.addr,
-                                   0, true, false);
+                                   vf->port_vlan_id, true, false);
+               if (!f)
+                       dev_info(&pf->pdev->dev,
+                                "Could not allocate VF MAC addr\n");
+               f = i40e_add_filter(vsi, brdcast, vf->port_vlan_id,
+                                   true, false);
+               if (!f)
+                       dev_info(&pf->pdev->dev,
+                                "Could not allocate VF broadcast filter\n");
        }
 
        if (!f) {
@@ -535,149 +421,10 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
                goto error_alloc_vsi_res;
        }
 
-       /* accept bcast pkts. by default */
-       ret = i40e_aq_set_vsi_broadcast(hw, vsi->seid, true, NULL);
-       if (ret) {
-               dev_err(&pf->pdev->dev,
-                       "set vsi bcast failed for vf %d, vsi %d, aq_err %d\n",
-                       vf->vf_id, vsi->idx, pf->hw.aq.asq_last_status);
-               ret = -EINVAL;
-       }
-
 error_alloc_vsi_res:
        return ret;
 }
 
-/**
- * i40e_reset_vf
- * @vf: pointer to the vf structure
- * @flr: VFLR was issued or not
- *
- * reset the vf
- **/
-int i40e_reset_vf(struct i40e_vf *vf, bool flr)
-{
-       int ret = -ENOENT;
-       struct i40e_pf *pf = vf->pf;
-       struct i40e_hw *hw = &pf->hw;
-       u32 reg, reg_idx, msix_vf;
-       bool rsd = false;
-       u16 pf_queue_id;
-       int i, j;
-
-       /* warn the VF */
-       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_INPROGRESS);
-
-       clear_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
-
-       /* PF triggers VFR only when VF requests, in case of
-        * VFLR, HW triggers VFR
-        */
-       if (!flr) {
-               /* reset vf using VPGEN_VFRTRIG reg */
-               reg = I40E_VPGEN_VFRTRIG_VFSWR_MASK;
-               wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
-               i40e_flush(hw);
-       }
-
-       /* poll VPGEN_VFRSTAT reg to make sure
-        * that reset is complete
-        */
-       for (i = 0; i < 4; i++) {
-               /* vf reset requires driver to first reset the
-                * vf & than poll the status register to make sure
-                * that the requested op was completed
-                * successfully
-                */
-               udelay(10);
-               reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
-               if (reg & I40E_VPGEN_VFRSTAT_VFRD_MASK) {
-                       rsd = true;
-                       break;
-               }
-       }
-
-       if (!rsd)
-               dev_err(&pf->pdev->dev, "VF reset check timeout %d\n",
-                       vf->vf_id);
-
-       /* fast disable qps */
-       for (j = 0; j < pf->vsi[vf->lan_vsi_index]->num_queue_pairs; j++) {
-               ret = i40e_ctrl_vsi_tx_queue(vf, vf->lan_vsi_index, j,
-                                            I40E_QUEUE_CTRL_FASTDISABLE);
-               ret = i40e_ctrl_vsi_rx_queue(vf, vf->lan_vsi_index, j,
-                                            I40E_QUEUE_CTRL_FASTDISABLE);
-       }
-
-       /* Queue enable/disable requires driver to
-        * first reset the vf & than poll the status register
-        * to make sure that the requested op was completed
-        * successfully
-        */
-       udelay(10);
-       for (j = 0; j < pf->vsi[vf->lan_vsi_index]->num_queue_pairs; j++) {
-               ret = i40e_ctrl_vsi_tx_queue(vf, vf->lan_vsi_index, j,
-                                            I40E_QUEUE_CTRL_FASTDISABLECHECK);
-               if (ret)
-                       dev_info(&pf->pdev->dev,
-                                "Queue control check failed on Tx queue %d of VSI %d VF %d\n",
-                                j, vf->lan_vsi_index, vf->vf_id);
-               ret = i40e_ctrl_vsi_rx_queue(vf, vf->lan_vsi_index, j,
-                                            I40E_QUEUE_CTRL_FASTDISABLECHECK);
-               if (ret)
-                       dev_info(&pf->pdev->dev,
-                                "Queue control check failed on Rx queue %d of VSI %d VF %d\n",
-                                j, vf->lan_vsi_index, vf->vf_id);
-       }
-
-       /* clear the irq settings */
-       msix_vf = pf->hw.func_caps.num_msix_vectors_vf;
-       for (i = 0; i < msix_vf; i++) {
-               /* format is same for both registers */
-               if (0 == i)
-                       reg_idx = I40E_VPINT_LNKLST0(vf->vf_id);
-               else
-                       reg_idx = I40E_VPINT_LNKLSTN(((msix_vf - 1) *
-                                                     (vf->vf_id))
-                                                    + (i - 1));
-               reg = (I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK |
-                      I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK);
-               wr32(hw, reg_idx, reg);
-               i40e_flush(hw);
-       }
-       /* disable interrupts so the VF starts in a known state */
-       for (i = 0; i < msix_vf; i++) {
-               /* format is same for both registers */
-               if (0 == i)
-                       reg_idx = I40E_VFINT_DYN_CTL0(vf->vf_id);
-               else
-                       reg_idx = I40E_VFINT_DYN_CTLN(((msix_vf - 1) *
-                                                     (vf->vf_id))
-                                                    + (i - 1));
-               wr32(hw, reg_idx, I40E_VFINT_DYN_CTLN_CLEARPBA_MASK);
-               i40e_flush(hw);
-       }
-
-       /* set the defaults for the rqctl & tqctl registers */
-       reg = (I40E_QINT_RQCTL_NEXTQ_INDX_MASK | I40E_QINT_RQCTL_ITR_INDX_MASK |
-              I40E_QINT_RQCTL_NEXTQ_TYPE_MASK);
-       for (j = 0; j < pf->vsi[vf->lan_vsi_index]->num_queue_pairs; j++) {
-               pf_queue_id = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_index, j);
-               wr32(hw, I40E_QINT_RQCTL(pf_queue_id), reg);
-               wr32(hw, I40E_QINT_TQCTL(pf_queue_id), reg);
-       }
-
-       /* clear the reset bit in the VPGEN_VFRTRIG reg */
-       reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
-       reg &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
-       wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
-       /* tell the VF the reset is done */
-       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_COMPLETED);
-       i40e_flush(hw);
-
-       return ret;
-}
-
 /**
  * i40e_enable_vf_mappings
  * @vf: pointer to the vf info
@@ -757,6 +504,9 @@ static void i40e_disable_vf_mappings(struct i40e_vf *vf)
 static void i40e_free_vf_res(struct i40e_vf *vf)
 {
        struct i40e_pf *pf = vf->pf;
+       struct i40e_hw *hw = &pf->hw;
+       u32 reg_idx, reg;
+       int i, msix_vf;
 
        /* free vsi & disconnect it from the parent uplink */
        if (vf->lan_vsi_index) {
@@ -764,7 +514,34 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
                vf->lan_vsi_index = 0;
                vf->lan_vsi_id = 0;
        }
+       msix_vf = pf->hw.func_caps.num_msix_vectors_vf + 1;
+       /* disable interrupts so the VF starts in a known state */
+       for (i = 0; i < msix_vf; i++) {
+               /* format is same for both registers */
+               if (0 == i)
+                       reg_idx = I40E_VFINT_DYN_CTL0(vf->vf_id);
+               else
+                       reg_idx = I40E_VFINT_DYN_CTLN(((msix_vf - 1) *
+                                                     (vf->vf_id))
+                                                    + (i - 1));
+               wr32(hw, reg_idx, I40E_VFINT_DYN_CTLN_CLEARPBA_MASK);
+               i40e_flush(hw);
+       }
 
+       /* clear the irq settings */
+       for (i = 0; i < msix_vf; i++) {
+               /* format is same for both registers */
+               if (0 == i)
+                       reg_idx = I40E_VPINT_LNKLST0(vf->vf_id);
+               else
+                       reg_idx = I40E_VPINT_LNKLSTN(((msix_vf - 1) *
+                                                     (vf->vf_id))
+                                                    + (i - 1));
+               reg = (I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK |
+                      I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK);
+               wr32(hw, reg_idx, reg);
+               i40e_flush(hw);
+       }
        /* reset some of the state varibles keeping
         * track of the resources
         */
@@ -806,6 +583,111 @@ error_alloc:
        return ret;
 }
 
+#define VF_DEVICE_STATUS 0xAA
+#define VF_TRANS_PENDING_MASK 0x20
+/**
+ * i40e_quiesce_vf_pci
+ * @vf: pointer to the vf structure
+ *
+ * Wait for VF PCI transactions to be cleared after reset. Returns -EIO
+ * if the transactions never clear.
+ **/
+static int i40e_quiesce_vf_pci(struct i40e_vf *vf)
+{
+       struct i40e_pf *pf = vf->pf;
+       struct i40e_hw *hw = &pf->hw;
+       int vf_abs_id, i;
+       u32 reg;
+
+       vf_abs_id = vf->vf_id + hw->func_caps.vf_base_id;
+
+       wr32(hw, I40E_PF_PCI_CIAA,
+            VF_DEVICE_STATUS | (vf_abs_id << I40E_PF_PCI_CIAA_VF_NUM_SHIFT));
+       for (i = 0; i < 100; i++) {
+               reg = rd32(hw, I40E_PF_PCI_CIAD);
+               if ((reg & VF_TRANS_PENDING_MASK) == 0)
+                       return 0;
+               udelay(1);
+       }
+       return -EIO;
+}
+
+/**
+ * i40e_reset_vf
+ * @vf: pointer to the vf structure
+ * @flr: VFLR was issued or not
+ *
+ * reset the vf
+ **/
+void i40e_reset_vf(struct i40e_vf *vf, bool flr)
+{
+       struct i40e_pf *pf = vf->pf;
+       struct i40e_hw *hw = &pf->hw;
+       bool rsd = false;
+       int i;
+       u32 reg;
+
+       /* warn the VF */
+       clear_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
+
+       /* In the case of a VFLR, the HW has already reset the VF and we
+        * just need to clean up, so don't hit the VFRTRIG register.
+        */
+       if (!flr) {
+               /* reset vf using VPGEN_VFRTRIG reg */
+               reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
+               reg |= I40E_VPGEN_VFRTRIG_VFSWR_MASK;
+               wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
+               i40e_flush(hw);
+       }
+
+       if (i40e_quiesce_vf_pci(vf))
+               dev_err(&pf->pdev->dev, "VF %d PCI transactions stuck\n",
+                       vf->vf_id);
+
+       /* poll VPGEN_VFRSTAT reg to make sure
+        * that reset is complete
+        */
+       for (i = 0; i < 100; i++) {
+               /* vf reset requires driver to first reset the
+                * vf & than poll the status register to make sure
+                * that the requested op was completed
+                * successfully
+                */
+               udelay(10);
+               reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
+               if (reg & I40E_VPGEN_VFRSTAT_VFRD_MASK) {
+                       rsd = true;
+                       break;
+               }
+       }
+
+       if (!rsd)
+               dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n",
+                       vf->vf_id);
+       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_COMPLETED);
+       /* clear the reset bit in the VPGEN_VFRTRIG reg */
+       reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
+       reg &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
+       wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
+
+       /* On initial reset, we won't have any queues */
+       if (vf->lan_vsi_index == 0)
+               goto complete_reset;
+
+       i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_index], false);
+complete_reset:
+       /* reallocate vf resources to reset the VSI state */
+       i40e_free_vf_res(vf);
+       mdelay(10);
+       i40e_alloc_vf_res(vf);
+       i40e_enable_vf_mappings(vf);
+
+       /* tell the VF the reset is done */
+       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE);
+       i40e_flush(hw);
+}
+
 /**
  * i40e_vfs_are_assigned
  * @pf: pointer to the pf structure
@@ -834,6 +716,76 @@ static bool i40e_vfs_are_assigned(struct i40e_pf *pf)
 
        return false;
 }
+#ifdef CONFIG_PCI_IOV
+
+/**
+ * i40e_enable_pf_switch_lb
+ * @pf: pointer to the pf structure
+ *
+ * enable switch loop back or die - no point in a return value
+ **/
+static void i40e_enable_pf_switch_lb(struct i40e_pf *pf)
+{
+       struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+       struct i40e_vsi_context ctxt;
+       int aq_ret;
+
+       ctxt.seid = pf->main_vsi_seid;
+       ctxt.pf_num = pf->hw.pf_id;
+       ctxt.vf_num = 0;
+       aq_ret = i40e_aq_get_vsi_params(&pf->hw, &ctxt, NULL);
+       if (aq_ret) {
+               dev_info(&pf->pdev->dev,
+                        "%s couldn't get pf vsi config, err %d, aq_err %d\n",
+                        __func__, aq_ret, pf->hw.aq.asq_last_status);
+               return;
+       }
+       ctxt.flags = I40E_AQ_VSI_TYPE_PF;
+       ctxt.info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
+       ctxt.info.switch_id |= cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB);
+
+       aq_ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
+       if (aq_ret) {
+               dev_info(&pf->pdev->dev,
+                        "%s: update vsi switch failed, aq_err=%d\n",
+                        __func__, vsi->back->hw.aq.asq_last_status);
+       }
+}
+#endif
+
+/**
+ * i40e_disable_pf_switch_lb
+ * @pf: pointer to the pf structure
+ *
+ * disable switch loop back or die - no point in a return value
+ **/
+static void i40e_disable_pf_switch_lb(struct i40e_pf *pf)
+{
+       struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+       struct i40e_vsi_context ctxt;
+       int aq_ret;
+
+       ctxt.seid = pf->main_vsi_seid;
+       ctxt.pf_num = pf->hw.pf_id;
+       ctxt.vf_num = 0;
+       aq_ret = i40e_aq_get_vsi_params(&pf->hw, &ctxt, NULL);
+       if (aq_ret) {
+               dev_info(&pf->pdev->dev,
+                        "%s couldn't get pf vsi config, err %d, aq_err %d\n",
+                        __func__, aq_ret, pf->hw.aq.asq_last_status);
+               return;
+       }
+       ctxt.flags = I40E_AQ_VSI_TYPE_PF;
+       ctxt.info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
+       ctxt.info.switch_id &= ~cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB);
+
+       aq_ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
+       if (aq_ret) {
+               dev_info(&pf->pdev->dev,
+                        "%s: update vsi switch failed, aq_err=%d\n",
+                        __func__, vsi->back->hw.aq.asq_last_status);
+       }
+}
 
 /**
  * i40e_free_vfs
@@ -844,17 +796,20 @@ static bool i40e_vfs_are_assigned(struct i40e_pf *pf)
 void i40e_free_vfs(struct i40e_pf *pf)
 {
        struct i40e_hw *hw = &pf->hw;
-       int i;
+       u32 reg_idx, bit_idx;
+       int i, tmp, vf_id;
 
        if (!pf->vf)
                return;
 
        /* Disable interrupt 0 so we don't try to handle the VFLR. */
-       wr32(hw, I40E_PFINT_DYN_CTL0, 0);
-       i40e_flush(hw);
+       i40e_irq_dynamic_disable_icr0(pf);
 
+       mdelay(10); /* let any messages in transit get finished up */
        /* free up vf resources */
-       for (i = 0; i < pf->num_alloc_vfs; i++) {
+       tmp = pf->num_alloc_vfs;
+       pf->num_alloc_vfs = 0;
+       for (i = 0; i < tmp; i++) {
                if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states))
                        i40e_free_vf_res(&pf->vf[i]);
                /* disable qp mappings */
@@ -863,20 +818,25 @@ void i40e_free_vfs(struct i40e_pf *pf)
 
        kfree(pf->vf);
        pf->vf = NULL;
-       pf->num_alloc_vfs = 0;
 
-       if (!i40e_vfs_are_assigned(pf))
+       if (!i40e_vfs_are_assigned(pf)) {
                pci_disable_sriov(pf->pdev);
-       else
+               /* Acknowledge VFLR for all VFS. Without this, VFs will fail to
+                * work correctly when SR-IOV gets re-enabled.
+                */
+               for (vf_id = 0; vf_id < tmp; vf_id++) {
+                       reg_idx = (hw->func_caps.vf_base_id + vf_id) / 32;
+                       bit_idx = (hw->func_caps.vf_base_id + vf_id) % 32;
+                       wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), (1 << bit_idx));
+               }
+               i40e_disable_pf_switch_lb(pf);
+       } else {
                dev_warn(&pf->pdev->dev,
                         "unable to disable SR-IOV because VFs are assigned.\n");
+       }
 
        /* Re-enable interrupt 0. */
-       wr32(hw, I40E_PFINT_DYN_CTL0,
-            I40E_PFINT_DYN_CTL0_INTENA_MASK |
-            I40E_PFINT_DYN_CTL0_CLEARPBA_MASK |
-            (I40E_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT));
-       i40e_flush(hw);
+       i40e_irq_dynamic_enable_icr0(pf);
 }
 
 #ifdef CONFIG_PCI_IOV
@@ -892,6 +852,9 @@ static int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
        struct i40e_vf *vfs;
        int i, ret = 0;
 
+       /* Disable interrupt 0 so we don't try to handle the VFLR. */
+       i40e_irq_dynamic_disable_icr0(pf);
+
        ret = pci_enable_sriov(pf->pdev, num_alloc_vfs);
        if (ret) {
                dev_err(&pf->pdev->dev,
@@ -915,11 +878,8 @@ static int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
 
                /* assign default capabilities */
                set_bit(I40E_VIRTCHNL_VF_CAP_L2, &vfs[i].vf_caps);
-
-               ret = i40e_alloc_vf_res(&vfs[i]);
-               i40e_reset_vf(&vfs[i], true);
-               if (ret)
-                       break;
+               /* vf resources get allocated during reset */
+               i40e_reset_vf(&vfs[i], false);
 
                /* enable vf vplan_qtable mappings */
                i40e_enable_vf_mappings(&vfs[i]);
@@ -927,10 +887,13 @@ static int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
        pf->vf = vfs;
        pf->num_alloc_vfs = num_alloc_vfs;
 
+       i40e_enable_pf_switch_lb(pf);
 err_alloc:
        if (ret)
                i40e_free_vfs(pf);
 err_iov:
+       /* Re-enable interrupt 0. */
+       i40e_irq_dynamic_enable_icr0(pf);
        return ret;
 }
 
@@ -1011,6 +974,7 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
 {
        struct i40e_pf *pf = vf->pf;
        struct i40e_hw *hw = &pf->hw;
+       int true_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
        i40e_status aq_ret;
 
        /* single place to detect unsuccessful return values */
@@ -1030,8 +994,8 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
                vf->num_valid_msgs++;
        }
 
-       aq_ret = i40e_aq_send_msg_to_vf(hw, vf->vf_id, v_opcode, v_retval,
-                                    msg, msglen, NULL);
+       aq_ret = i40e_aq_send_msg_to_vf(hw, true_vf_id, v_opcode, v_retval,
+                                       msg, msglen, NULL);
        if (aq_ret) {
                dev_err(&pf->pdev->dev,
                        "Unable to send the message to VF %d aq_err %d\n",
@@ -1146,12 +1110,10 @@ err:
  * unlike other virtchnl messages, pf driver
  * doesn't send the response back to the vf
  **/
-static int i40e_vc_reset_vf_msg(struct i40e_vf *vf)
+static void i40e_vc_reset_vf_msg(struct i40e_vf *vf)
 {
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
-               return -ENOENT;
-
-       return i40e_reset_vf(vf, false);
+       if (test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
+               i40e_reset_vf(vf, false);
 }
 
 /**
@@ -1293,27 +1255,21 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
                /* lookout for the invalid queue index */
                tempmap = map->rxq_map;
-               vsi_queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-               while (vsi_queue_id < I40E_MAX_VSI_QP) {
+               for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
                        if (!i40e_vc_isvalid_queue_id(vf, vsi_id,
                                                      vsi_queue_id)) {
                                aq_ret = I40E_ERR_PARAM;
                                goto error_param;
                        }
-                       vsi_queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                                    vsi_queue_id + 1);
                }
 
                tempmap = map->txq_map;
-               vsi_queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-               while (vsi_queue_id < I40E_MAX_VSI_QP) {
+               for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
                        if (!i40e_vc_isvalid_queue_id(vf, vsi_id,
                                                      vsi_queue_id)) {
                                aq_ret = I40E_ERR_PARAM;
                                goto error_param;
                        }
-                       vsi_queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                                    vsi_queue_id + 1);
                }
 
                i40e_config_irq_link_list(vf, vsi_id, map);
@@ -1339,8 +1295,6 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
        struct i40e_pf *pf = vf->pf;
        u16 vsi_id = vqs->vsi_id;
        i40e_status aq_ret = 0;
-       unsigned long tempmap;
-       u16 queue_id;
 
        if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
@@ -1356,66 +1310,8 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
        }
-
-       tempmap = vqs->rx_queues;
-       queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (queue_id < I40E_MAX_VSI_QP) {
-               if (!i40e_vc_isvalid_queue_id(vf, vsi_id, queue_id)) {
-                       aq_ret = I40E_ERR_PARAM;
-                       goto error_param;
-               }
-               i40e_ctrl_vsi_rx_queue(vf, vsi_id, queue_id,
-                                      I40E_QUEUE_CTRL_ENABLE);
-
-               queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                        queue_id + 1);
-       }
-
-       tempmap = vqs->tx_queues;
-       queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (queue_id < I40E_MAX_VSI_QP) {
-               if (!i40e_vc_isvalid_queue_id(vf, vsi_id, queue_id)) {
-                       aq_ret = I40E_ERR_PARAM;
-                       goto error_param;
-               }
-               i40e_ctrl_vsi_tx_queue(vf, vsi_id, queue_id,
-                                      I40E_QUEUE_CTRL_ENABLE);
-
-               queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                        queue_id + 1);
-       }
-
-       /* Poll the status register to make sure that the
-        * requested op was completed successfully
-        */
-       udelay(10);
-
-       tempmap = vqs->rx_queues;
-       queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (queue_id < I40E_MAX_VSI_QP) {
-               if (i40e_ctrl_vsi_rx_queue(vf, vsi_id, queue_id,
-                                          I40E_QUEUE_CTRL_ENABLECHECK)) {
-                       dev_err(&pf->pdev->dev,
-                               "Queue control check failed on RX queue %d of VSI %d VF %d\n",
-                               queue_id, vsi_id, vf->vf_id);
-               }
-               queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                        queue_id + 1);
-       }
-
-       tempmap = vqs->tx_queues;
-       queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (queue_id < I40E_MAX_VSI_QP) {
-               if (i40e_ctrl_vsi_tx_queue(vf, vsi_id, queue_id,
-                                          I40E_QUEUE_CTRL_ENABLECHECK)) {
-                       dev_err(&pf->pdev->dev,
-                               "Queue control check failed on TX queue %d of VSI %d VF %d\n",
-                               queue_id, vsi_id, vf->vf_id);
-               }
-               queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                        queue_id + 1);
-       }
-
+       if (i40e_vsi_control_rings(pf->vsi[vsi_id], true))
+               aq_ret = I40E_ERR_TIMEOUT;
 error_param:
        /* send the response to the vf */
        return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
@@ -1438,8 +1334,6 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
        struct i40e_pf *pf = vf->pf;
        u16 vsi_id = vqs->vsi_id;
        i40e_status aq_ret = 0;
-       unsigned long tempmap;
-       u16 queue_id;
 
        if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
@@ -1455,65 +1349,8 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
        }
-
-       tempmap = vqs->rx_queues;
-       queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (queue_id < I40E_MAX_VSI_QP) {
-               if (!i40e_vc_isvalid_queue_id(vf, vsi_id, queue_id)) {
-                       aq_ret = I40E_ERR_PARAM;
-                       goto error_param;
-               }
-               i40e_ctrl_vsi_rx_queue(vf, vsi_id, queue_id,
-                                      I40E_QUEUE_CTRL_DISABLE);
-
-               queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                        queue_id + 1);
-       }
-
-       tempmap = vqs->tx_queues;
-       queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (queue_id < I40E_MAX_VSI_QP) {
-               if (!i40e_vc_isvalid_queue_id(vf, vsi_id, queue_id)) {
-                       aq_ret = I40E_ERR_PARAM;
-                       goto error_param;
-               }
-               i40e_ctrl_vsi_tx_queue(vf, vsi_id, queue_id,
-                                      I40E_QUEUE_CTRL_DISABLE);
-
-               queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                        queue_id + 1);
-       }
-
-       /* Poll the status register to make sure that the
-        * requested op was completed successfully
-        */
-       udelay(10);
-
-       tempmap = vqs->rx_queues;
-       queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (queue_id < I40E_MAX_VSI_QP) {
-               if (i40e_ctrl_vsi_rx_queue(vf, vsi_id, queue_id,
-                                          I40E_QUEUE_CTRL_DISABLECHECK)) {
-                       dev_err(&pf->pdev->dev,
-                               "Queue control check failed on RX queue %d of VSI %d VF %d\n",
-                               queue_id, vsi_id, vf->vf_id);
-               }
-               queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                        queue_id + 1);
-       }
-
-       tempmap = vqs->tx_queues;
-       queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
-       while (queue_id < I40E_MAX_VSI_QP) {
-               if (i40e_ctrl_vsi_tx_queue(vf, vsi_id, queue_id,
-                                          I40E_QUEUE_CTRL_DISABLECHECK)) {
-                       dev_err(&pf->pdev->dev,
-                               "Queue control check failed on TX queue %d of VSI %d VF %d\n",
-                               queue_id, vsi_id, vf->vf_id);
-               }
-               queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
-                                        queue_id + 1);
-       }
+       if (i40e_vsi_control_rings(pf->vsi[vsi_id], false))
+               aq_ret = I40E_ERR_TIMEOUT;
 
 error_param:
        /* send the response to the vf */
@@ -1556,7 +1393,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
                goto error_param;
        }
        i40e_update_eth_stats(vsi);
-       memcpy(&stats, &vsi->eth_stats, sizeof(struct i40e_eth_stats));
+       stats = vsi->eth_stats;
 
 error_param:
        /* send the response back to the vf */
@@ -1564,6 +1401,40 @@ error_param:
                                      (u8 *)&stats, sizeof(stats));
 }
 
+/**
+ * i40e_check_vf_permission
+ * @vf: pointer to the vf info
+ * @macaddr: pointer to the MAC Address being checked
+ *
+ * Check if the VF has permission to add or delete unicast MAC address
+ * filters and return error code -EPERM if not.  Then check if the
+ * address filter requested is broadcast or zero and if so return
+ * an invalid MAC address error code.
+ **/
+static inline int i40e_check_vf_permission(struct i40e_vf *vf, u8 *macaddr)
+{
+       struct i40e_pf *pf = vf->pf;
+       int ret = 0;
+
+       if (is_broadcast_ether_addr(macaddr) ||
+                  is_zero_ether_addr(macaddr)) {
+               dev_err(&pf->pdev->dev, "invalid VF MAC addr %pM\n", macaddr);
+               ret = I40E_ERR_INVALID_MAC_ADDR;
+       } else if (vf->pf_set_mac && !is_multicast_ether_addr(macaddr) &&
+                  !ether_addr_equal(macaddr, vf->default_lan_addr.addr)) {
+               /* If the host VMM administrator has set the VF MAC address
+                * administratively via the ndo_set_vf_mac command then deny
+                * permission to the VF to add or delete unicast MAC addresses.
+                * The VF may request to set the MAC address filter already
+                * assigned to it so do not return an error in that case.
+                */
+               dev_err(&pf->pdev->dev,
+                       "VF attempting to override administratively set MAC address\nPlease reload the VF driver to resume normal operation\n");
+               ret = -EPERM;
+       }
+       return ret;
+}
+
 /**
  * i40e_vc_add_mac_addr_msg
  * @vf: pointer to the vf info
@@ -1579,24 +1450,20 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        u16 vsi_id = al->vsi_id;
-       i40e_status aq_ret = 0;
+       i40e_status ret = 0;
        int i;
 
        if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
            !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
-               aq_ret = I40E_ERR_PARAM;
+               ret = I40E_ERR_PARAM;
                goto error_param;
        }
 
        for (i = 0; i < al->num_elements; i++) {
-               if (is_broadcast_ether_addr(al->list[i].addr) ||
-                   is_zero_ether_addr(al->list[i].addr)) {
-                       dev_err(&pf->pdev->dev, "invalid VF MAC addr %pMAC\n",
-                               al->list[i].addr);
-                       aq_ret = I40E_ERR_PARAM;
+               ret = i40e_check_vf_permission(vf, al->list[i].addr);
+               if (ret)
                        goto error_param;
-               }
        }
        vsi = pf->vsi[vsi_id];
 
@@ -1617,7 +1484,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
                if (!f) {
                        dev_err(&pf->pdev->dev,
                                "Unable to add VF MAC filter\n");
-                       aq_ret = I40E_ERR_PARAM;
+                       ret = I40E_ERR_PARAM;
                        goto error_param;
                }
        }
@@ -1629,7 +1496,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 error_param:
        /* send the response to the vf */
        return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
-                                      aq_ret);
+                                      ret);
 }
 
 /**
@@ -1647,15 +1514,25 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        u16 vsi_id = al->vsi_id;
-       i40e_status aq_ret = 0;
+       i40e_status ret = 0;
        int i;
 
        if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
            !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
-               aq_ret = I40E_ERR_PARAM;
+               ret = I40E_ERR_PARAM;
                goto error_param;
        }
+
+       for (i = 0; i < al->num_elements; i++) {
+               if (is_broadcast_ether_addr(al->list[i].addr) ||
+                   is_zero_ether_addr(al->list[i].addr)) {
+                       dev_err(&pf->pdev->dev, "invalid VF MAC addr %pM\n",
+                               al->list[i].addr);
+                       ret = I40E_ERR_INVALID_MAC_ADDR;
+                       goto error_param;
+               }
+       }
        vsi = pf->vsi[vsi_id];
 
        /* delete addresses from the list */
@@ -1670,7 +1547,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 error_param:
        /* send the response to the vf */
        return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
-                                      aq_ret);
+                                      ret);
 }
 
 /**
@@ -1898,19 +1775,24 @@ static int i40e_vc_validate_vf_msg(struct i40e_vf *vf, u32 v_opcode,
 int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode,
                           u32 v_retval, u8 *msg, u16 msglen)
 {
-       struct i40e_vf *vf = &(pf->vf[vf_id]);
        struct i40e_hw *hw = &pf->hw;
+       int local_vf_id = vf_id - hw->func_caps.vf_base_id;
+       struct i40e_vf *vf;
        int ret;
 
        pf->vf_aq_requests++;
+       if (local_vf_id >= pf->num_alloc_vfs)
+               return -EINVAL;
+       vf = &(pf->vf[local_vf_id]);
        /* perform basic checks on the msg */
        ret = i40e_vc_validate_vf_msg(vf, v_opcode, v_retval, msg, msglen);
 
        if (ret) {
-               dev_err(&pf->pdev->dev, "invalid message from vf %d\n", vf_id);
+               dev_err(&pf->pdev->dev, "Invalid message from vf %d, opcode %d, len %d\n",
+                       local_vf_id, v_opcode, msglen);
                return ret;
        }
-       wr32(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_VFACTIVE);
+       wr32(hw, I40E_VFGEN_RSTAT1(local_vf_id), I40E_VFR_VFACTIVE);
        switch (v_opcode) {
        case I40E_VIRTCHNL_OP_VERSION:
                ret = i40e_vc_get_version_msg(vf);
@@ -1919,7 +1801,8 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode,
                ret = i40e_vc_get_vf_resources_msg(vf);
                break;
        case I40E_VIRTCHNL_OP_RESET_VF:
-               ret = i40e_vc_reset_vf_msg(vf);
+               i40e_vc_reset_vf_msg(vf);
+               ret = 0;
                break;
        case I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
                ret = i40e_vc_config_promiscuous_mode_msg(vf, msg, msglen);
@@ -1953,8 +1836,8 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode,
                break;
        case I40E_VIRTCHNL_OP_UNKNOWN:
        default:
-               dev_err(&pf->pdev->dev,
-                       "Unsupported opcode %d from vf %d\n", v_opcode, vf_id);
+               dev_err(&pf->pdev->dev, "Unsupported opcode %d from vf %d\n",
+                       v_opcode, local_vf_id);
                ret = i40e_vc_send_resp_to_vf(vf, v_opcode,
                                              I40E_ERR_NOT_IMPLEMENTED);
                break;
@@ -1990,19 +1873,7 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf)
                        /* clear the bit in GLGEN_VFLRSTAT */
                        wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), (1 << bit_idx));
 
-                       if (i40e_reset_vf(vf, true))
-                               dev_err(&pf->pdev->dev,
-                                       "Unable to reset the VF %d\n", vf_id);
-                       /* free up vf resources to destroy vsi state */
-                       i40e_free_vf_res(vf);
-
-                       /* allocate new vf resources with the default state */
-                       if (i40e_alloc_vf_res(vf))
-                               dev_err(&pf->pdev->dev,
-                                       "Unable to allocate VF resources %d\n",
-                                       vf_id);
-
-                       i40e_enable_vf_mappings(vf);
+                       i40e_reset_vf(vf, true);
                }
        }
 
@@ -2158,6 +2029,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
                goto error_param;
        }
        memcpy(vf->default_lan_addr.addr, mac, ETH_ALEN);
+       vf->pf_set_mac = true;
        dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
        ret = 0;
 
@@ -2218,7 +2090,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
                ret = i40e_vsi_add_pvid(vsi,
                                vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT));
        else
-               i40e_vlan_stripping_disable(vsi);
+               i40e_vsi_remove_pvid(vsi);
 
        if (vlan_id) {
                dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",
@@ -2238,6 +2110,10 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
                dev_err(&pf->pdev->dev, "Unable to update VF vsi context\n");
                goto error_pvid;
        }
+       /* The Port VLAN needs to be saved across resets the same as the
+        * default LAN MAC address.
+        */
+       vf->port_vlan_id = le16_to_cpu(vsi->info.pvid);
        ret = 0;
 
 error_pvid:
@@ -2269,7 +2145,6 @@ int i40e_ndo_get_vf_config(struct net_device *netdev,
                           int vf_id, struct ifla_vf_info *ivi)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_mac_filter *f, *ftmp;
        struct i40e_vsi *vsi = np->vsi;
        struct i40e_pf *pf = vsi->back;
        struct i40e_vf *vf;
@@ -2293,11 +2168,7 @@ int i40e_ndo_get_vf_config(struct net_device *netdev,
 
        ivi->vf = vf_id;
 
-       /* first entry of the list is the default ethernet address */
-       list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
-               memcpy(&ivi->mac, f->macaddr, I40E_ETH_LENGTH_OF_ADDRESS);
-               break;
-       }
+       memcpy(&ivi->mac, vf->default_lan_addr.addr, ETH_ALEN);
 
        ivi->tx_rate = 0;
        ivi->vlan = le16_to_cpu(vsi->info.pvid) & I40E_VLAN_MASK;
index 360382cf30400a6de8a626c03e7dcaa5b2dd4b6c..cc1feee36e12b69e0ffaa300a4aa8509ba97bd4b 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -12,9 +12,8 @@
  * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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".
@@ -82,6 +81,8 @@ struct i40e_vf {
 
        struct i40e_virtchnl_ether_addr default_lan_addr;
        struct i40e_virtchnl_ether_addr default_fcoe_addr;
+       u16 port_vlan_id;
+       bool pf_set_mac;        /* The VMM admin set the VF MAC address */
 
        /* VSI indices - actual VSI pointers are maintained in the PF structure
         * When assigned, these will be non-zero, because VSI 0 is always
@@ -104,7 +105,7 @@ int i40e_pci_sriov_configure(struct pci_dev *dev, int num_vfs);
 int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode,
                           u32 v_retval, u8 *msg, u16 msglen);
 int i40e_vc_process_vflr_event(struct i40e_pf *pf);
-int i40e_reset_vf(struct i40e_vf *vf, bool flr);
+void i40e_reset_vf(struct i40e_vf *vf, bool flr);
 void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
 
 /* vf configuration related iplink handlers */
diff --git a/drivers/net/ethernet/intel/i40evf/Makefile b/drivers/net/ethernet/intel/i40evf/Makefile
new file mode 100644 (file)
index 0000000..e09be37
--- /dev/null
@@ -0,0 +1,33 @@
+################################################################################
+#
+# Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+# Copyright(c) 2013 Intel Corporation.
+#
+# 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.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Contact Information:
+# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+#
+################################################################################
+
+#
+## Makefile for the Intel(R) 40GbE VF driver
+#
+#
+
+obj-$(CONFIG_I40EVF) += i40evf.o
+
+i40evf-objs := i40evf_main.o i40evf_ethtool.o i40evf_virtchnl.o \
+               i40e_txrx.o i40e_common.o i40e_adminq.o
+
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
new file mode 100644 (file)
index 0000000..5470ce9
--- /dev/null
@@ -0,0 +1,927 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#include "i40e_status.h"
+#include "i40e_type.h"
+#include "i40e_register.h"
+#include "i40e_adminq.h"
+#include "i40e_prototype.h"
+
+/**
+ *  i40e_adminq_init_regs - Initialize AdminQ registers
+ *  @hw: pointer to the hardware structure
+ *
+ *  This assumes the alloc_asq and alloc_arq functions have already been called
+ **/
+static void i40e_adminq_init_regs(struct i40e_hw *hw)
+{
+       /* set head and tail registers in our local struct */
+       if (hw->mac.type == I40E_MAC_VF) {
+               hw->aq.asq.tail = I40E_VF_ATQT1;
+               hw->aq.asq.head = I40E_VF_ATQH1;
+               hw->aq.asq.len  = I40E_VF_ATQLEN1;
+               hw->aq.arq.tail = I40E_VF_ARQT1;
+               hw->aq.arq.head = I40E_VF_ARQH1;
+               hw->aq.arq.len  = I40E_VF_ARQLEN1;
+       } else {
+               hw->aq.asq.tail = I40E_PF_ATQT;
+               hw->aq.asq.head = I40E_PF_ATQH;
+               hw->aq.asq.len  = I40E_PF_ATQLEN;
+               hw->aq.arq.tail = I40E_PF_ARQT;
+               hw->aq.arq.head = I40E_PF_ARQH;
+               hw->aq.arq.len  = I40E_PF_ARQLEN;
+       }
+}
+
+/**
+ *  i40e_alloc_adminq_asq_ring - Allocate Admin Queue send rings
+ *  @hw: pointer to the hardware structure
+ **/
+static i40e_status i40e_alloc_adminq_asq_ring(struct i40e_hw *hw)
+{
+       i40e_status ret_code;
+
+       ret_code = i40e_allocate_dma_mem(hw, &hw->aq.asq.desc_buf,
+                                        i40e_mem_atq_ring,
+                                        (hw->aq.num_asq_entries *
+                                        sizeof(struct i40e_aq_desc)),
+                                        I40E_ADMINQ_DESC_ALIGNMENT);
+       if (ret_code)
+               return ret_code;
+
+       ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.cmd_buf,
+                                         (hw->aq.num_asq_entries *
+                                         sizeof(struct i40e_asq_cmd_details)));
+       if (ret_code) {
+               i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
+               return ret_code;
+       }
+
+       return ret_code;
+}
+
+/**
+ *  i40e_alloc_adminq_arq_ring - Allocate Admin Queue receive rings
+ *  @hw: pointer to the hardware structure
+ **/
+static i40e_status i40e_alloc_adminq_arq_ring(struct i40e_hw *hw)
+{
+       i40e_status ret_code;
+
+       ret_code = i40e_allocate_dma_mem(hw, &hw->aq.arq.desc_buf,
+                                        i40e_mem_arq_ring,
+                                        (hw->aq.num_arq_entries *
+                                        sizeof(struct i40e_aq_desc)),
+                                        I40E_ADMINQ_DESC_ALIGNMENT);
+
+       return ret_code;
+}
+
+/**
+ *  i40e_free_adminq_asq - Free Admin Queue send rings
+ *  @hw: pointer to the hardware structure
+ *
+ *  This assumes the posted send buffers have already been cleaned
+ *  and de-allocated
+ **/
+static void i40e_free_adminq_asq(struct i40e_hw *hw)
+{
+       i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
+}
+
+/**
+ *  i40e_free_adminq_arq - Free Admin Queue receive rings
+ *  @hw: pointer to the hardware structure
+ *
+ *  This assumes the posted receive buffers have already been cleaned
+ *  and de-allocated
+ **/
+static void i40e_free_adminq_arq(struct i40e_hw *hw)
+{
+       i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
+}
+
+/**
+ *  i40e_alloc_arq_bufs - Allocate pre-posted buffers for the receive queue
+ *  @hw: pointer to the hardware structure
+ **/
+static i40e_status i40e_alloc_arq_bufs(struct i40e_hw *hw)
+{
+       i40e_status ret_code;
+       struct i40e_aq_desc *desc;
+       struct i40e_dma_mem *bi;
+       int i;
+
+       /* We'll be allocating the buffer info memory first, then we can
+        * allocate the mapped buffers for the event processing
+        */
+
+       /* buffer_info structures do not need alignment */
+       ret_code = i40e_allocate_virt_mem(hw, &hw->aq.arq.dma_head,
+               (hw->aq.num_arq_entries * sizeof(struct i40e_dma_mem)));
+       if (ret_code)
+               goto alloc_arq_bufs;
+       hw->aq.arq.r.arq_bi = (struct i40e_dma_mem *)hw->aq.arq.dma_head.va;
+
+       /* allocate the mapped buffers */
+       for (i = 0; i < hw->aq.num_arq_entries; i++) {
+               bi = &hw->aq.arq.r.arq_bi[i];
+               ret_code = i40e_allocate_dma_mem(hw, bi,
+                                                i40e_mem_arq_buf,
+                                                hw->aq.arq_buf_size,
+                                                I40E_ADMINQ_DESC_ALIGNMENT);
+               if (ret_code)
+                       goto unwind_alloc_arq_bufs;
+
+               /* now configure the descriptors for use */
+               desc = I40E_ADMINQ_DESC(hw->aq.arq, i);
+
+               desc->flags = cpu_to_le16(I40E_AQ_FLAG_BUF);
+               if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
+                       desc->flags |= cpu_to_le16(I40E_AQ_FLAG_LB);
+               desc->opcode = 0;
+               /* This is in accordance with Admin queue design, there is no
+                * register for buffer size configuration
+                */
+               desc->datalen = cpu_to_le16((u16)bi->size);
+               desc->retval = 0;
+               desc->cookie_high = 0;
+               desc->cookie_low = 0;
+               desc->params.external.addr_high =
+                       cpu_to_le32(upper_32_bits(bi->pa));
+               desc->params.external.addr_low =
+                       cpu_to_le32(lower_32_bits(bi->pa));
+               desc->params.external.param0 = 0;
+               desc->params.external.param1 = 0;
+       }
+
+alloc_arq_bufs:
+       return ret_code;
+
+unwind_alloc_arq_bufs:
+       /* don't try to free the one that failed... */
+       i--;
+       for (; i >= 0; i--)
+               i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
+       i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
+
+       return ret_code;
+}
+
+/**
+ *  i40e_alloc_asq_bufs - Allocate empty buffer structs for the send queue
+ *  @hw: pointer to the hardware structure
+ **/
+static i40e_status i40e_alloc_asq_bufs(struct i40e_hw *hw)
+{
+       i40e_status ret_code;
+       struct i40e_dma_mem *bi;
+       int i;
+
+       /* No mapped memory needed yet, just the buffer info structures */
+       ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.dma_head,
+               (hw->aq.num_asq_entries * sizeof(struct i40e_dma_mem)));
+       if (ret_code)
+               goto alloc_asq_bufs;
+       hw->aq.asq.r.asq_bi = (struct i40e_dma_mem *)hw->aq.asq.dma_head.va;
+
+       /* allocate the mapped buffers */
+       for (i = 0; i < hw->aq.num_asq_entries; i++) {
+               bi = &hw->aq.asq.r.asq_bi[i];
+               ret_code = i40e_allocate_dma_mem(hw, bi,
+                                                i40e_mem_asq_buf,
+                                                hw->aq.asq_buf_size,
+                                                I40E_ADMINQ_DESC_ALIGNMENT);
+               if (ret_code)
+                       goto unwind_alloc_asq_bufs;
+       }
+alloc_asq_bufs:
+       return ret_code;
+
+unwind_alloc_asq_bufs:
+       /* don't try to free the one that failed... */
+       i--;
+       for (; i >= 0; i--)
+               i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
+       i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
+
+       return ret_code;
+}
+
+/**
+ *  i40e_free_arq_bufs - Free receive queue buffer info elements
+ *  @hw: pointer to the hardware structure
+ **/
+static void i40e_free_arq_bufs(struct i40e_hw *hw)
+{
+       int i;
+
+       /* free descriptors */
+       for (i = 0; i < hw->aq.num_arq_entries; i++)
+               i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
+
+       /* free the descriptor memory */
+       i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
+
+       /* free the dma header */
+       i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
+}
+
+/**
+ *  i40e_free_asq_bufs - Free send queue buffer info elements
+ *  @hw: pointer to the hardware structure
+ **/
+static void i40e_free_asq_bufs(struct i40e_hw *hw)
+{
+       int i;
+
+       /* only unmap if the address is non-NULL */
+       for (i = 0; i < hw->aq.num_asq_entries; i++)
+               if (hw->aq.asq.r.asq_bi[i].pa)
+                       i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
+
+       /* free the buffer info list */
+       i40e_free_virt_mem(hw, &hw->aq.asq.cmd_buf);
+
+       /* free the descriptor memory */
+       i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
+
+       /* free the dma header */
+       i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
+}
+
+/**
+ *  i40e_config_asq_regs - configure ASQ registers
+ *  @hw: pointer to the hardware structure
+ *
+ *  Configure base address and length registers for the transmit queue
+ **/
+static void i40e_config_asq_regs(struct i40e_hw *hw)
+{
+       if (hw->mac.type == I40E_MAC_VF) {
+               /* configure the transmit queue */
+               wr32(hw, I40E_VF_ATQBAH1,
+                   upper_32_bits(hw->aq.asq.desc_buf.pa));
+               wr32(hw, I40E_VF_ATQBAL1,
+                   lower_32_bits(hw->aq.asq.desc_buf.pa));
+               wr32(hw, I40E_VF_ATQLEN1, (hw->aq.num_asq_entries |
+                                         I40E_VF_ATQLEN1_ATQENABLE_MASK));
+       } else {
+               /* configure the transmit queue */
+               wr32(hw, I40E_PF_ATQBAH,
+                   upper_32_bits(hw->aq.asq.desc_buf.pa));
+               wr32(hw, I40E_PF_ATQBAL,
+                   lower_32_bits(hw->aq.asq.desc_buf.pa));
+               wr32(hw, I40E_PF_ATQLEN, (hw->aq.num_asq_entries |
+                                         I40E_PF_ATQLEN_ATQENABLE_MASK));
+       }
+}
+
+/**
+ *  i40e_config_arq_regs - ARQ register configuration
+ *  @hw: pointer to the hardware structure
+ *
+ * Configure base address and length registers for the receive (event queue)
+ **/
+static void i40e_config_arq_regs(struct i40e_hw *hw)
+{
+       if (hw->mac.type == I40E_MAC_VF) {
+               /* configure the receive queue */
+               wr32(hw, I40E_VF_ARQBAH1,
+                   upper_32_bits(hw->aq.arq.desc_buf.pa));
+               wr32(hw, I40E_VF_ARQBAL1,
+                   lower_32_bits(hw->aq.arq.desc_buf.pa));
+               wr32(hw, I40E_VF_ARQLEN1, (hw->aq.num_arq_entries |
+                                         I40E_VF_ARQLEN1_ARQENABLE_MASK));
+       } else {
+               /* configure the receive queue */
+               wr32(hw, I40E_PF_ARQBAH,
+                   upper_32_bits(hw->aq.arq.desc_buf.pa));
+               wr32(hw, I40E_PF_ARQBAL,
+                   lower_32_bits(hw->aq.arq.desc_buf.pa));
+               wr32(hw, I40E_PF_ARQLEN, (hw->aq.num_arq_entries |
+                                         I40E_PF_ARQLEN_ARQENABLE_MASK));
+       }
+
+       /* Update tail in the HW to post pre-allocated buffers */
+       wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1);
+}
+
+/**
+ *  i40e_init_asq - main initialization routine for ASQ
+ *  @hw: pointer to the hardware structure
+ *
+ *  This is the main initialization routine for the Admin Send Queue
+ *  Prior to calling this function, drivers *MUST* set the following fields
+ *  in the hw->aq structure:
+ *     - hw->aq.num_asq_entries
+ *     - hw->aq.arq_buf_size
+ *
+ *  Do *NOT* hold the lock when calling this as the memory allocation routines
+ *  called are not going to be atomic context safe
+ **/
+static i40e_status i40e_init_asq(struct i40e_hw *hw)
+{
+       i40e_status ret_code = 0;
+
+       if (hw->aq.asq.count > 0) {
+               /* queue already initialized */
+               ret_code = I40E_ERR_NOT_READY;
+               goto init_adminq_exit;
+       }
+
+       /* verify input for valid configuration */
+       if ((hw->aq.num_asq_entries == 0) ||
+           (hw->aq.asq_buf_size == 0)) {
+               ret_code = I40E_ERR_CONFIG;
+               goto init_adminq_exit;
+       }
+
+       hw->aq.asq.next_to_use = 0;
+       hw->aq.asq.next_to_clean = 0;
+       hw->aq.asq.count = hw->aq.num_asq_entries;
+
+       /* allocate the ring memory */
+       ret_code = i40e_alloc_adminq_asq_ring(hw);
+       if (ret_code)
+               goto init_adminq_exit;
+
+       /* allocate buffers in the rings */
+       ret_code = i40e_alloc_asq_bufs(hw);
+       if (ret_code)
+               goto init_adminq_free_rings;
+
+       /* initialize base registers */
+       i40e_config_asq_regs(hw);
+
+       /* success! */
+       goto init_adminq_exit;
+
+init_adminq_free_rings:
+       i40e_free_adminq_asq(hw);
+
+init_adminq_exit:
+       return ret_code;
+}
+
+/**
+ *  i40e_init_arq - initialize ARQ
+ *  @hw: pointer to the hardware structure
+ *
+ *  The main initialization routine for the Admin Receive (Event) Queue.
+ *  Prior to calling this function, drivers *MUST* set the following fields
+ *  in the hw->aq structure:
+ *     - hw->aq.num_asq_entries
+ *     - hw->aq.arq_buf_size
+ *
+ *  Do *NOT* hold the lock when calling this as the memory allocation routines
+ *  called are not going to be atomic context safe
+ **/
+static i40e_status i40e_init_arq(struct i40e_hw *hw)
+{
+       i40e_status ret_code = 0;
+
+       if (hw->aq.arq.count > 0) {
+               /* queue already initialized */
+               ret_code = I40E_ERR_NOT_READY;
+               goto init_adminq_exit;
+       }
+
+       /* verify input for valid configuration */
+       if ((hw->aq.num_arq_entries == 0) ||
+           (hw->aq.arq_buf_size == 0)) {
+               ret_code = I40E_ERR_CONFIG;
+               goto init_adminq_exit;
+       }
+
+       hw->aq.arq.next_to_use = 0;
+       hw->aq.arq.next_to_clean = 0;
+       hw->aq.arq.count = hw->aq.num_arq_entries;
+
+       /* allocate the ring memory */
+       ret_code = i40e_alloc_adminq_arq_ring(hw);
+       if (ret_code)
+               goto init_adminq_exit;
+
+       /* allocate buffers in the rings */
+       ret_code = i40e_alloc_arq_bufs(hw);
+       if (ret_code)
+               goto init_adminq_free_rings;
+
+       /* initialize base registers */
+       i40e_config_arq_regs(hw);
+
+       /* success! */
+       goto init_adminq_exit;
+
+init_adminq_free_rings:
+       i40e_free_adminq_arq(hw);
+
+init_adminq_exit:
+       return ret_code;
+}
+
+/**
+ *  i40e_shutdown_asq - shutdown the ASQ
+ *  @hw: pointer to the hardware structure
+ *
+ *  The main shutdown routine for the Admin Send Queue
+ **/
+static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
+{
+       i40e_status ret_code = 0;
+
+       if (hw->aq.asq.count == 0)
+               return I40E_ERR_NOT_READY;
+
+       /* Stop firmware AdminQ processing */
+       wr32(hw, hw->aq.asq.head, 0);
+       wr32(hw, hw->aq.asq.tail, 0);
+       wr32(hw, hw->aq.asq.len, 0);
+
+       /* make sure lock is available */
+       mutex_lock(&hw->aq.asq_mutex);
+
+       hw->aq.asq.count = 0; /* to indicate uninitialized queue */
+
+       /* free ring buffers */
+       i40e_free_asq_bufs(hw);
+
+       mutex_unlock(&hw->aq.asq_mutex);
+
+       return ret_code;
+}
+
+/**
+ *  i40e_shutdown_arq - shutdown ARQ
+ *  @hw: pointer to the hardware structure
+ *
+ *  The main shutdown routine for the Admin Receive Queue
+ **/
+static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
+{
+       i40e_status ret_code = 0;
+
+       if (hw->aq.arq.count == 0)
+               return I40E_ERR_NOT_READY;
+
+       /* Stop firmware AdminQ processing */
+       wr32(hw, hw->aq.arq.head, 0);
+       wr32(hw, hw->aq.arq.tail, 0);
+       wr32(hw, hw->aq.arq.len, 0);
+
+       /* make sure lock is available */
+       mutex_lock(&hw->aq.arq_mutex);
+
+       hw->aq.arq.count = 0; /* to indicate uninitialized queue */
+
+       /* free ring buffers */
+       i40e_free_arq_bufs(hw);
+
+       mutex_unlock(&hw->aq.arq_mutex);
+
+       return ret_code;
+}
+
+/**
+ *  i40evf_init_adminq - main initialization routine for Admin Queue
+ *  @hw: pointer to the hardware structure
+ *
+ *  Prior to calling this function, drivers *MUST* set the following fields
+ *  in the hw->aq structure:
+ *     - hw->aq.num_asq_entries
+ *     - hw->aq.num_arq_entries
+ *     - hw->aq.arq_buf_size
+ *     - hw->aq.asq_buf_size
+ **/
+i40e_status i40evf_init_adminq(struct i40e_hw *hw)
+{
+       i40e_status ret_code;
+
+       /* verify input for valid configuration */
+       if ((hw->aq.num_arq_entries == 0) ||
+           (hw->aq.num_asq_entries == 0) ||
+           (hw->aq.arq_buf_size == 0) ||
+           (hw->aq.asq_buf_size == 0)) {
+               ret_code = I40E_ERR_CONFIG;
+               goto init_adminq_exit;
+       }
+
+       /* initialize locks */
+       mutex_init(&hw->aq.asq_mutex);
+       mutex_init(&hw->aq.arq_mutex);
+
+       /* Set up register offsets */
+       i40e_adminq_init_regs(hw);
+
+       /* allocate the ASQ */
+       ret_code = i40e_init_asq(hw);
+       if (ret_code)
+               goto init_adminq_destroy_locks;
+
+       /* allocate the ARQ */
+       ret_code = i40e_init_arq(hw);
+       if (ret_code)
+               goto init_adminq_free_asq;
+
+       /* success! */
+       goto init_adminq_exit;
+
+init_adminq_free_asq:
+       i40e_shutdown_asq(hw);
+init_adminq_destroy_locks:
+
+init_adminq_exit:
+       return ret_code;
+}
+
+/**
+ *  i40evf_shutdown_adminq - shutdown routine for the Admin Queue
+ *  @hw: pointer to the hardware structure
+ **/
+i40e_status i40evf_shutdown_adminq(struct i40e_hw *hw)
+{
+       i40e_status ret_code = 0;
+
+       if (i40evf_check_asq_alive(hw))
+               i40evf_aq_queue_shutdown(hw, true);
+
+       i40e_shutdown_asq(hw);
+       i40e_shutdown_arq(hw);
+
+       /* destroy the locks */
+
+       return ret_code;
+}
+
+/**
+ *  i40e_clean_asq - cleans Admin send queue
+ *  @hw: pointer to the hardware structure
+ *
+ *  returns the number of free desc
+ **/
+static u16 i40e_clean_asq(struct i40e_hw *hw)
+{
+       struct i40e_adminq_ring *asq = &(hw->aq.asq);
+       struct i40e_asq_cmd_details *details;
+       u16 ntc = asq->next_to_clean;
+       struct i40e_aq_desc desc_cb;
+       struct i40e_aq_desc *desc;
+
+       desc = I40E_ADMINQ_DESC(*asq, ntc);
+       details = I40E_ADMINQ_DETAILS(*asq, ntc);
+       while (rd32(hw, hw->aq.asq.head) != ntc) {
+               if (details->callback) {
+                       I40E_ADMINQ_CALLBACK cb_func =
+                                       (I40E_ADMINQ_CALLBACK)details->callback;
+                       desc_cb = *desc;
+                       cb_func(hw, &desc_cb);
+               }
+               memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
+               memset((void *)details, 0,
+                      sizeof(struct i40e_asq_cmd_details));
+               ntc++;
+               if (ntc == asq->count)
+                       ntc = 0;
+               desc = I40E_ADMINQ_DESC(*asq, ntc);
+               details = I40E_ADMINQ_DETAILS(*asq, ntc);
+       }
+
+       asq->next_to_clean = ntc;
+
+       return I40E_DESC_UNUSED(asq);
+}
+
+/**
+ *  i40evf_asq_done - check if FW has processed the Admin Send Queue
+ *  @hw: pointer to the hw struct
+ *
+ *  Returns true if the firmware has processed all descriptors on the
+ *  admin send queue. Returns false if there are still requests pending.
+ **/
+bool i40evf_asq_done(struct i40e_hw *hw)
+{
+       /* AQ designers suggest use of head for better
+        * timing reliability than DD bit
+        */
+       return rd32(hw, hw->aq.asq.head) == hw->aq.asq.next_to_use;
+
+}
+
+/**
+ *  i40evf_asq_send_command - send command to Admin Queue
+ *  @hw: pointer to the hw struct
+ *  @desc: prefilled descriptor describing the command (non DMA mem)
+ *  @buff: buffer to use for indirect commands
+ *  @buff_size: size of buffer for indirect commands
+ *  @cmd_details: pointer to command details structure
+ *
+ *  This is the main send command driver routine for the Admin Queue send
+ *  queue.  It runs the queue, cleans the queue, etc
+ **/
+i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
+                               struct i40e_aq_desc *desc,
+                               void *buff, /* can be NULL */
+                               u16  buff_size,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       i40e_status status = 0;
+       struct i40e_dma_mem *dma_buff = NULL;
+       struct i40e_asq_cmd_details *details;
+       struct i40e_aq_desc *desc_on_ring;
+       bool cmd_completed = false;
+       u16  retval = 0;
+
+       if (hw->aq.asq.count == 0) {
+               i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+                          "AQTX: Admin queue not initialized.\n");
+               status = I40E_ERR_QUEUE_EMPTY;
+               goto asq_send_command_exit;
+       }
+
+       details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
+       if (cmd_details) {
+               *details = *cmd_details;
+
+               /* If the cmd_details are defined copy the cookie.  The
+                * cpu_to_le32 is not needed here because the data is ignored
+                * by the FW, only used by the driver
+                */
+               if (details->cookie) {
+                       desc->cookie_high =
+                               cpu_to_le32(upper_32_bits(details->cookie));
+                       desc->cookie_low =
+                               cpu_to_le32(lower_32_bits(details->cookie));
+               }
+       } else {
+               memset(details, 0, sizeof(struct i40e_asq_cmd_details));
+       }
+
+       /* clear requested flags and then set additional flags if defined */
+       desc->flags &= ~cpu_to_le16(details->flags_dis);
+       desc->flags |= cpu_to_le16(details->flags_ena);
+
+       mutex_lock(&hw->aq.asq_mutex);
+
+       if (buff_size > hw->aq.asq_buf_size) {
+               i40e_debug(hw,
+                          I40E_DEBUG_AQ_MESSAGE,
+                          "AQTX: Invalid buffer size: %d.\n",
+                          buff_size);
+               status = I40E_ERR_INVALID_SIZE;
+               goto asq_send_command_error;
+       }
+
+       if (details->postpone && !details->async) {
+               i40e_debug(hw,
+                          I40E_DEBUG_AQ_MESSAGE,
+                          "AQTX: Async flag not set along with postpone flag");
+               status = I40E_ERR_PARAM;
+               goto asq_send_command_error;
+       }
+
+       /* call clean and check queue available function to reclaim the
+        * descriptors that were processed by FW, the function returns the
+        * number of desc available
+        */
+       /* the clean function called here could be called in a separate thread
+        * in case of asynchronous completions
+        */
+       if (i40e_clean_asq(hw) == 0) {
+               i40e_debug(hw,
+                          I40E_DEBUG_AQ_MESSAGE,
+                          "AQTX: Error queue is full.\n");
+               status = I40E_ERR_ADMIN_QUEUE_FULL;
+               goto asq_send_command_error;
+       }
+
+       /* initialize the temp desc pointer with the right desc */
+       desc_on_ring = I40E_ADMINQ_DESC(hw->aq.asq, hw->aq.asq.next_to_use);
+
+       /* if the desc is available copy the temp desc to the right place */
+       *desc_on_ring = *desc;
+
+       /* if buff is not NULL assume indirect command */
+       if (buff != NULL) {
+               dma_buff = &(hw->aq.asq.r.asq_bi[hw->aq.asq.next_to_use]);
+               /* copy the user buff into the respective DMA buff */
+               memcpy(dma_buff->va, buff, buff_size);
+               desc_on_ring->datalen = cpu_to_le16(buff_size);
+
+               /* Update the address values in the desc with the pa value
+                * for respective buffer
+                */
+               desc_on_ring->params.external.addr_high =
+                               cpu_to_le32(upper_32_bits(dma_buff->pa));
+               desc_on_ring->params.external.addr_low =
+                               cpu_to_le32(lower_32_bits(dma_buff->pa));
+       }
+
+       /* bump the tail */
+       i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring, buff);
+       (hw->aq.asq.next_to_use)++;
+       if (hw->aq.asq.next_to_use == hw->aq.asq.count)
+               hw->aq.asq.next_to_use = 0;
+       if (!details->postpone)
+               wr32(hw, hw->aq.asq.tail, hw->aq.asq.next_to_use);
+
+       /* if cmd_details are not defined or async flag is not set,
+        * we need to wait for desc write back
+        */
+       if (!details->async && !details->postpone) {
+               u32 total_delay = 0;
+               u32 delay_len = 10;
+
+               do {
+                       /* AQ designers suggest use of head for better
+                        * timing reliability than DD bit
+                        */
+                       if (i40evf_asq_done(hw))
+                               break;
+                       /* ugh! delay while spin_lock */
+                       udelay(delay_len);
+                       total_delay += delay_len;
+               } while (total_delay <  I40E_ASQ_CMD_TIMEOUT);
+       }
+
+       /* if ready, copy the desc back to temp */
+       if (i40evf_asq_done(hw)) {
+               *desc = *desc_on_ring;
+               if (buff != NULL)
+                       memcpy(buff, dma_buff->va, buff_size);
+               retval = le16_to_cpu(desc->retval);
+               if (retval != 0) {
+                       i40e_debug(hw,
+                                  I40E_DEBUG_AQ_MESSAGE,
+                                  "AQTX: Command completed with error 0x%X.\n",
+                                  retval);
+                       /* strip off FW internal code */
+                       retval &= 0xff;
+               }
+               cmd_completed = true;
+               if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_OK)
+                       status = 0;
+               else
+                       status = I40E_ERR_ADMIN_QUEUE_ERROR;
+               hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
+       }
+
+       /* update the error if time out occurred */
+       if ((!cmd_completed) &&
+           (!details->async && !details->postpone)) {
+               i40e_debug(hw,
+                          I40E_DEBUG_AQ_MESSAGE,
+                          "AQTX: Writeback timeout.\n");
+               status = I40E_ERR_ADMIN_QUEUE_TIMEOUT;
+       }
+
+asq_send_command_error:
+       mutex_unlock(&hw->aq.asq_mutex);
+asq_send_command_exit:
+       return status;
+}
+
+/**
+ *  i40evf_fill_default_direct_cmd_desc - AQ descriptor helper function
+ *  @desc:     pointer to the temp descriptor (non DMA mem)
+ *  @opcode:   the opcode can be used to decide which flags to turn off or on
+ *
+ *  Fill the desc with default values
+ **/
+void i40evf_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
+                                      u16 opcode)
+{
+       /* zero out the desc */
+       memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
+       desc->opcode = cpu_to_le16(opcode);
+       desc->flags = cpu_to_le16(I40E_AQ_FLAG_SI);
+}
+
+/**
+ *  i40evf_clean_arq_element
+ *  @hw: pointer to the hw struct
+ *  @e: event info from the receive descriptor, includes any buffers
+ *  @pending: number of events that could be left to process
+ *
+ *  This function cleans one Admin Receive Queue element and returns
+ *  the contents through e.  It can also return how many events are
+ *  left to process through 'pending'
+ **/
+i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
+                                            struct i40e_arq_event_info *e,
+                                            u16 *pending)
+{
+       i40e_status ret_code = 0;
+       u16 ntc = hw->aq.arq.next_to_clean;
+       struct i40e_aq_desc *desc;
+       struct i40e_dma_mem *bi;
+       u16 desc_idx;
+       u16 datalen;
+       u16 flags;
+       u16 ntu;
+
+       /* take the lock before we start messing with the ring */
+       mutex_lock(&hw->aq.arq_mutex);
+
+       /* set next_to_use to head */
+       ntu = (rd32(hw, hw->aq.arq.head) & I40E_PF_ARQH_ARQH_MASK);
+       if (ntu == ntc) {
+               /* nothing to do - shouldn't need to update ring's values */
+               i40e_debug(hw,
+                          I40E_DEBUG_AQ_MESSAGE,
+                          "AQRX: Queue is empty.\n");
+               ret_code = I40E_ERR_ADMIN_QUEUE_NO_WORK;
+               goto clean_arq_element_out;
+       }
+
+       /* now clean the next descriptor */
+       desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
+       desc_idx = ntc;
+       i40evf_debug_aq(hw,
+                     I40E_DEBUG_AQ_COMMAND,
+                     (void *)desc,
+                     hw->aq.arq.r.arq_bi[desc_idx].va);
+
+       flags = le16_to_cpu(desc->flags);
+       if (flags & I40E_AQ_FLAG_ERR) {
+               ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
+               hw->aq.arq_last_status =
+                       (enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
+               i40e_debug(hw,
+                          I40E_DEBUG_AQ_MESSAGE,
+                          "AQRX: Event received with error 0x%X.\n",
+                          hw->aq.arq_last_status);
+       } else {
+               e->desc = *desc;
+               datalen = le16_to_cpu(desc->datalen);
+               e->msg_size = min(datalen, e->msg_size);
+               if (e->msg_buf != NULL && (e->msg_size != 0))
+                       memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
+                              e->msg_size);
+       }
+
+       /* Restore the original datalen and buffer address in the desc,
+        * FW updates datalen to indicate the event message
+        * size
+        */
+       bi = &hw->aq.arq.r.arq_bi[ntc];
+       memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
+
+       desc->flags = cpu_to_le16(I40E_AQ_FLAG_BUF);
+       if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
+               desc->flags |= cpu_to_le16(I40E_AQ_FLAG_LB);
+       desc->datalen = cpu_to_le16((u16)bi->size);
+       desc->params.external.addr_high = cpu_to_le32(upper_32_bits(bi->pa));
+       desc->params.external.addr_low = cpu_to_le32(lower_32_bits(bi->pa));
+
+       /* set tail = the last cleaned desc index. */
+       wr32(hw, hw->aq.arq.tail, ntc);
+       /* ntc is updated to tail + 1 */
+       ntc++;
+       if (ntc == hw->aq.num_arq_entries)
+               ntc = 0;
+       hw->aq.arq.next_to_clean = ntc;
+       hw->aq.arq.next_to_use = ntu;
+
+clean_arq_element_out:
+       /* Set pending if needed, unlock and return */
+       if (pending != NULL)
+               *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
+       mutex_unlock(&hw->aq.arq_mutex);
+
+       return ret_code;
+}
+
+void i40evf_resume_aq(struct i40e_hw *hw)
+{
+       /* Registers are reset after PF reset */
+       hw->aq.asq.next_to_use = 0;
+       hw->aq.asq.next_to_clean = 0;
+
+       i40e_config_asq_regs(hw);
+
+       hw->aq.arq.next_to_use = 0;
+       hw->aq.arq.next_to_clean = 0;
+
+       i40e_config_arq_regs(hw);
+}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
new file mode 100644 (file)
index 0000000..8f72c31
--- /dev/null
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_ADMINQ_H_
+#define _I40E_ADMINQ_H_
+
+#include "i40e_osdep.h"
+#include "i40e_adminq_cmd.h"
+
+#define I40E_ADMINQ_DESC(R, i)   \
+       (&(((struct i40e_aq_desc *)((R).desc_buf.va))[i]))
+
+#define I40E_ADMINQ_DESC_ALIGNMENT 4096
+
+struct i40e_adminq_ring {
+       struct i40e_virt_mem dma_head;  /* space for dma structures */
+       struct i40e_dma_mem desc_buf;   /* descriptor ring memory */
+       struct i40e_virt_mem cmd_buf;   /* command buffer memory */
+
+       union {
+               struct i40e_dma_mem *asq_bi;
+               struct i40e_dma_mem *arq_bi;
+       } r;
+
+       u16 count;              /* Number of descriptors */
+       u16 rx_buf_len;         /* Admin Receive Queue buffer length */
+
+       /* used for interrupt processing */
+       u16 next_to_use;
+       u16 next_to_clean;
+
+       /* used for queue tracking */
+       u32 head;
+       u32 tail;
+       u32 len;
+};
+
+/* ASQ transaction details */
+struct i40e_asq_cmd_details {
+       void *callback; /* cast from type I40E_ADMINQ_CALLBACK */
+       u64 cookie;
+       u16 flags_ena;
+       u16 flags_dis;
+       bool async;
+       bool postpone;
+};
+
+#define I40E_ADMINQ_DETAILS(R, i)   \
+       (&(((struct i40e_asq_cmd_details *)((R).cmd_buf.va))[i]))
+
+/* ARQ event information */
+struct i40e_arq_event_info {
+       struct i40e_aq_desc desc;
+       u16 msg_size;
+       u8 *msg_buf;
+};
+
+/* Admin Queue information */
+struct i40e_adminq_info {
+       struct i40e_adminq_ring arq;    /* receive queue */
+       struct i40e_adminq_ring asq;    /* send queue */
+       u16 num_arq_entries;            /* receive queue depth */
+       u16 num_asq_entries;            /* send queue depth */
+       u16 arq_buf_size;               /* receive queue buffer size */
+       u16 asq_buf_size;               /* send queue buffer size */
+       u16 fw_maj_ver;                 /* firmware major version */
+       u16 fw_min_ver;                 /* firmware minor version */
+       u16 api_maj_ver;                /* api major version */
+       u16 api_min_ver;                /* api minor version */
+
+       struct mutex asq_mutex; /* Send queue lock */
+       struct mutex arq_mutex; /* Receive queue lock */
+
+       /* last status values on send and receive queues */
+       enum i40e_admin_queue_err asq_last_status;
+       enum i40e_admin_queue_err arq_last_status;
+};
+
+/* general information */
+#define I40E_AQ_LARGE_BUF      512
+#define I40E_ASQ_CMD_TIMEOUT   100000  /* usecs */
+
+void i40evf_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
+                                      u16 opcode);
+
+#endif /* _I40E_ADMINQ_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
new file mode 100644 (file)
index 0000000..f7cea1b
--- /dev/null
@@ -0,0 +1,2153 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_ADMINQ_CMD_H_
+#define _I40E_ADMINQ_CMD_H_
+
+/* This header file defines the i40e Admin Queue commands and is shared between
+ * i40e Firmware and Software.
+ *
+ * This file needs to comply with the Linux Kernel coding style.
+ */
+
+#define I40E_FW_API_VERSION_MAJOR  0x0001
+#define I40E_FW_API_VERSION_MINOR  0x0001
+#define I40E_FW_API_VERSION_A0_MINOR  0x0000
+
+struct i40e_aq_desc {
+       __le16 flags;
+       __le16 opcode;
+       __le16 datalen;
+       __le16 retval;
+       __le32 cookie_high;
+       __le32 cookie_low;
+       union {
+               struct {
+                       __le32 param0;
+                       __le32 param1;
+                       __le32 param2;
+                       __le32 param3;
+               } internal;
+               struct {
+                       __le32 param0;
+                       __le32 param1;
+                       __le32 addr_high;
+                       __le32 addr_low;
+               } external;
+               u8 raw[16];
+       } params;
+};
+
+/* Flags sub-structure
+ * |0  |1  |2  |3  |4  |5  |6  |7  |8  |9  |10 |11 |12 |13 |14 |15 |
+ * |DD |CMP|ERR|VFE| * *  RESERVED * * |LB |RD |VFC|BUF|SI |EI |FE |
+ */
+
+/* command flags and offsets*/
+#define I40E_AQ_FLAG_DD_SHIFT  0
+#define I40E_AQ_FLAG_CMP_SHIFT 1
+#define I40E_AQ_FLAG_ERR_SHIFT 2
+#define I40E_AQ_FLAG_VFE_SHIFT 3
+#define I40E_AQ_FLAG_LB_SHIFT  9
+#define I40E_AQ_FLAG_RD_SHIFT  10
+#define I40E_AQ_FLAG_VFC_SHIFT 11
+#define I40E_AQ_FLAG_BUF_SHIFT 12
+#define I40E_AQ_FLAG_SI_SHIFT  13
+#define I40E_AQ_FLAG_EI_SHIFT  14
+#define I40E_AQ_FLAG_FE_SHIFT  15
+
+#define I40E_AQ_FLAG_DD  (1 << I40E_AQ_FLAG_DD_SHIFT)  /* 0x1    */
+#define I40E_AQ_FLAG_CMP (1 << I40E_AQ_FLAG_CMP_SHIFT) /* 0x2    */
+#define I40E_AQ_FLAG_ERR (1 << I40E_AQ_FLAG_ERR_SHIFT) /* 0x4    */
+#define I40E_AQ_FLAG_VFE (1 << I40E_AQ_FLAG_VFE_SHIFT) /* 0x8    */
+#define I40E_AQ_FLAG_LB  (1 << I40E_AQ_FLAG_LB_SHIFT)  /* 0x200  */
+#define I40E_AQ_FLAG_RD  (1 << I40E_AQ_FLAG_RD_SHIFT)  /* 0x400  */
+#define I40E_AQ_FLAG_VFC (1 << I40E_AQ_FLAG_VFC_SHIFT) /* 0x800  */
+#define I40E_AQ_FLAG_BUF (1 << I40E_AQ_FLAG_BUF_SHIFT) /* 0x1000 */
+#define I40E_AQ_FLAG_SI  (1 << I40E_AQ_FLAG_SI_SHIFT)  /* 0x2000 */
+#define I40E_AQ_FLAG_EI  (1 << I40E_AQ_FLAG_EI_SHIFT)  /* 0x4000 */
+#define I40E_AQ_FLAG_FE  (1 << I40E_AQ_FLAG_FE_SHIFT)  /* 0x8000 */
+
+/* error codes */
+enum i40e_admin_queue_err {
+       I40E_AQ_RC_OK       = 0,    /* success */
+       I40E_AQ_RC_EPERM    = 1,    /* Operation not permitted */
+       I40E_AQ_RC_ENOENT   = 2,    /* No such element */
+       I40E_AQ_RC_ESRCH    = 3,    /* Bad opcode */
+       I40E_AQ_RC_EINTR    = 4,    /* operation interrupted */
+       I40E_AQ_RC_EIO      = 5,    /* I/O error */
+       I40E_AQ_RC_ENXIO    = 6,    /* No such resource */
+       I40E_AQ_RC_E2BIG    = 7,    /* Arg too long */
+       I40E_AQ_RC_EAGAIN   = 8,    /* Try again */
+       I40E_AQ_RC_ENOMEM   = 9,    /* Out of memory */
+       I40E_AQ_RC_EACCES   = 10,   /* Permission denied */
+       I40E_AQ_RC_EFAULT   = 11,   /* Bad address */
+       I40E_AQ_RC_EBUSY    = 12,   /* Device or resource busy */
+       I40E_AQ_RC_EEXIST   = 13,   /* object already exists */
+       I40E_AQ_RC_EINVAL   = 14,   /* Invalid argument */
+       I40E_AQ_RC_ENOTTY   = 15,   /* Not a typewriter */
+       I40E_AQ_RC_ENOSPC   = 16,   /* No space left or alloc failure */
+       I40E_AQ_RC_ENOSYS   = 17,   /* Function not implemented */
+       I40E_AQ_RC_ERANGE   = 18,   /* Parameter out of range */
+       I40E_AQ_RC_EFLUSHED = 19,   /* Cmd flushed because of prev cmd error */
+       I40E_AQ_RC_BAD_ADDR = 20,   /* Descriptor contains a bad pointer */
+       I40E_AQ_RC_EMODE    = 21,   /* Op not allowed in current dev mode */
+       I40E_AQ_RC_EFBIG    = 22,   /* File too large */
+};
+
+/* Admin Queue command opcodes */
+enum i40e_admin_queue_opc {
+       /* aq commands */
+       i40e_aqc_opc_get_version      = 0x0001,
+       i40e_aqc_opc_driver_version   = 0x0002,
+       i40e_aqc_opc_queue_shutdown   = 0x0003,
+
+       /* resource ownership */
+       i40e_aqc_opc_request_resource = 0x0008,
+       i40e_aqc_opc_release_resource = 0x0009,
+
+       i40e_aqc_opc_list_func_capabilities = 0x000A,
+       i40e_aqc_opc_list_dev_capabilities  = 0x000B,
+
+       i40e_aqc_opc_set_cppm_configuration = 0x0103,
+       i40e_aqc_opc_set_arp_proxy_entry    = 0x0104,
+       i40e_aqc_opc_set_ns_proxy_entry     = 0x0105,
+
+       /* LAA */
+       i40e_aqc_opc_mng_laa                = 0x0106,   /* AQ obsolete */
+       i40e_aqc_opc_mac_address_read       = 0x0107,
+       i40e_aqc_opc_mac_address_write      = 0x0108,
+
+       /* PXE */
+       i40e_aqc_opc_clear_pxe_mode         = 0x0110,
+
+       /* internal switch commands */
+       i40e_aqc_opc_get_switch_config         = 0x0200,
+       i40e_aqc_opc_add_statistics            = 0x0201,
+       i40e_aqc_opc_remove_statistics         = 0x0202,
+       i40e_aqc_opc_set_port_parameters       = 0x0203,
+       i40e_aqc_opc_get_switch_resource_alloc = 0x0204,
+
+       i40e_aqc_opc_add_vsi                = 0x0210,
+       i40e_aqc_opc_update_vsi_parameters  = 0x0211,
+       i40e_aqc_opc_get_vsi_parameters     = 0x0212,
+
+       i40e_aqc_opc_add_pv                = 0x0220,
+       i40e_aqc_opc_update_pv_parameters  = 0x0221,
+       i40e_aqc_opc_get_pv_parameters     = 0x0222,
+
+       i40e_aqc_opc_add_veb               = 0x0230,
+       i40e_aqc_opc_update_veb_parameters = 0x0231,
+       i40e_aqc_opc_get_veb_parameters    = 0x0232,
+
+       i40e_aqc_opc_delete_element  = 0x0243,
+
+       i40e_aqc_opc_add_macvlan                  = 0x0250,
+       i40e_aqc_opc_remove_macvlan               = 0x0251,
+       i40e_aqc_opc_add_vlan                     = 0x0252,
+       i40e_aqc_opc_remove_vlan                  = 0x0253,
+       i40e_aqc_opc_set_vsi_promiscuous_modes    = 0x0254,
+       i40e_aqc_opc_add_tag                      = 0x0255,
+       i40e_aqc_opc_remove_tag                   = 0x0256,
+       i40e_aqc_opc_add_multicast_etag           = 0x0257,
+       i40e_aqc_opc_remove_multicast_etag        = 0x0258,
+       i40e_aqc_opc_update_tag                   = 0x0259,
+       i40e_aqc_opc_add_control_packet_filter    = 0x025A,
+       i40e_aqc_opc_remove_control_packet_filter = 0x025B,
+       i40e_aqc_opc_add_cloud_filters            = 0x025C,
+       i40e_aqc_opc_remove_cloud_filters         = 0x025D,
+
+       i40e_aqc_opc_add_mirror_rule    = 0x0260,
+       i40e_aqc_opc_delete_mirror_rule = 0x0261,
+
+       i40e_aqc_opc_set_storm_control_config = 0x0280,
+       i40e_aqc_opc_get_storm_control_config = 0x0281,
+
+       /* DCB commands */
+       i40e_aqc_opc_dcb_ignore_pfc = 0x0301,
+       i40e_aqc_opc_dcb_updated    = 0x0302,
+
+       /* TX scheduler */
+       i40e_aqc_opc_configure_vsi_bw_limit            = 0x0400,
+       i40e_aqc_opc_configure_vsi_ets_sla_bw_limit    = 0x0406,
+       i40e_aqc_opc_configure_vsi_tc_bw               = 0x0407,
+       i40e_aqc_opc_query_vsi_bw_config               = 0x0408,
+       i40e_aqc_opc_query_vsi_ets_sla_config          = 0x040A,
+       i40e_aqc_opc_configure_switching_comp_bw_limit = 0x0410,
+
+       i40e_aqc_opc_enable_switching_comp_ets             = 0x0413,
+       i40e_aqc_opc_modify_switching_comp_ets             = 0x0414,
+       i40e_aqc_opc_disable_switching_comp_ets            = 0x0415,
+       i40e_aqc_opc_configure_switching_comp_ets_bw_limit = 0x0416,
+       i40e_aqc_opc_configure_switching_comp_bw_config    = 0x0417,
+       i40e_aqc_opc_query_switching_comp_ets_config       = 0x0418,
+       i40e_aqc_opc_query_port_ets_config                 = 0x0419,
+       i40e_aqc_opc_query_switching_comp_bw_config        = 0x041A,
+       i40e_aqc_opc_suspend_port_tx                       = 0x041B,
+       i40e_aqc_opc_resume_port_tx                        = 0x041C,
+
+       /* hmc */
+       i40e_aqc_opc_query_hmc_resource_profile = 0x0500,
+       i40e_aqc_opc_set_hmc_resource_profile   = 0x0501,
+
+       /* phy commands*/
+       i40e_aqc_opc_get_phy_abilities   = 0x0600,
+       i40e_aqc_opc_set_phy_config      = 0x0601,
+       i40e_aqc_opc_set_mac_config      = 0x0603,
+       i40e_aqc_opc_set_link_restart_an = 0x0605,
+       i40e_aqc_opc_get_link_status     = 0x0607,
+       i40e_aqc_opc_set_phy_int_mask    = 0x0613,
+       i40e_aqc_opc_get_local_advt_reg  = 0x0614,
+       i40e_aqc_opc_set_local_advt_reg  = 0x0615,
+       i40e_aqc_opc_get_partner_advt    = 0x0616,
+       i40e_aqc_opc_set_lb_modes        = 0x0618,
+       i40e_aqc_opc_get_phy_wol_caps    = 0x0621,
+       i40e_aqc_opc_set_phy_reset       = 0x0622,
+       i40e_aqc_opc_upload_ext_phy_fm   = 0x0625,
+
+       /* NVM commands */
+       i40e_aqc_opc_nvm_read   = 0x0701,
+       i40e_aqc_opc_nvm_erase  = 0x0702,
+       i40e_aqc_opc_nvm_update = 0x0703,
+
+       /* virtualization commands */
+       i40e_aqc_opc_send_msg_to_pf   = 0x0801,
+       i40e_aqc_opc_send_msg_to_vf   = 0x0802,
+       i40e_aqc_opc_send_msg_to_peer = 0x0803,
+
+       /* alternate structure */
+       i40e_aqc_opc_alternate_write          = 0x0900,
+       i40e_aqc_opc_alternate_write_indirect = 0x0901,
+       i40e_aqc_opc_alternate_read           = 0x0902,
+       i40e_aqc_opc_alternate_read_indirect  = 0x0903,
+       i40e_aqc_opc_alternate_write_done     = 0x0904,
+       i40e_aqc_opc_alternate_set_mode       = 0x0905,
+       i40e_aqc_opc_alternate_clear_port     = 0x0906,
+
+       /* LLDP commands */
+       i40e_aqc_opc_lldp_get_mib    = 0x0A00,
+       i40e_aqc_opc_lldp_update_mib = 0x0A01,
+       i40e_aqc_opc_lldp_add_tlv    = 0x0A02,
+       i40e_aqc_opc_lldp_update_tlv = 0x0A03,
+       i40e_aqc_opc_lldp_delete_tlv = 0x0A04,
+       i40e_aqc_opc_lldp_stop       = 0x0A05,
+       i40e_aqc_opc_lldp_start      = 0x0A06,
+
+       /* Tunnel commands */
+       i40e_aqc_opc_add_udp_tunnel       = 0x0B00,
+       i40e_aqc_opc_del_udp_tunnel       = 0x0B01,
+       i40e_aqc_opc_tunnel_key_structure = 0x0B10,
+
+       /* Async Events */
+       i40e_aqc_opc_event_lan_overflow = 0x1001,
+
+       /* OEM commands */
+       i40e_aqc_opc_oem_parameter_change     = 0xFE00,
+       i40e_aqc_opc_oem_device_status_change = 0xFE01,
+
+       /* debug commands */
+       i40e_aqc_opc_debug_get_deviceid     = 0xFF00,
+       i40e_aqc_opc_debug_set_mode         = 0xFF01,
+       i40e_aqc_opc_debug_read_reg         = 0xFF03,
+       i40e_aqc_opc_debug_write_reg        = 0xFF04,
+       i40e_aqc_opc_debug_read_reg_sg      = 0xFF05,
+       i40e_aqc_opc_debug_write_reg_sg     = 0xFF06,
+       i40e_aqc_opc_debug_modify_reg       = 0xFF07,
+       i40e_aqc_opc_debug_dump_internals   = 0xFF08,
+       i40e_aqc_opc_debug_modify_internals = 0xFF09,
+};
+
+/* command structures and indirect data structures */
+
+/* Structure naming conventions:
+ * - no suffix for direct command descriptor structures
+ * - _data for indirect sent data
+ * - _resp for indirect return data (data which is both will use _data)
+ * - _completion for direct return data
+ * - _element_ for repeated elements (may also be _data or _resp)
+ *
+ * Command structures are expected to overlay the params.raw member of the basic
+ * descriptor, and as such cannot exceed 16 bytes in length.
+ */
+
+/* This macro is used to generate a compilation error if a structure
+ * is not exactly the correct length. It gives a divide by zero error if the
+ * structure is not of the correct size, otherwise it creates an enum that is
+ * never used.
+ */
+#define I40E_CHECK_STRUCT_LEN(n, X) enum i40e_static_assert_enum_##X \
+       { i40e_static_assert_##X = (n)/((sizeof(struct X) == (n)) ? 1 : 0) }
+
+/* This macro is used extensively to ensure that command structures are 16
+ * bytes in length as they have to map to the raw array of that size.
+ */
+#define I40E_CHECK_CMD_LENGTH(X) I40E_CHECK_STRUCT_LEN(16, X)
+
+/* internal (0x00XX) commands */
+
+/* Get version (direct 0x0001) */
+struct i40e_aqc_get_version {
+       __le32 rom_ver;
+       __le32 fw_build;
+       __le16 fw_major;
+       __le16 fw_minor;
+       __le16 api_major;
+       __le16 api_minor;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_get_version);
+
+/* Send driver version (indirect 0x0002) */
+struct i40e_aqc_driver_version {
+       u8     driver_major_ver;
+       u8     driver_minor_ver;
+       u8     driver_build_ver;
+       u8     driver_subbuild_ver;
+       u8     reserved[4];
+       __le32 address_high;
+       __le32 address_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_driver_version);
+
+/* Queue Shutdown (direct 0x0003) */
+struct i40e_aqc_queue_shutdown {
+       __le32     driver_unloading;
+#define I40E_AQ_DRIVER_UNLOADING    0x1
+       u8     reserved[12];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_queue_shutdown);
+
+/* Request resource ownership (direct 0x0008)
+ * Release resource ownership (direct 0x0009)
+ */
+#define I40E_AQ_RESOURCE_NVM               1
+#define I40E_AQ_RESOURCE_SDP               2
+#define I40E_AQ_RESOURCE_ACCESS_READ       1
+#define I40E_AQ_RESOURCE_ACCESS_WRITE      2
+#define I40E_AQ_RESOURCE_NVM_READ_TIMEOUT  3000
+#define I40E_AQ_RESOURCE_NVM_WRITE_TIMEOUT 180000
+
+struct i40e_aqc_request_resource {
+       __le16 resource_id;
+       __le16 access_type;
+       __le32 timeout;
+       __le32 resource_number;
+       u8     reserved[4];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_request_resource);
+
+/* Get function capabilities (indirect 0x000A)
+ * Get device capabilities (indirect 0x000B)
+ */
+struct i40e_aqc_list_capabilites {
+       u8 command_flags;
+#define I40E_AQ_LIST_CAP_PF_INDEX_EN     1
+       u8 pf_index;
+       u8 reserved[2];
+       __le32 count;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_list_capabilites);
+
+struct i40e_aqc_list_capabilities_element_resp {
+       __le16 id;
+       u8     major_rev;
+       u8     minor_rev;
+       __le32 number;
+       __le32 logical_id;
+       __le32 phys_id;
+       u8     reserved[16];
+};
+
+/* list of caps */
+
+#define I40E_AQ_CAP_ID_SWITCH_MODE      0x0001
+#define I40E_AQ_CAP_ID_MNG_MODE         0x0002
+#define I40E_AQ_CAP_ID_NPAR_ACTIVE      0x0003
+#define I40E_AQ_CAP_ID_OS2BMC_CAP       0x0004
+#define I40E_AQ_CAP_ID_FUNCTIONS_VALID  0x0005
+#define I40E_AQ_CAP_ID_ALTERNATE_RAM    0x0006
+#define I40E_AQ_CAP_ID_SRIOV            0x0012
+#define I40E_AQ_CAP_ID_VF               0x0013
+#define I40E_AQ_CAP_ID_VMDQ             0x0014
+#define I40E_AQ_CAP_ID_8021QBG          0x0015
+#define I40E_AQ_CAP_ID_8021QBR          0x0016
+#define I40E_AQ_CAP_ID_VSI              0x0017
+#define I40E_AQ_CAP_ID_DCB              0x0018
+#define I40E_AQ_CAP_ID_FCOE             0x0021
+#define I40E_AQ_CAP_ID_RSS              0x0040
+#define I40E_AQ_CAP_ID_RXQ              0x0041
+#define I40E_AQ_CAP_ID_TXQ              0x0042
+#define I40E_AQ_CAP_ID_MSIX             0x0043
+#define I40E_AQ_CAP_ID_VF_MSIX          0x0044
+#define I40E_AQ_CAP_ID_FLOW_DIRECTOR    0x0045
+#define I40E_AQ_CAP_ID_1588             0x0046
+#define I40E_AQ_CAP_ID_IWARP            0x0051
+#define I40E_AQ_CAP_ID_LED              0x0061
+#define I40E_AQ_CAP_ID_SDP              0x0062
+#define I40E_AQ_CAP_ID_MDIO             0x0063
+#define I40E_AQ_CAP_ID_FLEX10           0x00F1
+#define I40E_AQ_CAP_ID_CEM              0x00F2
+
+/* Set CPPM Configuration (direct 0x0103) */
+struct i40e_aqc_cppm_configuration {
+       __le16 command_flags;
+#define I40E_AQ_CPPM_EN_LTRC    0x0800
+#define I40E_AQ_CPPM_EN_DMCTH   0x1000
+#define I40E_AQ_CPPM_EN_DMCTLX  0x2000
+#define I40E_AQ_CPPM_EN_HPTC    0x4000
+#define I40E_AQ_CPPM_EN_DMARC   0x8000
+       __le16 ttlx;
+       __le32 dmacr;
+       __le16 dmcth;
+       u8     hptc;
+       u8     reserved;
+       __le32 pfltrc;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_cppm_configuration);
+
+/* Set ARP Proxy command / response (indirect 0x0104) */
+struct i40e_aqc_arp_proxy_data {
+       __le16 command_flags;
+#define I40E_AQ_ARP_INIT_IPV4           0x0008
+#define I40E_AQ_ARP_UNSUP_CTL           0x0010
+#define I40E_AQ_ARP_ENA                 0x0020
+#define I40E_AQ_ARP_ADD_IPV4            0x0040
+#define I40E_AQ_ARP_DEL_IPV4            0x0080
+       __le16 table_id;
+       __le32 pfpm_proxyfc;
+       __le32 ip_addr;
+       u8     mac_addr[6];
+};
+
+/* Set NS Proxy Table Entry Command (indirect 0x0105) */
+struct i40e_aqc_ns_proxy_data {
+       __le16 table_idx_mac_addr_0;
+       __le16 table_idx_mac_addr_1;
+       __le16 table_idx_ipv6_0;
+       __le16 table_idx_ipv6_1;
+       __le16 control;
+#define I40E_AQ_NS_PROXY_ADD_0             0x0100
+#define I40E_AQ_NS_PROXY_DEL_0             0x0200
+#define I40E_AQ_NS_PROXY_ADD_1             0x0400
+#define I40E_AQ_NS_PROXY_DEL_1             0x0800
+#define I40E_AQ_NS_PROXY_ADD_IPV6_0        0x1000
+#define I40E_AQ_NS_PROXY_DEL_IPV6_0        0x2000
+#define I40E_AQ_NS_PROXY_ADD_IPV6_1        0x4000
+#define I40E_AQ_NS_PROXY_DEL_IPV6_1        0x8000
+#define I40E_AQ_NS_PROXY_COMMAND_SEQ       0x0001
+#define I40E_AQ_NS_PROXY_INIT_IPV6_TBL     0x0002
+#define I40E_AQ_NS_PROXY_INIT_MAC_TBL      0x0004
+       u8     mac_addr_0[6];
+       u8     mac_addr_1[6];
+       u8     local_mac_addr[6];
+       u8     ipv6_addr_0[16]; /* Warning! spec specifies BE byte order */
+       u8     ipv6_addr_1[16];
+};
+
+/* Manage LAA Command (0x0106) - obsolete */
+struct i40e_aqc_mng_laa {
+       __le16  command_flags;
+#define I40E_AQ_LAA_FLAG_WR   0x8000
+       u8     reserved[2];
+       __le32 sal;
+       __le16 sah;
+       u8     reserved2[6];
+};
+
+/* Manage MAC Address Read Command (indirect 0x0107) */
+struct i40e_aqc_mac_address_read {
+       __le16  command_flags;
+#define I40E_AQC_LAN_ADDR_VALID   0x10
+#define I40E_AQC_SAN_ADDR_VALID   0x20
+#define I40E_AQC_PORT_ADDR_VALID  0x40
+#define I40E_AQC_WOL_ADDR_VALID   0x80
+#define I40E_AQC_ADDR_VALID_MASK  0xf0
+       u8     reserved[6];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_read);
+
+struct i40e_aqc_mac_address_read_data {
+       u8 pf_lan_mac[6];
+       u8 pf_san_mac[6];
+       u8 port_mac[6];
+       u8 pf_wol_mac[6];
+};
+
+I40E_CHECK_STRUCT_LEN(24, i40e_aqc_mac_address_read_data);
+
+/* Manage MAC Address Write Command (0x0108) */
+struct i40e_aqc_mac_address_write {
+       __le16 command_flags;
+#define I40E_AQC_WRITE_TYPE_LAA_ONLY    0x0000
+#define I40E_AQC_WRITE_TYPE_LAA_WOL     0x4000
+#define I40E_AQC_WRITE_TYPE_PORT        0x8000
+#define I40E_AQC_WRITE_TYPE_MASK        0xc000
+       __le16 mac_sah;
+       __le32 mac_sal;
+       u8     reserved[8];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_write);
+
+/* PXE commands (0x011x) */
+
+/* Clear PXE Command and response  (direct 0x0110) */
+struct i40e_aqc_clear_pxe {
+       u8      rx_cnt;
+       u8      reserved[15];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_clear_pxe);
+
+/* Switch configuration commands (0x02xx) */
+
+/* Used by many indirect commands that only pass an seid and a buffer in the
+ * command
+ */
+struct i40e_aqc_switch_seid {
+       __le16 seid;
+       u8     reserved[6];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_switch_seid);
+
+/* Get Switch Configuration command (indirect 0x0200)
+ * uses i40e_aqc_switch_seid for the descriptor
+ */
+struct i40e_aqc_get_switch_config_header_resp {
+       __le16 num_reported;
+       __le16 num_total;
+       u8     reserved[12];
+};
+
+struct i40e_aqc_switch_config_element_resp {
+       u8     element_type;
+#define I40E_AQ_SW_ELEM_TYPE_MAC        1
+#define I40E_AQ_SW_ELEM_TYPE_PF         2
+#define I40E_AQ_SW_ELEM_TYPE_VF         3
+#define I40E_AQ_SW_ELEM_TYPE_EMP        4
+#define I40E_AQ_SW_ELEM_TYPE_BMC        5
+#define I40E_AQ_SW_ELEM_TYPE_PV         16
+#define I40E_AQ_SW_ELEM_TYPE_VEB        17
+#define I40E_AQ_SW_ELEM_TYPE_PA         18
+#define I40E_AQ_SW_ELEM_TYPE_VSI        19
+       u8     revision;
+#define I40E_AQ_SW_ELEM_REV_1           1
+       __le16 seid;
+       __le16 uplink_seid;
+       __le16 downlink_seid;
+       u8     reserved[3];
+       u8     connection_type;
+#define I40E_AQ_CONN_TYPE_REGULAR       0x1
+#define I40E_AQ_CONN_TYPE_DEFAULT       0x2
+#define I40E_AQ_CONN_TYPE_CASCADED      0x3
+       __le16 scheduler_id;
+       __le16 element_info;
+};
+
+/* Get Switch Configuration (indirect 0x0200)
+ *    an array of elements are returned in the response buffer
+ *    the first in the array is the header, remainder are elements
+ */
+struct i40e_aqc_get_switch_config_resp {
+       struct i40e_aqc_get_switch_config_header_resp header;
+       struct i40e_aqc_switch_config_element_resp    element[1];
+};
+
+/* Add Statistics (direct 0x0201)
+ * Remove Statistics (direct 0x0202)
+ */
+struct i40e_aqc_add_remove_statistics {
+       __le16 seid;
+       __le16 vlan;
+       __le16 stat_index;
+       u8     reserved[10];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_statistics);
+
+/* Set Port Parameters command (direct 0x0203) */
+struct i40e_aqc_set_port_parameters {
+       __le16 command_flags;
+#define I40E_AQ_SET_P_PARAMS_SAVE_BAD_PACKETS   1
+#define I40E_AQ_SET_P_PARAMS_PAD_SHORT_PACKETS  2 /* must set! */
+#define I40E_AQ_SET_P_PARAMS_DOUBLE_VLAN_ENA    4
+       __le16 bad_frame_vsi;
+       __le16 default_seid;        /* reserved for command */
+       u8     reserved[10];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_set_port_parameters);
+
+/* Get Switch Resource Allocation (indirect 0x0204) */
+struct i40e_aqc_get_switch_resource_alloc {
+       u8     num_entries;         /* reserved for command */
+       u8     reserved[7];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_get_switch_resource_alloc);
+
+/* expect an array of these structs in the response buffer */
+struct i40e_aqc_switch_resource_alloc_element_resp {
+       u8     resource_type;
+#define I40E_AQ_RESOURCE_TYPE_VEB                 0x0
+#define I40E_AQ_RESOURCE_TYPE_VSI                 0x1
+#define I40E_AQ_RESOURCE_TYPE_MACADDR             0x2
+#define I40E_AQ_RESOURCE_TYPE_STAG                0x3
+#define I40E_AQ_RESOURCE_TYPE_ETAG                0x4
+#define I40E_AQ_RESOURCE_TYPE_MULTICAST_HASH      0x5
+#define I40E_AQ_RESOURCE_TYPE_UNICAST_HASH        0x6
+#define I40E_AQ_RESOURCE_TYPE_VLAN                0x7
+#define I40E_AQ_RESOURCE_TYPE_VSI_LIST_ENTRY      0x8
+#define I40E_AQ_RESOURCE_TYPE_ETAG_LIST_ENTRY     0x9
+#define I40E_AQ_RESOURCE_TYPE_VLAN_STAT_POOL      0xA
+#define I40E_AQ_RESOURCE_TYPE_MIRROR_RULE         0xB
+#define I40E_AQ_RESOURCE_TYPE_QUEUE_SETS          0xC
+#define I40E_AQ_RESOURCE_TYPE_VLAN_FILTERS        0xD
+#define I40E_AQ_RESOURCE_TYPE_INNER_MAC_FILTERS   0xF
+#define I40E_AQ_RESOURCE_TYPE_IP_FILTERS          0x10
+#define I40E_AQ_RESOURCE_TYPE_GRE_VN_KEYS         0x11
+#define I40E_AQ_RESOURCE_TYPE_VN2_KEYS            0x12
+#define I40E_AQ_RESOURCE_TYPE_TUNNEL_PORTS        0x13
+       u8     reserved1;
+       __le16 guaranteed;
+       __le16 total;
+       __le16 used;
+       __le16 total_unalloced;
+       u8     reserved2[6];
+};
+
+/* Add VSI (indirect 0x0210)
+ *    this indirect command uses struct i40e_aqc_vsi_properties_data
+ *    as the indirect buffer (128 bytes)
+ *
+ * Update VSI (indirect 0x211)
+ *     uses the same data structure as Add VSI
+ *
+ * Get VSI (indirect 0x0212)
+ *     uses the same completion and data structure as Add VSI
+ */
+struct i40e_aqc_add_get_update_vsi {
+       __le16 uplink_seid;
+       u8     connection_type;
+#define I40E_AQ_VSI_CONN_TYPE_NORMAL            0x1
+#define I40E_AQ_VSI_CONN_TYPE_DEFAULT           0x2
+#define I40E_AQ_VSI_CONN_TYPE_CASCADED          0x3
+       u8     reserved1;
+       u8     vf_id;
+       u8     reserved2;
+       __le16 vsi_flags;
+#define I40E_AQ_VSI_TYPE_SHIFT          0x0
+#define I40E_AQ_VSI_TYPE_MASK           (0x3 << I40E_AQ_VSI_TYPE_SHIFT)
+#define I40E_AQ_VSI_TYPE_VF             0x0
+#define I40E_AQ_VSI_TYPE_VMDQ2          0x1
+#define I40E_AQ_VSI_TYPE_PF             0x2
+#define I40E_AQ_VSI_TYPE_EMP_MNG        0x3
+#define I40E_AQ_VSI_FLAG_CASCADED_PV    0x4
+#define I40E_AQ_VSI_FLAG_CLOUD_VSI      0x8
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi);
+
+struct i40e_aqc_add_get_update_vsi_completion {
+       __le16 seid;
+       __le16 vsi_number;
+       __le16 vsi_used;
+       __le16 vsi_free;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi_completion);
+
+struct i40e_aqc_vsi_properties_data {
+       /* first 96 byte are written by SW */
+       __le16 valid_sections;
+#define I40E_AQ_VSI_PROP_SWITCH_VALID       0x0001
+#define I40E_AQ_VSI_PROP_SECURITY_VALID     0x0002
+#define I40E_AQ_VSI_PROP_VLAN_VALID         0x0004
+#define I40E_AQ_VSI_PROP_CAS_PV_VALID       0x0008
+#define I40E_AQ_VSI_PROP_INGRESS_UP_VALID   0x0010
+#define I40E_AQ_VSI_PROP_EGRESS_UP_VALID    0x0020
+#define I40E_AQ_VSI_PROP_QUEUE_MAP_VALID    0x0040
+#define I40E_AQ_VSI_PROP_QUEUE_OPT_VALID    0x0080
+#define I40E_AQ_VSI_PROP_OUTER_UP_VALID     0x0100
+#define I40E_AQ_VSI_PROP_SCHED_VALID        0x0200
+       /* switch section */
+       __le16 switch_id; /* 12bit id combined with flags below */
+#define I40E_AQ_VSI_SW_ID_SHIFT             0x0000
+#define I40E_AQ_VSI_SW_ID_MASK              (0xFFF << I40E_AQ_VSI_SW_ID_SHIFT)
+#define I40E_AQ_VSI_SW_ID_FLAG_NOT_STAG     0x1000
+#define I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB     0x2000
+#define I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB     0x4000
+       u8     sw_reserved[2];
+       /* security section */
+       u8     sec_flags;
+#define I40E_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD    0x01
+#define I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK    0x02
+#define I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK     0x04
+       u8     sec_reserved;
+       /* VLAN section */
+       __le16 pvid; /* VLANS include priority bits */
+       __le16 fcoe_pvid;
+       u8     port_vlan_flags;
+#define I40E_AQ_VSI_PVLAN_MODE_SHIFT        0x00
+#define I40E_AQ_VSI_PVLAN_MODE_MASK         (0x03 << \
+                                               I40E_AQ_VSI_PVLAN_MODE_SHIFT)
+#define I40E_AQ_VSI_PVLAN_MODE_TAGGED       0x01
+#define I40E_AQ_VSI_PVLAN_MODE_UNTAGGED     0x02
+#define I40E_AQ_VSI_PVLAN_MODE_ALL          0x03
+#define I40E_AQ_VSI_PVLAN_INSERT_PVID       0x04
+#define I40E_AQ_VSI_PVLAN_EMOD_SHIFT        0x03
+#define I40E_AQ_VSI_PVLAN_EMOD_MASK         (0x3 << \
+                                       I40E_AQ_VSI_PVLAN_EMOD_SHIFT)
+#define I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH     0x0
+#define I40E_AQ_VSI_PVLAN_EMOD_STR_UP       0x08
+#define I40E_AQ_VSI_PVLAN_EMOD_STR          0x10
+#define I40E_AQ_VSI_PVLAN_EMOD_NOTHING      0x18
+       u8     pvlan_reserved[3];
+       /* ingress egress up sections */
+       __le32 ingress_table; /* bitmap, 3 bits per up */
+#define I40E_AQ_VSI_UP_TABLE_UP0_SHIFT      0
+#define I40E_AQ_VSI_UP_TABLE_UP0_MASK       (0x7 << \
+                                       I40E_AQ_VSI_UP_TABLE_UP0_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP1_SHIFT      3
+#define I40E_AQ_VSI_UP_TABLE_UP1_MASK       (0x7 << \
+                                       I40E_AQ_VSI_UP_TABLE_UP1_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP2_SHIFT      6
+#define I40E_AQ_VSI_UP_TABLE_UP2_MASK       (0x7 << \
+                                       I40E_AQ_VSI_UP_TABLE_UP2_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP3_SHIFT      9
+#define I40E_AQ_VSI_UP_TABLE_UP3_MASK       (0x7 << \
+                                       I40E_AQ_VSI_UP_TABLE_UP3_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP4_SHIFT      12
+#define I40E_AQ_VSI_UP_TABLE_UP4_MASK       (0x7 << \
+                                       I40E_AQ_VSI_UP_TABLE_UP4_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP5_SHIFT      15
+#define I40E_AQ_VSI_UP_TABLE_UP5_MASK       (0x7 << \
+                                       I40E_AQ_VSI_UP_TABLE_UP5_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP6_SHIFT      18
+#define I40E_AQ_VSI_UP_TABLE_UP6_MASK       (0x7 << \
+                                       I40E_AQ_VSI_UP_TABLE_UP6_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP7_SHIFT      21
+#define I40E_AQ_VSI_UP_TABLE_UP7_MASK       (0x7 << \
+                                       I40E_AQ_VSI_UP_TABLE_UP7_SHIFT)
+       __le32 egress_table;   /* same defines as for ingress table */
+       /* cascaded PV section */
+       __le16 cas_pv_tag;
+       u8     cas_pv_flags;
+#define I40E_AQ_VSI_CAS_PV_TAGX_SHIFT      0x00
+#define I40E_AQ_VSI_CAS_PV_TAGX_MASK       (0x03 << \
+                                               I40E_AQ_VSI_CAS_PV_TAGX_SHIFT)
+#define I40E_AQ_VSI_CAS_PV_TAGX_LEAVE      0x00
+#define I40E_AQ_VSI_CAS_PV_TAGX_REMOVE     0x01
+#define I40E_AQ_VSI_CAS_PV_TAGX_COPY       0x02
+#define I40E_AQ_VSI_CAS_PV_INSERT_TAG      0x10
+#define I40E_AQ_VSI_CAS_PV_ETAG_PRUNE      0x20
+#define I40E_AQ_VSI_CAS_PV_ACCEPT_HOST_TAG 0x40
+       u8     cas_pv_reserved;
+       /* queue mapping section */
+       __le16 mapping_flags;
+#define I40E_AQ_VSI_QUE_MAP_CONTIG          0x0
+#define I40E_AQ_VSI_QUE_MAP_NONCONTIG       0x1
+       __le16 queue_mapping[16];
+#define I40E_AQ_VSI_QUEUE_SHIFT             0x0
+#define I40E_AQ_VSI_QUEUE_MASK              (0x7FF << I40E_AQ_VSI_QUEUE_SHIFT)
+       __le16 tc_mapping[8];
+#define I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT     0
+#define I40E_AQ_VSI_TC_QUE_OFFSET_MASK      (0x1FF << \
+                                               I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT)
+#define I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT     9
+#define I40E_AQ_VSI_TC_QUE_NUMBER_MASK      (0x7 << \
+                                               I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT)
+       /* queueing option section */
+       u8     queueing_opt_flags;
+#define I40E_AQ_VSI_QUE_OPT_TCP_ENA         0x10
+#define I40E_AQ_VSI_QUE_OPT_FCOE_ENA        0x20
+       u8     queueing_opt_reserved[3];
+       /* scheduler section */
+       u8     up_enable_bits;
+       u8     sched_reserved;
+       /* outer up section */
+       __le32 outer_up_table; /* same structure and defines as ingress table */
+       u8     cmd_reserved[8];
+       /* last 32 bytes are written by FW */
+       __le16 qs_handle[8];
+#define I40E_AQ_VSI_QS_HANDLE_INVALID  0xFFFF
+       __le16 stat_counter_idx;
+       __le16 sched_id;
+       u8     resp_reserved[12];
+};
+
+I40E_CHECK_STRUCT_LEN(128, i40e_aqc_vsi_properties_data);
+
+/* Add Port Virtualizer (direct 0x0220)
+ * also used for update PV (direct 0x0221) but only flags are used
+ * (IS_CTRL_PORT only works on add PV)
+ */
+struct i40e_aqc_add_update_pv {
+       __le16 command_flags;
+#define I40E_AQC_PV_FLAG_PV_TYPE                0x1
+#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_STAG_EN    0x2
+#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_ETAG_EN    0x4
+#define I40E_AQC_PV_FLAG_IS_CTRL_PORT           0x8
+       __le16 uplink_seid;
+       __le16 connected_seid;
+       u8     reserved[10];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv);
+
+struct i40e_aqc_add_update_pv_completion {
+       /* reserved for update; for add also encodes error if rc == ENOSPC */
+       __le16 pv_seid;
+#define I40E_AQC_PV_ERR_FLAG_NO_PV               0x1
+#define I40E_AQC_PV_ERR_FLAG_NO_SCHED            0x2
+#define I40E_AQC_PV_ERR_FLAG_NO_COUNTER          0x4
+#define I40E_AQC_PV_ERR_FLAG_NO_ENTRY            0x8
+       u8     reserved[14];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv_completion);
+
+/* Get PV Params (direct 0x0222)
+ * uses i40e_aqc_switch_seid for the descriptor
+ */
+
+struct i40e_aqc_get_pv_params_completion {
+       __le16 seid;
+       __le16 default_stag;
+       __le16 pv_flags; /* same flags as add_pv */
+#define I40E_AQC_GET_PV_PV_TYPE            0x1
+#define I40E_AQC_GET_PV_FRWD_UNKNOWN_STAG  0x2
+#define I40E_AQC_GET_PV_FRWD_UNKNOWN_ETAG  0x4
+       u8     reserved[8];
+       __le16 default_port_seid;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_get_pv_params_completion);
+
+/* Add VEB (direct 0x0230) */
+struct i40e_aqc_add_veb {
+       __le16 uplink_seid;
+       __le16 downlink_seid;
+       __le16 veb_flags;
+#define I40E_AQC_ADD_VEB_FLOATING           0x1
+#define I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT    1
+#define I40E_AQC_ADD_VEB_PORT_TYPE_MASK     (0x3 << \
+                                       I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT)
+#define I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT  0x2
+#define I40E_AQC_ADD_VEB_PORT_TYPE_DATA     0x4
+#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER   0x8
+       u8     enable_tcs;
+       u8     reserved[9];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb);
+
+struct i40e_aqc_add_veb_completion {
+       u8     reserved[6];
+       __le16 switch_seid;
+       /* also encodes error if rc == ENOSPC; codes are the same as add_pv */
+       __le16 veb_seid;
+#define I40E_AQC_VEB_ERR_FLAG_NO_VEB              0x1
+#define I40E_AQC_VEB_ERR_FLAG_NO_SCHED            0x2
+#define I40E_AQC_VEB_ERR_FLAG_NO_COUNTER          0x4
+#define I40E_AQC_VEB_ERR_FLAG_NO_ENTRY            0x8
+       __le16 statistic_index;
+       __le16 vebs_used;
+       __le16 vebs_free;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb_completion);
+
+/* Get VEB Parameters (direct 0x0232)
+ * uses i40e_aqc_switch_seid for the descriptor
+ */
+struct i40e_aqc_get_veb_parameters_completion {
+       __le16 seid;
+       __le16 switch_id;
+       __le16 veb_flags; /* only the first/last flags from 0x0230 is valid */
+       __le16 statistic_index;
+       __le16 vebs_used;
+       __le16 vebs_free;
+       u8     reserved[4];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_get_veb_parameters_completion);
+
+/* Delete Element (direct 0x0243)
+ * uses the generic i40e_aqc_switch_seid
+ */
+
+/* Add MAC-VLAN (indirect 0x0250) */
+
+/* used for the command for most vlan commands */
+struct i40e_aqc_macvlan {
+       __le16 num_addresses;
+       __le16 seid[3];
+#define I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT  0
+#define I40E_AQC_MACVLAN_CMD_SEID_NUM_MASK   (0x3FF << \
+                                       I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT)
+#define I40E_AQC_MACVLAN_CMD_SEID_VALID      0x8000
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_macvlan);
+
+/* indirect data for command and response */
+struct i40e_aqc_add_macvlan_element_data {
+       u8     mac_addr[6];
+       __le16 vlan_tag;
+       __le16 flags;
+#define I40E_AQC_MACVLAN_ADD_PERFECT_MATCH     0x0001
+#define I40E_AQC_MACVLAN_ADD_HASH_MATCH        0x0002
+#define I40E_AQC_MACVLAN_ADD_IGNORE_VLAN       0x0004
+#define I40E_AQC_MACVLAN_ADD_TO_QUEUE          0x0008
+       __le16 queue_number;
+#define I40E_AQC_MACVLAN_CMD_QUEUE_SHIFT  0
+#define I40E_AQC_MACVLAN_CMD_QUEUE_MASK   (0x7FF << \
+                                       I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT)
+       /* response section */
+       u8     match_method;
+#define I40E_AQC_MM_PERFECT_MATCH             0x01
+#define I40E_AQC_MM_HASH_MATCH                0x02
+#define I40E_AQC_MM_ERR_NO_RES                0xFF
+       u8     reserved1[3];
+};
+
+struct i40e_aqc_add_remove_macvlan_completion {
+       __le16 perfect_mac_used;
+       __le16 perfect_mac_free;
+       __le16 unicast_hash_free;
+       __le16 multicast_hash_free;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_macvlan_completion);
+
+/* Remove MAC-VLAN (indirect 0x0251)
+ * uses i40e_aqc_macvlan for the descriptor
+ * data points to an array of num_addresses of elements
+ */
+
+struct i40e_aqc_remove_macvlan_element_data {
+       u8     mac_addr[6];
+       __le16 vlan_tag;
+       u8     flags;
+#define I40E_AQC_MACVLAN_DEL_PERFECT_MATCH      0x01
+#define I40E_AQC_MACVLAN_DEL_HASH_MATCH         0x02
+#define I40E_AQC_MACVLAN_DEL_IGNORE_VLAN        0x08
+#define I40E_AQC_MACVLAN_DEL_ALL_VSIS           0x10
+       u8     reserved[3];
+       /* reply section */
+       u8     error_code;
+#define I40E_AQC_REMOVE_MACVLAN_SUCCESS         0x0
+#define I40E_AQC_REMOVE_MACVLAN_FAIL            0xFF
+       u8     reply_reserved[3];
+};
+
+/* Add VLAN (indirect 0x0252)
+ * Remove VLAN (indirect 0x0253)
+ * use the generic i40e_aqc_macvlan for the command
+ */
+struct i40e_aqc_add_remove_vlan_element_data {
+       __le16 vlan_tag;
+       u8     vlan_flags;
+/* flags for add VLAN */
+#define I40E_AQC_ADD_VLAN_LOCAL             0x1
+#define I40E_AQC_ADD_PVLAN_TYPE_SHIFT       1
+#define I40E_AQC_ADD_PVLAN_TYPE_MASK        (0x3 << \
+                                               I40E_AQC_ADD_PVLAN_TYPE_SHIFT)
+#define I40E_AQC_ADD_PVLAN_TYPE_REGULAR     0x0
+#define I40E_AQC_ADD_PVLAN_TYPE_PRIMARY     0x2
+#define I40E_AQC_ADD_PVLAN_TYPE_SECONDARY   0x4
+#define I40E_AQC_VLAN_PTYPE_SHIFT           3
+#define I40E_AQC_VLAN_PTYPE_MASK            (0x3 << I40E_AQC_VLAN_PTYPE_SHIFT)
+#define I40E_AQC_VLAN_PTYPE_REGULAR_VSI     0x0
+#define I40E_AQC_VLAN_PTYPE_PROMISC_VSI     0x8
+#define I40E_AQC_VLAN_PTYPE_COMMUNITY_VSI   0x10
+#define I40E_AQC_VLAN_PTYPE_ISOLATED_VSI    0x18
+/* flags for remove VLAN */
+#define I40E_AQC_REMOVE_VLAN_ALL            0x1
+       u8     reserved;
+       u8     result;
+/* flags for add VLAN */
+#define I40E_AQC_ADD_VLAN_SUCCESS       0x0
+#define I40E_AQC_ADD_VLAN_FAIL_REQUEST  0xFE
+#define I40E_AQC_ADD_VLAN_FAIL_RESOURCE 0xFF
+/* flags for remove VLAN */
+#define I40E_AQC_REMOVE_VLAN_SUCCESS    0x0
+#define I40E_AQC_REMOVE_VLAN_FAIL       0xFF
+       u8     reserved1[3];
+};
+
+struct i40e_aqc_add_remove_vlan_completion {
+       u8     reserved[4];
+       __le16 vlans_used;
+       __le16 vlans_free;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+/* Set VSI Promiscuous Modes (direct 0x0254) */
+struct i40e_aqc_set_vsi_promiscuous_modes {
+       __le16 promiscuous_flags;
+       __le16 valid_flags;
+/* flags used for both fields above */
+#define I40E_AQC_SET_VSI_PROMISC_UNICAST     0x01
+#define I40E_AQC_SET_VSI_PROMISC_MULTICAST   0x02
+#define I40E_AQC_SET_VSI_PROMISC_BROADCAST   0x04
+#define I40E_AQC_SET_VSI_DEFAULT             0x08
+#define I40E_AQC_SET_VSI_PROMISC_VLAN        0x10
+       __le16 seid;
+#define I40E_AQC_VSI_PROM_CMD_SEID_MASK      0x3FF
+       u8     reserved[10];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_set_vsi_promiscuous_modes);
+
+/* Add S/E-tag command (direct 0x0255)
+ * Uses generic i40e_aqc_add_remove_tag_completion for completion
+ */
+struct i40e_aqc_add_tag {
+       __le16 flags;
+#define I40E_AQC_ADD_TAG_FLAG_TO_QUEUE     0x0001
+       __le16 seid;
+#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT  0
+#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_MASK   (0x3FF << \
+                                       I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT)
+       __le16 tag;
+       __le16 queue_number;
+       u8     reserved[8];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_tag);
+
+struct i40e_aqc_add_remove_tag_completion {
+       u8     reserved[12];
+       __le16 tags_used;
+       __le16 tags_free;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_tag_completion);
+
+/* Remove S/E-tag command (direct 0x0256)
+ * Uses generic i40e_aqc_add_remove_tag_completion for completion
+ */
+struct i40e_aqc_remove_tag {
+       __le16 seid;
+#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT  0
+#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_MASK   (0x3FF << \
+                                       I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT)
+       __le16 tag;
+       u8     reserved[12];
+};
+
+/* Add multicast E-Tag (direct 0x0257)
+ * del multicast E-Tag (direct 0x0258) only uses pv_seid and etag fields
+ * and no external data
+ */
+struct i40e_aqc_add_remove_mcast_etag {
+       __le16 pv_seid;
+       __le16 etag;
+       u8     num_unicast_etags;
+       u8     reserved[3];
+       __le32 addr_high;          /* address of array of 2-byte s-tags */
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag);
+
+struct i40e_aqc_add_remove_mcast_etag_completion {
+       u8     reserved[4];
+       __le16 mcast_etags_used;
+       __le16 mcast_etags_free;
+       __le32 addr_high;
+       __le32 addr_low;
+
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag_completion);
+
+/* Update S/E-Tag (direct 0x0259) */
+struct i40e_aqc_update_tag {
+       __le16 seid;
+#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT  0
+#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_MASK   (0x3FF << \
+                                       I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT)
+       __le16 old_tag;
+       __le16 new_tag;
+       u8     reserved[10];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag);
+
+struct i40e_aqc_update_tag_completion {
+       u8     reserved[12];
+       __le16 tags_used;
+       __le16 tags_free;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag_completion);
+
+/* Add Control Packet filter (direct 0x025A)
+ * Remove Control Packet filter (direct 0x025B)
+ * uses the i40e_aqc_add_oveb_cloud,
+ * and the generic direct completion structure
+ */
+struct i40e_aqc_add_remove_control_packet_filter {
+       u8     mac[6];
+       __le16 etype;
+       __le16 flags;
+#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC    0x0001
+#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP          0x0002
+#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE      0x0004
+#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX            0x0008
+#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_RX            0x0000
+       __le16 seid;
+#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT  0
+#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_MASK   (0x3FF << \
+                               I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT)
+       __le16 queue;
+       u8     reserved[2];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter);
+
+struct i40e_aqc_add_remove_control_packet_filter_completion {
+       __le16 mac_etype_used;
+       __le16 etype_used;
+       __le16 mac_etype_free;
+       __le16 etype_free;
+       u8     reserved[8];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter_completion);
+
+/* Add Cloud filters (indirect 0x025C)
+ * Remove Cloud filters (indirect 0x025D)
+ * uses the i40e_aqc_add_remove_cloud_filters,
+ * and the generic indirect completion structure
+ */
+struct i40e_aqc_add_remove_cloud_filters {
+       u8     num_filters;
+       u8     reserved;
+       __le16 seid;
+#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT  0
+#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK   (0x3FF << \
+                                       I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT)
+       u8     reserved2[4];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_cloud_filters);
+
+struct i40e_aqc_add_remove_cloud_filters_element_data {
+       u8     outer_mac[6];
+       u8     inner_mac[6];
+       __le16 inner_vlan;
+       union {
+               struct {
+                       u8 reserved[12];
+                       u8 data[4];
+               } v4;
+               struct {
+                       u8 data[16];
+               } v6;
+       } ipaddr;
+       __le16 flags;
+#define I40E_AQC_ADD_CLOUD_FILTER_SHIFT                 0
+#define I40E_AQC_ADD_CLOUD_FILTER_MASK                  (0x3F << \
+                                       I40E_AQC_ADD_CLOUD_FILTER_SHIFT)
+#define I40E_AQC_ADD_CLOUD_FILTER_OIP_GRE               0x0002
+#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_GRE        0x0004
+#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_VNL        0x0007
+/* 0x0000 reserved */
+#define I40E_AQC_ADD_CLOUD_FILTER_OIP                   0x0001
+/* 0x0002 reserved */
+#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN            0x0003
+#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID     0x0004
+/* 0x0005 reserved */
+#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID           0x0006
+/* 0x0007 reserved */
+/* 0x0008 reserved */
+#define I40E_AQC_ADD_CLOUD_FILTER_OMAC                  0x0009
+#define I40E_AQC_ADD_CLOUD_FILTER_IMAC                  0x000A
+#define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC      0x000B
+#define I40E_AQC_ADD_CLOUD_FILTER_IIP                   0x000C
+
+#define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE               0x0080
+#define I40E_AQC_ADD_CLOUD_VNK_SHIFT                    6
+#define I40E_AQC_ADD_CLOUD_VNK_MASK                     0x00C0
+#define I40E_AQC_ADD_CLOUD_FLAGS_IPV4                   0
+#define I40E_AQC_ADD_CLOUD_FLAGS_IPV6                   0x0100
+
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT               9
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK                0x1E00
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN               0
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC          1
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE                 2
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP                  3
+
+       __le32 tenant_id ;
+       u8     reserved[4];
+       __le16 queue_number;
+#define I40E_AQC_ADD_CLOUD_QUEUE_SHIFT                  0
+#define I40E_AQC_ADD_CLOUD_QUEUE_MASK                   (0x3F << \
+                                       I40E_AQC_ADD_CLOUD_QUEUE_SHIFT)
+       u8     reserved2[14];
+       /* response section */
+       u8     allocation_result;
+#define I40E_AQC_ADD_CLOUD_FILTER_SUCCESS         0x0
+#define I40E_AQC_ADD_CLOUD_FILTER_FAIL            0xFF
+       u8     response_reserved[7];
+};
+
+struct i40e_aqc_remove_cloud_filters_completion {
+       __le16 perfect_ovlan_used;
+       __le16 perfect_ovlan_free;
+       __le16 vlan_used;
+       __le16 vlan_free;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_cloud_filters_completion);
+
+/* Add Mirror Rule (indirect or direct 0x0260)
+ * Delete Mirror Rule (indirect or direct 0x0261)
+ * note: some rule types (4,5) do not use an external buffer.
+ *       take care to set the flags correctly.
+ */
+struct i40e_aqc_add_delete_mirror_rule {
+       __le16 seid;
+       __le16 rule_type;
+#define I40E_AQC_MIRROR_RULE_TYPE_SHIFT            0
+#define I40E_AQC_MIRROR_RULE_TYPE_MASK             (0x7 << \
+                                               I40E_AQC_MIRROR_RULE_TYPE_SHIFT)
+#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_INGRESS    1
+#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_EGRESS     2
+#define I40E_AQC_MIRROR_RULE_TYPE_VLAN             3
+#define I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS      4
+#define I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS       5
+       __le16 num_entries;
+       __le16 destination;  /* VSI for add, rule id for delete */
+       __le32 addr_high;    /* address of array of 2-byte VSI or VLAN ids */
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule);
+
+struct i40e_aqc_add_delete_mirror_rule_completion {
+       u8     reserved[2];
+       __le16 rule_id;  /* only used on add */
+       __le16 mirror_rules_used;
+       __le16 mirror_rules_free;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion);
+
+/* Set Storm Control Configuration (direct 0x0280)
+ * Get Storm Control Configuration (direct 0x0281)
+ *    the command and response use the same descriptor structure
+ */
+struct i40e_aqc_set_get_storm_control_config {
+       __le32 broadcast_threshold;
+       __le32 multicast_threshold;
+       __le32 control_flags;
+#define I40E_AQC_STORM_CONTROL_MDIPW            0x01
+#define I40E_AQC_STORM_CONTROL_MDICW            0x02
+#define I40E_AQC_STORM_CONTROL_BDIPW            0x04
+#define I40E_AQC_STORM_CONTROL_BDICW            0x08
+#define I40E_AQC_STORM_CONTROL_BIDU             0x10
+#define I40E_AQC_STORM_CONTROL_INTERVAL_SHIFT   8
+#define I40E_AQC_STORM_CONTROL_INTERVAL_MASK    (0x3FF << \
+                                       I40E_AQC_STORM_CONTROL_INTERVAL_SHIFT)
+       u8     reserved[4];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_set_get_storm_control_config);
+
+/* DCB 0x03xx*/
+
+/* PFC Ignore (direct 0x0301)
+ *    the command and response use the same descriptor structure
+ */
+struct i40e_aqc_pfc_ignore {
+       u8     tc_bitmap;
+       u8     command_flags; /* unused on response */
+#define I40E_AQC_PFC_IGNORE_SET    0x80
+#define I40E_AQC_PFC_IGNORE_CLEAR  0x0
+       u8     reserved[14];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_pfc_ignore);
+
+/* DCB Update (direct 0x0302) uses the i40e_aq_desc structure
+ * with no parameters
+ */
+
+/* TX scheduler 0x04xx */
+
+/* Almost all the indirect commands use
+ * this generic struct to pass the SEID in param0
+ */
+struct i40e_aqc_tx_sched_ind {
+       __le16 vsi_seid;
+       u8     reserved[6];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_tx_sched_ind);
+
+/* Several commands respond with a set of queue set handles */
+struct i40e_aqc_qs_handles_resp {
+       __le16 qs_handles[8];
+};
+
+/* Configure VSI BW limits (direct 0x0400) */
+struct i40e_aqc_configure_vsi_bw_limit {
+       __le16 vsi_seid;
+       u8     reserved[2];
+       __le16 credit;
+       u8     reserved1[2];
+       u8     max_credit; /* 0-3, limit = 2^max */
+       u8     reserved2[7];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_vsi_bw_limit);
+
+/* Configure VSI Bandwidth Limit per Traffic Type (indirect 0x0406)
+ *    responds with i40e_aqc_qs_handles_resp
+ */
+struct i40e_aqc_configure_vsi_ets_sla_bw_data {
+       u8     tc_valid_bits;
+       u8     reserved[15];
+       __le16 tc_bw_credits[8]; /* FW writesback QS handles here */
+
+       /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */
+       __le16 tc_bw_max[2];
+       u8     reserved1[28];
+};
+
+/* Configure VSI Bandwidth Allocation per Traffic Type (indirect 0x0407)
+ *    responds with i40e_aqc_qs_handles_resp
+ */
+struct i40e_aqc_configure_vsi_tc_bw_data {
+       u8     tc_valid_bits;
+       u8     reserved[3];
+       u8     tc_bw_credits[8];
+       u8     reserved1[4];
+       __le16 qs_handles[8];
+};
+
+/* Query vsi bw configuration (indirect 0x0408) */
+struct i40e_aqc_query_vsi_bw_config_resp {
+       u8     tc_valid_bits;
+       u8     tc_suspended_bits;
+       u8     reserved[14];
+       __le16 qs_handles[8];
+       u8     reserved1[4];
+       __le16 port_bw_limit;
+       u8     reserved2[2];
+       u8     max_bw; /* 0-3, limit = 2^max */
+       u8     reserved3[23];
+};
+
+/* Query VSI Bandwidth Allocation per Traffic Type (indirect 0x040A) */
+struct i40e_aqc_query_vsi_ets_sla_config_resp {
+       u8     tc_valid_bits;
+       u8     reserved[3];
+       u8     share_credits[8];
+       __le16 credits[8];
+
+       /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */
+       __le16 tc_bw_max[2];
+};
+
+/* Configure Switching Component Bandwidth Limit (direct 0x0410) */
+struct i40e_aqc_configure_switching_comp_bw_limit {
+       __le16 seid;
+       u8     reserved[2];
+       __le16 credit;
+       u8     reserved1[2];
+       u8     max_bw; /* 0-3, limit = 2^max */
+       u8     reserved2[7];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_switching_comp_bw_limit);
+
+/* Enable  Physical Port ETS (indirect 0x0413)
+ * Modify  Physical Port ETS (indirect 0x0414)
+ * Disable Physical Port ETS (indirect 0x0415)
+ */
+struct i40e_aqc_configure_switching_comp_ets_data {
+       u8     reserved[4];
+       u8     tc_valid_bits;
+       u8     reserved1;
+       u8     tc_strict_priority_flags;
+       u8     reserved2[17];
+       u8     tc_bw_share_credits[8];
+       u8     reserved3[96];
+};
+
+/* Configure Switching Component Bandwidth Limits per Tc (indirect 0x0416) */
+struct i40e_aqc_configure_switching_comp_ets_bw_limit_data {
+       u8     tc_valid_bits;
+       u8     reserved[15];
+       __le16 tc_bw_credit[8];
+
+       /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */
+       __le16 tc_bw_max[2];
+       u8     reserved1[28];
+};
+
+/* Configure Switching Component Bandwidth Allocation per Tc
+ * (indirect 0x0417)
+ */
+struct i40e_aqc_configure_switching_comp_bw_config_data {
+       u8     tc_valid_bits;
+       u8     reserved[2];
+       u8     absolute_credits; /* bool */
+       u8     tc_bw_share_credits[8];
+       u8     reserved1[20];
+};
+
+/* Query Switching Component Configuration (indirect 0x0418) */
+struct i40e_aqc_query_switching_comp_ets_config_resp {
+       u8     tc_valid_bits;
+       u8     reserved[35];
+       __le16 port_bw_limit;
+       u8     reserved1[2];
+       u8     tc_bw_max; /* 0-3, limit = 2^max */
+       u8     reserved2[23];
+};
+
+/* Query PhysicalPort ETS Configuration (indirect 0x0419) */
+struct i40e_aqc_query_port_ets_config_resp {
+       u8     reserved[4];
+       u8     tc_valid_bits;
+       u8     reserved1;
+       u8     tc_strict_priority_bits;
+       u8     reserved2;
+       u8     tc_bw_share_credits[8];
+       __le16 tc_bw_limits[8];
+
+       /* 4 bits per tc 0-7, 4th bit reserved, limit = 2^max */
+       __le16 tc_bw_max[2];
+       u8     reserved3[32];
+};
+
+/* Query Switching Component Bandwidth Allocation per Traffic Type
+ * (indirect 0x041A)
+ */
+struct i40e_aqc_query_switching_comp_bw_config_resp {
+       u8     tc_valid_bits;
+       u8     reserved[2];
+       u8     absolute_credits_enable; /* bool */
+       u8     tc_bw_share_credits[8];
+       __le16 tc_bw_limits[8];
+
+       /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */
+       __le16 tc_bw_max[2];
+};
+
+/* Suspend/resume port TX traffic
+ * (direct 0x041B and 0x041C) uses the generic SEID struct
+ */
+
+/* Get and set the active HMC resource profile and status.
+ * (direct 0x0500) and (direct 0x0501)
+ */
+struct i40e_aq_get_set_hmc_resource_profile {
+       u8     pm_profile;
+       u8     pe_vf_enabled;
+       u8     reserved[14];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aq_get_set_hmc_resource_profile);
+
+enum i40e_aq_hmc_profile {
+       /* I40E_HMC_PROFILE_NO_CHANGE    = 0, reserved */
+       I40E_HMC_PROFILE_DEFAULT     = 1,
+       I40E_HMC_PROFILE_FAVOR_VF    = 2,
+       I40E_HMC_PROFILE_EQUAL       = 3,
+};
+
+#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_PM_MASK       0xF
+#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_COUNT_MASK    0x3F
+
+/* Get PHY Abilities (indirect 0x0600) uses the generic indirect struct */
+
+/* set in param0 for get phy abilities to report qualified modules */
+#define I40E_AQ_PHY_REPORT_QUALIFIED_MODULES  0x0001
+#define I40E_AQ_PHY_REPORT_INITIAL_VALUES     0x0002
+
+enum i40e_aq_phy_type {
+       I40E_PHY_TYPE_SGMII                     = 0x0,
+       I40E_PHY_TYPE_1000BASE_KX               = 0x1,
+       I40E_PHY_TYPE_10GBASE_KX4               = 0x2,
+       I40E_PHY_TYPE_10GBASE_KR                = 0x3,
+       I40E_PHY_TYPE_40GBASE_KR4               = 0x4,
+       I40E_PHY_TYPE_XAUI                      = 0x5,
+       I40E_PHY_TYPE_XFI                       = 0x6,
+       I40E_PHY_TYPE_SFI                       = 0x7,
+       I40E_PHY_TYPE_XLAUI                     = 0x8,
+       I40E_PHY_TYPE_XLPPI                     = 0x9,
+       I40E_PHY_TYPE_40GBASE_CR4_CU            = 0xA,
+       I40E_PHY_TYPE_10GBASE_CR1_CU            = 0xB,
+       I40E_PHY_TYPE_100BASE_TX                = 0x11,
+       I40E_PHY_TYPE_1000BASE_T                = 0x12,
+       I40E_PHY_TYPE_10GBASE_T                 = 0x13,
+       I40E_PHY_TYPE_10GBASE_SR                = 0x14,
+       I40E_PHY_TYPE_10GBASE_LR                = 0x15,
+       I40E_PHY_TYPE_10GBASE_SFPP_CU           = 0x16,
+       I40E_PHY_TYPE_10GBASE_CR1               = 0x17,
+       I40E_PHY_TYPE_40GBASE_CR4               = 0x18,
+       I40E_PHY_TYPE_40GBASE_SR4               = 0x19,
+       I40E_PHY_TYPE_40GBASE_LR4               = 0x1A,
+       I40E_PHY_TYPE_20GBASE_KR2               = 0x1B,
+       I40E_PHY_TYPE_MAX
+};
+
+#define I40E_LINK_SPEED_100MB_SHIFT    0x1
+#define I40E_LINK_SPEED_1000MB_SHIFT   0x2
+#define I40E_LINK_SPEED_10GB_SHIFT     0x3
+#define I40E_LINK_SPEED_40GB_SHIFT     0x4
+#define I40E_LINK_SPEED_20GB_SHIFT     0x5
+
+enum i40e_aq_link_speed {
+       I40E_LINK_SPEED_UNKNOWN = 0,
+       I40E_LINK_SPEED_100MB   = (1 << I40E_LINK_SPEED_100MB_SHIFT),
+       I40E_LINK_SPEED_1GB     = (1 << I40E_LINK_SPEED_1000MB_SHIFT),
+       I40E_LINK_SPEED_10GB    = (1 << I40E_LINK_SPEED_10GB_SHIFT),
+       I40E_LINK_SPEED_40GB    = (1 << I40E_LINK_SPEED_40GB_SHIFT),
+       I40E_LINK_SPEED_20GB    = (1 << I40E_LINK_SPEED_20GB_SHIFT)
+};
+
+struct i40e_aqc_module_desc {
+       u8 oui[3];
+       u8 reserved1;
+       u8 part_number[16];
+       u8 revision[4];
+       u8 reserved2[8];
+};
+
+struct i40e_aq_get_phy_abilities_resp {
+       __le32 phy_type;       /* bitmap using the above enum for offsets */
+       u8     link_speed;     /* bitmap using the above enum bit patterns */
+       u8     abilities;
+#define I40E_AQ_PHY_FLAG_PAUSE_TX         0x01
+#define I40E_AQ_PHY_FLAG_PAUSE_RX         0x02
+#define I40E_AQ_PHY_FLAG_LOW_POWER        0x04
+#define I40E_AQ_PHY_FLAG_AN_SHIFT         3
+#define I40E_AQ_PHY_FLAG_AN_MASK          (0x3 << I40E_AQ_PHY_FLAG_AN_SHIFT)
+#define I40E_AQ_PHY_FLAG_AN_OFF           0x00 /* link forced on */
+#define I40E_AQ_PHY_FLAG_AN_OFF_LINK_DOWN 0x01
+#define I40E_AQ_PHY_FLAG_AN_ON            0x02
+#define I40E_AQ_PHY_FLAG_MODULE_QUAL      0x20
+       __le16 eee_capability;
+#define I40E_AQ_EEE_100BASE_TX       0x0002
+#define I40E_AQ_EEE_1000BASE_T       0x0004
+#define I40E_AQ_EEE_10GBASE_T        0x0008
+#define I40E_AQ_EEE_1000BASE_KX      0x0010
+#define I40E_AQ_EEE_10GBASE_KX4      0x0020
+#define I40E_AQ_EEE_10GBASE_KR       0x0040
+       __le32 eeer_val;
+       u8     d3_lpan;
+#define I40E_AQ_SET_PHY_D3_LPAN_ENA  0x01
+       u8     reserved[3];
+       u8     phy_id[4];
+       u8     module_type[3];
+       u8     qualified_module_count;
+#define I40E_AQ_PHY_MAX_QMS          16
+       struct i40e_aqc_module_desc  qualified_module[I40E_AQ_PHY_MAX_QMS];
+};
+
+/* Set PHY Config (direct 0x0601) */
+struct i40e_aq_set_phy_config { /* same bits as above in all */
+       __le32 phy_type;
+       u8     link_speed;
+       u8     abilities;
+/* bits 0-2 use the values from get_phy_abilities_resp */
+#define I40E_AQ_PHY_ENABLE_LINK                0x08
+#define I40E_AQ_PHY_ENABLE_AN          0x10
+#define I40E_AQ_PHY_ENABLE_ATOMIC_LINK 0x20
+       __le16 eee_capability;
+       __le32 eeer;
+       u8     low_power_ctrl;
+       u8     reserved[3];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
+
+/* Set MAC Config command data structure (direct 0x0603) */
+struct i40e_aq_set_mac_config {
+       __le16 max_frame_size;
+       u8     params;
+#define I40E_AQ_SET_MAC_CONFIG_CRC_EN           0x04
+#define I40E_AQ_SET_MAC_CONFIG_PACING_MASK      0x78
+#define I40E_AQ_SET_MAC_CONFIG_PACING_SHIFT     3
+#define I40E_AQ_SET_MAC_CONFIG_PACING_NONE      0x0
+#define I40E_AQ_SET_MAC_CONFIG_PACING_1B_13TX   0xF
+#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_9TX   0x9
+#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_4TX   0x8
+#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_7TX   0x7
+#define I40E_AQ_SET_MAC_CONFIG_PACING_2DW_3TX   0x6
+#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_1TX   0x5
+#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_2TX   0x4
+#define I40E_AQ_SET_MAC_CONFIG_PACING_7DW_3TX   0x3
+#define I40E_AQ_SET_MAC_CONFIG_PACING_4DW_1TX   0x2
+#define I40E_AQ_SET_MAC_CONFIG_PACING_9DW_1TX   0x1
+       u8     tx_timer_priority; /* bitmap */
+       __le16 tx_timer_value;
+       __le16 fc_refresh_threshold;
+       u8     reserved[8];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aq_set_mac_config);
+
+/* Restart Auto-Negotiation (direct 0x605) */
+struct i40e_aqc_set_link_restart_an {
+       u8     command;
+#define I40E_AQ_PHY_RESTART_AN  0x02
+#define I40E_AQ_PHY_LINK_ENABLE 0x04
+       u8     reserved[15];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_set_link_restart_an);
+
+/* Get Link Status cmd & response data structure (direct 0x0607) */
+struct i40e_aqc_get_link_status {
+       __le16 command_flags; /* only field set on command */
+#define I40E_AQ_LSE_MASK             0x3
+#define I40E_AQ_LSE_NOP              0x0
+#define I40E_AQ_LSE_DISABLE          0x2
+#define I40E_AQ_LSE_ENABLE           0x3
+/* only response uses this flag */
+#define I40E_AQ_LSE_IS_ENABLED       0x1
+       u8     phy_type;    /* i40e_aq_phy_type   */
+       u8     link_speed;  /* i40e_aq_link_speed */
+       u8     link_info;
+#define I40E_AQ_LINK_UP              0x01
+#define I40E_AQ_LINK_FAULT           0x02
+#define I40E_AQ_LINK_FAULT_TX        0x04
+#define I40E_AQ_LINK_FAULT_RX        0x08
+#define I40E_AQ_LINK_FAULT_REMOTE    0x10
+#define I40E_AQ_MEDIA_AVAILABLE      0x40
+#define I40E_AQ_SIGNAL_DETECT        0x80
+       u8     an_info;
+#define I40E_AQ_AN_COMPLETED         0x01
+#define I40E_AQ_LP_AN_ABILITY        0x02
+#define I40E_AQ_PD_FAULT             0x04
+#define I40E_AQ_FEC_EN               0x08
+#define I40E_AQ_PHY_LOW_POWER        0x10
+#define I40E_AQ_LINK_PAUSE_TX        0x20
+#define I40E_AQ_LINK_PAUSE_RX        0x40
+#define I40E_AQ_QUALIFIED_MODULE     0x80
+       u8     ext_info;
+#define I40E_AQ_LINK_PHY_TEMP_ALARM  0x01
+#define I40E_AQ_LINK_XCESSIVE_ERRORS 0x02
+#define I40E_AQ_LINK_TX_SHIFT        0x02
+#define I40E_AQ_LINK_TX_MASK         (0x03 << I40E_AQ_LINK_TX_SHIFT)
+#define I40E_AQ_LINK_TX_ACTIVE       0x00
+#define I40E_AQ_LINK_TX_DRAINED      0x01
+#define I40E_AQ_LINK_TX_FLUSHED      0x03
+       u8     loopback;         /* use defines from i40e_aqc_set_lb_mode */
+       __le16 max_frame_size;
+       u8     config;
+#define I40E_AQ_CONFIG_CRC_ENA       0x04
+#define I40E_AQ_CONFIG_PACING_MASK   0x78
+       u8     reserved[5];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
+
+/* Set event mask command (direct 0x613) */
+struct i40e_aqc_set_phy_int_mask {
+       u8     reserved[8];
+       __le16 event_mask;
+#define I40E_AQ_EVENT_LINK_UPDOWN       0x0002
+#define I40E_AQ_EVENT_MEDIA_NA          0x0004
+#define I40E_AQ_EVENT_LINK_FAULT        0x0008
+#define I40E_AQ_EVENT_PHY_TEMP_ALARM    0x0010
+#define I40E_AQ_EVENT_EXCESSIVE_ERRORS  0x0020
+#define I40E_AQ_EVENT_SIGNAL_DETECT     0x0040
+#define I40E_AQ_EVENT_AN_COMPLETED      0x0080
+#define I40E_AQ_EVENT_MODULE_QUAL_FAIL  0x0100
+#define I40E_AQ_EVENT_PORT_TX_SUSPENDED 0x0200
+       u8     reserved1[6];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_int_mask);
+
+/* Get Local AN advt register (direct 0x0614)
+ * Set Local AN advt register (direct 0x0615)
+ * Get Link Partner AN advt register (direct 0x0616)
+ */
+struct i40e_aqc_an_advt_reg {
+       __le32 local_an_reg0;
+       __le16 local_an_reg1;
+       u8     reserved[10];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_an_advt_reg);
+
+/* Set Loopback mode (0x0618) */
+struct i40e_aqc_set_lb_mode {
+       __le16 lb_mode;
+#define I40E_AQ_LB_PHY_LOCAL   0x01
+#define I40E_AQ_LB_PHY_REMOTE  0x02
+#define I40E_AQ_LB_MAC_LOCAL   0x04
+       u8     reserved[14];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_set_lb_mode);
+
+/* Set PHY Reset command (0x0622) */
+struct i40e_aqc_set_phy_reset {
+       u8     reset_flags;
+#define I40E_AQ_PHY_RESET_REQUEST  0x02
+       u8     reserved[15];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_reset);
+
+enum i40e_aq_phy_reg_type {
+       I40E_AQC_PHY_REG_INTERNAL         = 0x1,
+       I40E_AQC_PHY_REG_EXERNAL_BASET    = 0x2,
+       I40E_AQC_PHY_REG_EXERNAL_MODULE   = 0x3
+};
+
+/* NVM Read command (indirect 0x0701)
+ * NVM Erase commands (direct 0x0702)
+ * NVM Update commands (indirect 0x0703)
+ */
+struct i40e_aqc_nvm_update {
+       u8     command_flags;
+#define I40E_AQ_NVM_LAST_CMD    0x01
+#define I40E_AQ_NVM_FLASH_ONLY  0x80
+       u8     module_pointer;
+       __le16 length;
+       __le32 offset;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_update);
+
+/* Send to PF command (indirect 0x0801) id is only used by PF
+ * Send to VF command (indirect 0x0802) id is only used by PF
+ * Send to Peer PF command (indirect 0x0803)
+ */
+struct i40e_aqc_pf_vf_message {
+       __le32 id;
+       u8     reserved[4];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_pf_vf_message);
+
+/* Alternate structure */
+
+/* Direct write (direct 0x0900)
+ * Direct read (direct 0x0902)
+ */
+struct i40e_aqc_alternate_write {
+       __le32 address0;
+       __le32 data0;
+       __le32 address1;
+       __le32 data1;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_write);
+
+/* Indirect write (indirect 0x0901)
+ * Indirect read (indirect 0x0903)
+ */
+
+struct i40e_aqc_alternate_ind_write {
+       __le32 address;
+       __le32 length;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_ind_write);
+
+/* Done alternate write (direct 0x0904)
+ * uses i40e_aq_desc
+ */
+struct i40e_aqc_alternate_write_done {
+       __le16 cmd_flags;
+#define I40E_AQ_ALTERNATE_MODE_BIOS_MASK       1
+#define I40E_AQ_ALTERNATE_MODE_BIOS_LEGACY     0
+#define I40E_AQ_ALTERNATE_MODE_BIOS_UEFI       1
+#define I40E_AQ_ALTERNATE_RESET_NEEDED         2
+       u8     reserved[14];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_write_done);
+
+/* Set OEM mode (direct 0x0905) */
+struct i40e_aqc_alternate_set_mode {
+       __le32 mode;
+#define I40E_AQ_ALTERNATE_MODE_NONE    0
+#define I40E_AQ_ALTERNATE_MODE_OEM     1
+       u8     reserved[12];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_set_mode);
+
+/* Clear port Alternate RAM (direct 0x0906) uses i40e_aq_desc */
+
+/* async events 0x10xx */
+
+/* Lan Queue Overflow Event (direct, 0x1001) */
+struct i40e_aqc_lan_overflow {
+       __le32 prtdcb_rupto;
+       __le32 otx_ctl;
+       u8     reserved[8];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_lan_overflow);
+
+/* Get LLDP MIB (indirect 0x0A00) */
+struct i40e_aqc_lldp_get_mib {
+       u8     type;
+       u8     reserved1;
+#define I40E_AQ_LLDP_MIB_TYPE_MASK                      0x3
+#define I40E_AQ_LLDP_MIB_LOCAL                          0x0
+#define I40E_AQ_LLDP_MIB_REMOTE                         0x1
+#define I40E_AQ_LLDP_MIB_LOCAL_AND_REMOTE               0x2
+#define I40E_AQ_LLDP_BRIDGE_TYPE_MASK                   0xC
+#define I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT                  0x2
+#define I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE         0x0
+#define I40E_AQ_LLDP_BRIDGE_TYPE_NON_TPMR               0x1
+#define I40E_AQ_LLDP_TX_SHIFT              0x4
+#define I40E_AQ_LLDP_TX_MASK               (0x03 << I40E_AQ_LLDP_TX_SHIFT)
+/* TX pause flags use I40E_AQ_LINK_TX_* above */
+       __le16 local_len;
+       __le16 remote_len;
+       u8     reserved2[2];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_get_mib);
+
+/* Configure LLDP MIB Change Event (direct 0x0A01)
+ * also used for the event (with type in the command field)
+ */
+struct i40e_aqc_lldp_update_mib {
+       u8     command;
+#define I40E_AQ_LLDP_MIB_UPDATE_ENABLE          0x0
+#define I40E_AQ_LLDP_MIB_UPDATE_DISABLE         0x1
+       u8     reserved[7];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_mib);
+
+/* Add LLDP TLV (indirect 0x0A02)
+ * Delete LLDP TLV (indirect 0x0A04)
+ */
+struct i40e_aqc_lldp_add_tlv {
+       u8     type; /* only nearest bridge and non-TPMR from 0x0A00 */
+       u8     reserved1[1];
+       __le16 len;
+       u8     reserved2[4];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_add_tlv);
+
+/* Update LLDP TLV (indirect 0x0A03) */
+struct i40e_aqc_lldp_update_tlv {
+       u8     type; /* only nearest bridge and non-TPMR from 0x0A00 */
+       u8     reserved;
+       __le16 old_len;
+       __le16 new_offset;
+       __le16 new_len;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_tlv);
+
+/* Stop LLDP (direct 0x0A05) */
+struct i40e_aqc_lldp_stop {
+       u8     command;
+#define I40E_AQ_LLDP_AGENT_STOP                 0x0
+#define I40E_AQ_LLDP_AGENT_SHUTDOWN             0x1
+       u8     reserved[15];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop);
+
+/* Start LLDP (direct 0x0A06) */
+
+struct i40e_aqc_lldp_start {
+       u8     command;
+#define I40E_AQ_LLDP_AGENT_START                0x1
+       u8     reserved[15];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start);
+
+/* Apply MIB changes (0x0A07)
+ * uses the generic struc as it contains no data
+ */
+
+/* Add Udp Tunnel command and completion (direct 0x0B00) */
+struct i40e_aqc_add_udp_tunnel {
+       __le16 udp_port;
+       u8     header_len; /* in DWords, 1 to 15 */
+       u8     protocol_type;
+#define I40E_AQC_TUNNEL_TYPE_TEREDO    0x0
+#define I40E_AQC_TUNNEL_TYPE_VXLAN     0x2
+#define I40E_AQC_TUNNEL_TYPE_NGE       0x3
+       u8     variable_udp_length;
+#define I40E_AQC_TUNNEL_FIXED_UDP_LENGTH       0x0
+#define I40E_AQC_TUNNEL_VARIABLE_UDP_LENGTH    0x1
+       u8              udp_key_index;
+#define I40E_AQC_TUNNEL_KEY_INDEX_VXLAN                        0x0
+#define I40E_AQC_TUNNEL_KEY_INDEX_NGE                  0x1
+#define I40E_AQC_TUNNEL_KEY_INDEX_PROPRIETARY_UDP      0x2
+       u8              reserved[10];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel);
+
+struct i40e_aqc_add_udp_tunnel_completion {
+       __le16 udp_port;
+       u8      filter_entry_index;
+       u8      multiple_pfs;
+#define I40E_AQC_SINGLE_PF                             0x0
+#define I40E_AQC_MULTIPLE_PFS                  0x1
+       u8      total_filters;
+       u8      reserved[11];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel_completion);
+
+/* remove UDP Tunnel command (0x0B01) */
+struct i40e_aqc_remove_udp_tunnel {
+       u8     reserved[2];
+       u8     index; /* 0 to 15 */
+       u8     pf_filters;
+       u8     total_filters;
+       u8     reserved2[11];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_udp_tunnel);
+
+struct i40e_aqc_del_udp_tunnel_completion {
+       __le16 udp_port;
+       u8     index; /* 0 to 15 */
+       u8     multiple_pfs;
+       u8     total_filters_used;
+       u8     reserved;
+       u8     tunnels_free;
+       u8     reserved1[9];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_del_udp_tunnel_completion);
+
+/* tunnel key structure 0x0B10 */
+
+struct i40e_aqc_tunnel_key_structure_A0 {
+       __le16     key1_off;
+       __le16     key1_len;
+       __le16     key2_off;
+       __le16     key2_len;
+       __le16     flags;
+#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01
+/* response flags */
+#define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS    0x01
+#define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED   0x02
+#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03
+       u8         resreved[6];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_tunnel_key_structure_A0);
+
+struct i40e_aqc_tunnel_key_structure {
+       u8      key1_off;
+       u8      key2_off;
+       u8      key1_len;  /* 0 to 15 */
+       u8      key2_len;  /* 0 to 15 */
+       u8      flags;
+#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01
+/* response flags */
+#define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS    0x01
+#define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED   0x02
+#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03
+       u8      network_key_index;
+#define I40E_AQC_NETWORK_KEY_INDEX_VXLAN               0x0
+#define I40E_AQC_NETWORK_KEY_INDEX_NGE                 0x1
+#define I40E_AQC_NETWORK_KEY_INDEX_FLEX_MAC_IN_UDP     0x2
+#define I40E_AQC_NETWORK_KEY_INDEX_GRE                 0x3
+       u8      reserved[10];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_tunnel_key_structure);
+
+/* OEM mode commands (direct 0xFE0x) */
+struct i40e_aqc_oem_param_change {
+       __le32 param_type;
+#define I40E_AQ_OEM_PARAM_TYPE_PF_CTL   0
+#define I40E_AQ_OEM_PARAM_TYPE_BW_CTL   1
+#define I40E_AQ_OEM_PARAM_MAC           2
+       __le32 param_value1;
+       u8     param_value2[8];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_param_change);
+
+struct i40e_aqc_oem_state_change {
+       __le32 state;
+#define I40E_AQ_OEM_STATE_LINK_DOWN  0x0
+#define I40E_AQ_OEM_STATE_LINK_UP    0x1
+       u8     reserved[12];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_state_change);
+
+/* debug commands */
+
+/* get device id (0xFF00) uses the generic structure */
+
+/* set test more (0xFF01, internal) */
+
+struct i40e_acq_set_test_mode {
+       u8     mode;
+#define I40E_AQ_TEST_PARTIAL    0
+#define I40E_AQ_TEST_FULL       1
+#define I40E_AQ_TEST_NVM        2
+       u8     reserved[3];
+       u8     command;
+#define I40E_AQ_TEST_OPEN        0
+#define I40E_AQ_TEST_CLOSE       1
+#define I40E_AQ_TEST_INC         2
+       u8     reserved2[3];
+       __le32 address_high;
+       __le32 address_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_acq_set_test_mode);
+
+/* Debug Read Register command (0xFF03)
+ * Debug Write Register command (0xFF04)
+ */
+struct i40e_aqc_debug_reg_read_write {
+       __le32 reserved;
+       __le32 address;
+       __le32 value_high;
+       __le32 value_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_reg_read_write);
+
+/* Scatter/gather Reg Read  (indirect 0xFF05)
+ * Scatter/gather Reg Write (indirect 0xFF06)
+ */
+
+/* i40e_aq_desc is used for the command */
+struct i40e_aqc_debug_reg_sg_element_data {
+       __le32 address;
+       __le32 value;
+};
+
+/* Debug Modify register (direct 0xFF07) */
+struct i40e_aqc_debug_modify_reg {
+       __le32 address;
+       __le32 value;
+       __le32 clear_mask;
+       __le32 set_mask;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_reg);
+
+/* dump internal data (0xFF08, indirect) */
+
+#define I40E_AQ_CLUSTER_ID_AUX         0
+#define I40E_AQ_CLUSTER_ID_SWITCH_FLU  1
+#define I40E_AQ_CLUSTER_ID_TXSCHED     2
+#define I40E_AQ_CLUSTER_ID_HMC         3
+#define I40E_AQ_CLUSTER_ID_MAC0                4
+#define I40E_AQ_CLUSTER_ID_MAC1                5
+#define I40E_AQ_CLUSTER_ID_MAC2                6
+#define I40E_AQ_CLUSTER_ID_MAC3                7
+#define I40E_AQ_CLUSTER_ID_DCB         8
+#define I40E_AQ_CLUSTER_ID_EMP_MEM     9
+#define I40E_AQ_CLUSTER_ID_PKT_BUF     10
+#define I40E_AQ_CLUSTER_ID_ALTRAM      11
+
+struct i40e_aqc_debug_dump_internals {
+       u8     cluster_id;
+       u8     table_id;
+       __le16 data_size;
+       __le32 idx;
+       __le32 address_high;
+       __le32 address_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_dump_internals);
+
+struct i40e_aqc_debug_modify_internals {
+       u8     cluster_id;
+       u8     cluster_specific_params[7];
+       __le32 address_high;
+       __le32 address_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_internals);
+
+#endif
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_alloc.h b/drivers/net/ethernet/intel/i40evf/i40e_alloc.h
new file mode 100644 (file)
index 0000000..d8654fb
--- /dev/null
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_ALLOC_H_
+#define _I40E_ALLOC_H_
+
+struct i40e_hw;
+
+/* Memory allocation types */
+enum i40e_memory_type {
+       i40e_mem_arq_buf = 0,           /* ARQ indirect command buffer */
+       i40e_mem_asq_buf = 1,
+       i40e_mem_atq_buf = 2,           /* ATQ indirect command buffer */
+       i40e_mem_arq_ring = 3,          /* ARQ descriptor ring */
+       i40e_mem_atq_ring = 4,          /* ATQ descriptor ring */
+       i40e_mem_pd = 5,                /* Page Descriptor */
+       i40e_mem_bp = 6,                /* Backing Page - 4KB */
+       i40e_mem_bp_jumbo = 7,          /* Backing Page - > 4KB */
+       i40e_mem_reserved
+};
+
+/* prototype for functions used for dynamic memory allocation */
+i40e_status i40e_allocate_dma_mem(struct i40e_hw *hw,
+                                           struct i40e_dma_mem *mem,
+                                           enum i40e_memory_type type,
+                                           u64 size, u32 alignment);
+i40e_status i40e_free_dma_mem(struct i40e_hw *hw,
+                                       struct i40e_dma_mem *mem);
+i40e_status i40e_allocate_virt_mem(struct i40e_hw *hw,
+                                            struct i40e_virt_mem *mem,
+                                            u32 size);
+i40e_status i40e_free_virt_mem(struct i40e_hw *hw,
+                                        struct i40e_virt_mem *mem);
+
+#endif /* _I40E_ALLOC_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c
new file mode 100644 (file)
index 0000000..44b90b3
--- /dev/null
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#include "i40e_type.h"
+#include "i40e_adminq.h"
+#include "i40e_prototype.h"
+#include "i40e_virtchnl.h"
+
+/**
+ * i40e_set_mac_type - Sets MAC type
+ * @hw: pointer to the HW structure
+ *
+ * This function sets the mac type of the adapter based on the
+ * vendor ID and device ID stored in the hw structure.
+ **/
+i40e_status i40e_set_mac_type(struct i40e_hw *hw)
+{
+       i40e_status status = 0;
+
+       if (hw->vendor_id == PCI_VENDOR_ID_INTEL) {
+               switch (hw->device_id) {
+               case I40E_SFP_XL710_DEVICE_ID:
+               case I40E_SFP_X710_DEVICE_ID:
+               case I40E_QEMU_DEVICE_ID:
+               case I40E_KX_A_DEVICE_ID:
+               case I40E_KX_B_DEVICE_ID:
+               case I40E_KX_C_DEVICE_ID:
+               case I40E_KX_D_DEVICE_ID:
+               case I40E_QSFP_A_DEVICE_ID:
+               case I40E_QSFP_B_DEVICE_ID:
+               case I40E_QSFP_C_DEVICE_ID:
+                       hw->mac.type = I40E_MAC_XL710;
+                       break;
+               case I40E_VF_DEVICE_ID:
+               case I40E_VF_HV_DEVICE_ID:
+                       hw->mac.type = I40E_MAC_VF;
+                       break;
+               default:
+                       hw->mac.type = I40E_MAC_GENERIC;
+                       break;
+               }
+       } else {
+               status = I40E_ERR_DEVICE_NOT_SUPPORTED;
+       }
+
+       hw_dbg(hw, "i40e_set_mac_type found mac: %d, returns: %d\n",
+                 hw->mac.type, status);
+       return status;
+}
+
+/**
+ * i40evf_debug_aq
+ * @hw: debug mask related to admin queue
+ * @mask: debug mask
+ * @desc: pointer to admin queue descriptor
+ * @buffer: pointer to command buffer
+ *
+ * Dumps debug log about adminq command with descriptor contents.
+ **/
+void i40evf_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
+                  void *buffer)
+{
+       struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc;
+       u8 *aq_buffer = (u8 *)buffer;
+       u32 data[4];
+       u32 i = 0;
+
+       if ((!(mask & hw->debug_mask)) || (desc == NULL))
+               return;
+
+       i40e_debug(hw, mask,
+                  "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
+                  aq_desc->opcode, aq_desc->flags, aq_desc->datalen,
+                  aq_desc->retval);
+       i40e_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n",
+                  aq_desc->cookie_high, aq_desc->cookie_low);
+       i40e_debug(hw, mask, "\tparam (0,1)  0x%08X 0x%08X\n",
+                  aq_desc->params.internal.param0,
+                  aq_desc->params.internal.param1);
+       i40e_debug(hw, mask, "\taddr (h,l)   0x%08X 0x%08X\n",
+                  aq_desc->params.external.addr_high,
+                  aq_desc->params.external.addr_low);
+
+       if ((buffer != NULL) && (aq_desc->datalen != 0)) {
+               memset(data, 0, sizeof(data));
+               i40e_debug(hw, mask, "AQ CMD Buffer:\n");
+               for (i = 0; i < le16_to_cpu(aq_desc->datalen); i++) {
+                       data[((i % 16) / 4)] |=
+                               ((u32)aq_buffer[i]) << (8 * (i % 4));
+                       if ((i % 16) == 15) {
+                               i40e_debug(hw, mask,
+                                          "\t0x%04X  %08X %08X %08X %08X\n",
+                                          i - 15, data[0], data[1], data[2],
+                                          data[3]);
+                               memset(data, 0, sizeof(data));
+                       }
+               }
+               if ((i % 16) != 0)
+                       i40e_debug(hw, mask, "\t0x%04X  %08X %08X %08X %08X\n",
+                                  i - (i % 16), data[0], data[1], data[2],
+                                  data[3]);
+       }
+}
+
+/**
+ * i40evf_check_asq_alive
+ * @hw: pointer to the hw struct
+ *
+ * Returns true if Queue is enabled else false.
+ **/
+bool i40evf_check_asq_alive(struct i40e_hw *hw)
+{
+       return !!(rd32(hw, hw->aq.asq.len) & I40E_PF_ATQLEN_ATQENABLE_MASK);
+}
+
+/**
+ * i40evf_aq_queue_shutdown
+ * @hw: pointer to the hw struct
+ * @unloading: is the driver unloading itself
+ *
+ * Tell the Firmware that we're shutting down the AdminQ and whether
+ * or not the driver is unloading as well.
+ **/
+i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw,
+                                            bool unloading)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_queue_shutdown *cmd =
+               (struct i40e_aqc_queue_shutdown *)&desc.params.raw;
+       i40e_status status;
+
+       i40evf_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_queue_shutdown);
+
+       if (unloading)
+               cmd->driver_unloading = cpu_to_le32(I40E_AQ_DRIVER_UNLOADING);
+       status = i40evf_asq_send_command(hw, &desc, NULL, 0, NULL);
+
+       return status;
+}
+
+
+/**
+ * i40e_aq_send_msg_to_pf
+ * @hw: pointer to the hardware structure
+ * @v_opcode: opcodes for VF-PF communication
+ * @v_retval: return error code
+ * @msg: pointer to the msg buffer
+ * @msglen: msg length
+ * @cmd_details: pointer to command details
+ *
+ * Send message to PF driver using admin queue. By default, this message
+ * is sent asynchronously, i.e. i40evf_asq_send_command() does not wait for
+ * completion before returning.
+ **/
+i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
+                               enum i40e_virtchnl_ops v_opcode,
+                               i40e_status v_retval,
+                               u8 *msg, u16 msglen,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       i40e_status status;
+
+       i40evf_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_send_msg_to_pf);
+       desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_SI);
+       desc.cookie_high = cpu_to_le32(v_opcode);
+       desc.cookie_low = cpu_to_le32(v_retval);
+       if (msglen) {
+               desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF
+                                               | I40E_AQ_FLAG_RD));
+               if (msglen > I40E_AQ_LARGE_BUF)
+                       desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
+               desc.datalen = cpu_to_le16(msglen);
+       }
+       if (!cmd_details) {
+               struct i40e_asq_cmd_details details;
+               memset(&details, 0, sizeof(details));
+               details.async = true;
+               cmd_details = &details;
+       }
+       status = i40evf_asq_send_command(hw, (struct i40e_aq_desc *)&desc, msg,
+                                      msglen, cmd_details);
+       return status;
+}
+
+/**
+ * i40e_vf_parse_hw_config
+ * @hw: pointer to the hardware structure
+ * @msg: pointer to the virtual channel VF resource structure
+ *
+ * Given a VF resource message from the PF, populate the hw struct
+ * with appropriate information.
+ **/
+void i40e_vf_parse_hw_config(struct i40e_hw *hw,
+                            struct i40e_virtchnl_vf_resource *msg)
+{
+       struct i40e_virtchnl_vsi_resource *vsi_res;
+       int i;
+
+       vsi_res = &msg->vsi_res[0];
+
+       hw->dev_caps.num_vsis = msg->num_vsis;
+       hw->dev_caps.num_rx_qp = msg->num_queue_pairs;
+       hw->dev_caps.num_tx_qp = msg->num_queue_pairs;
+       hw->dev_caps.num_msix_vectors_vf = msg->max_vectors;
+       hw->dev_caps.dcb = msg->vf_offload_flags &
+                          I40E_VIRTCHNL_VF_OFFLOAD_L2;
+       hw->dev_caps.fcoe = (msg->vf_offload_flags &
+                            I40E_VIRTCHNL_VF_OFFLOAD_FCOE) ? 1 : 0;
+       for (i = 0; i < msg->num_vsis; i++) {
+               if (vsi_res->vsi_type == I40E_VSI_SRIOV) {
+                       memcpy(hw->mac.perm_addr, vsi_res->default_mac_addr,
+                              ETH_ALEN);
+                       memcpy(hw->mac.addr, vsi_res->default_mac_addr,
+                              ETH_ALEN);
+               }
+               vsi_res++;
+       }
+}
+
+/**
+ * i40e_vf_reset
+ * @hw: pointer to the hardware structure
+ *
+ * Send a VF_RESET message to the PF. Does not wait for response from PF
+ * as none will be forthcoming. Immediately after calling this function,
+ * the admin queue should be shut down and (optionally) reinitialized.
+ **/
+i40e_status i40e_vf_reset(struct i40e_hw *hw)
+{
+       return i40e_aq_send_msg_to_pf(hw, I40E_VIRTCHNL_OP_RESET_VF,
+                                     0, NULL, 0, NULL);
+}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_hmc.h b/drivers/net/ethernet/intel/i40evf/i40e_hmc.h
new file mode 100644 (file)
index 0000000..cb97b3e
--- /dev/null
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_HMC_H_
+#define _I40E_HMC_H_
+
+#define I40E_HMC_MAX_BP_COUNT 512
+
+/* forward-declare the HW struct for the compiler */
+struct i40e_hw;
+
+#define I40E_HMC_INFO_SIGNATURE                0x484D5347 /* HMSG */
+#define I40E_HMC_PD_CNT_IN_SD          512
+#define I40E_HMC_DIRECT_BP_SIZE                0x200000 /* 2M */
+#define I40E_HMC_PAGED_BP_SIZE         4096
+#define I40E_HMC_PD_BP_BUF_ALIGNMENT   4096
+#define I40E_FIRST_VF_FPM_ID           16
+
+struct i40e_hmc_obj_info {
+       u64 base;       /* base addr in FPM */
+       u32 max_cnt;    /* max count available for this hmc func */
+       u32 cnt;        /* count of objects driver actually wants to create */
+       u64 size;       /* size in bytes of one object */
+};
+
+enum i40e_sd_entry_type {
+       I40E_SD_TYPE_INVALID = 0,
+       I40E_SD_TYPE_PAGED   = 1,
+       I40E_SD_TYPE_DIRECT  = 2
+};
+
+struct i40e_hmc_bp {
+       enum i40e_sd_entry_type entry_type;
+       struct i40e_dma_mem addr; /* populate to be used by hw */
+       u32 sd_pd_index;
+       u32 ref_cnt;
+};
+
+struct i40e_hmc_pd_entry {
+       struct i40e_hmc_bp bp;
+       u32 sd_index;
+       bool valid;
+};
+
+struct i40e_hmc_pd_table {
+       struct i40e_dma_mem pd_page_addr; /* populate to be used by hw */
+       struct i40e_hmc_pd_entry  *pd_entry; /* [512] for sw book keeping */
+       struct i40e_virt_mem pd_entry_virt_mem; /* virt mem for pd_entry */
+
+       u32 ref_cnt;
+       u32 sd_index;
+};
+
+struct i40e_hmc_sd_entry {
+       enum i40e_sd_entry_type entry_type;
+       bool valid;
+
+       union {
+               struct i40e_hmc_pd_table pd_table;
+               struct i40e_hmc_bp bp;
+       } u;
+};
+
+struct i40e_hmc_sd_table {
+       struct i40e_virt_mem addr; /* used to track sd_entry allocations */
+       u32 sd_cnt;
+       u32 ref_cnt;
+       struct i40e_hmc_sd_entry *sd_entry; /* (sd_cnt*512) entries max */
+};
+
+struct i40e_hmc_info {
+       u32 signature;
+       /* equals to pci func num for PF and dynamically allocated for VFs */
+       u8 hmc_fn_id;
+       u16 first_sd_index; /* index of the first available SD */
+
+       /* hmc objects */
+       struct i40e_hmc_obj_info *hmc_obj;
+       struct i40e_virt_mem hmc_obj_virt_mem;
+       struct i40e_hmc_sd_table sd_table;
+};
+
+#define I40E_INC_SD_REFCNT(sd_table)   ((sd_table)->ref_cnt++)
+#define I40E_INC_PD_REFCNT(pd_table)   ((pd_table)->ref_cnt++)
+#define I40E_INC_BP_REFCNT(bp)         ((bp)->ref_cnt++)
+
+#define I40E_DEC_SD_REFCNT(sd_table)   ((sd_table)->ref_cnt--)
+#define I40E_DEC_PD_REFCNT(pd_table)   ((pd_table)->ref_cnt--)
+#define I40E_DEC_BP_REFCNT(bp)         ((bp)->ref_cnt--)
+
+/**
+ * I40E_SET_PF_SD_ENTRY - marks the sd entry as valid in the hardware
+ * @hw: pointer to our hw struct
+ * @pa: pointer to physical address
+ * @sd_index: segment descriptor index
+ * @type: if sd entry is direct or paged
+ **/
+#define I40E_SET_PF_SD_ENTRY(hw, pa, sd_index, type)                   \
+{                                                                      \
+       u32 val1, val2, val3;                                           \
+       val1 = (u32)(upper_32_bits(pa));                                \
+       val2 = (u32)(pa) | (I40E_HMC_MAX_BP_COUNT <<                    \
+                I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) |              \
+               ((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) <<            \
+               I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) |                  \
+               (1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT);            \
+       val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);       \
+       wr32((hw), I40E_PFHMC_SDDATAHIGH, val1);                        \
+       wr32((hw), I40E_PFHMC_SDDATALOW, val2);                         \
+       wr32((hw), I40E_PFHMC_SDCMD, val3);                             \
+}
+
+/**
+ * I40E_CLEAR_PF_SD_ENTRY - marks the sd entry as invalid in the hardware
+ * @hw: pointer to our hw struct
+ * @sd_index: segment descriptor index
+ * @type: if sd entry is direct or paged
+ **/
+#define I40E_CLEAR_PF_SD_ENTRY(hw, sd_index, type)                     \
+{                                                                      \
+       u32 val2, val3;                                                 \
+       val2 = (I40E_HMC_MAX_BP_COUNT <<                                \
+               I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) |               \
+               ((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) <<            \
+               I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT);                   \
+       val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);       \
+       wr32((hw), I40E_PFHMC_SDDATAHIGH, 0);                           \
+       wr32((hw), I40E_PFHMC_SDDATALOW, val2);                         \
+       wr32((hw), I40E_PFHMC_SDCMD, val3);                             \
+}
+
+/**
+ * I40E_INVALIDATE_PF_HMC_PD - Invalidates the pd cache in the hardware
+ * @hw: pointer to our hw struct
+ * @sd_idx: segment descriptor index
+ * @pd_idx: page descriptor index
+ **/
+#define I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, pd_idx)                  \
+       wr32((hw), I40E_PFHMC_PDINV,                                    \
+           (((sd_idx) << I40E_PFHMC_PDINV_PMSDIDX_SHIFT) |             \
+            ((pd_idx) << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)))
+
+#define I40E_INVALIDATE_VF_HMC_PD(hw, sd_idx, pd_idx, hmc_fn_id)          \
+       wr32((hw), I40E_GLHMC_VFPDINV((hmc_fn_id) - I40E_FIRST_VF_FPM_ID), \
+            (((sd_idx) << I40E_PFHMC_PDINV_PMSDIDX_SHIFT) |               \
+             ((pd_idx) << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)))
+
+/**
+ * I40E_FIND_SD_INDEX_LIMIT - finds segment descriptor index limit
+ * @hmc_info: pointer to the HMC configuration information structure
+ * @type: type of HMC resources we're searching
+ * @index: starting index for the object
+ * @cnt: number of objects we're trying to create
+ * @sd_idx: pointer to return index of the segment descriptor in question
+ * @sd_limit: pointer to return the maximum number of segment descriptors
+ *
+ * This function calculates the segment descriptor index and index limit
+ * for the resource defined by i40e_hmc_rsrc_type.
+ **/
+#define I40E_FIND_SD_INDEX_LIMIT(hmc_info, type, index, cnt, sd_idx, sd_limit)\
+{                                                                      \
+       u64 fpm_addr, fpm_limit;                                        \
+       fpm_addr = (hmc_info)->hmc_obj[(type)].base +                   \
+                  (hmc_info)->hmc_obj[(type)].size * (index);          \
+       fpm_limit = fpm_addr + (hmc_info)->hmc_obj[(type)].size * (cnt);\
+       *(sd_idx) = (u32)(fpm_addr / I40E_HMC_DIRECT_BP_SIZE);          \
+       *(sd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_DIRECT_BP_SIZE); \
+       /* add one more to the limit to correct our range */            \
+       *(sd_limit) += 1;                                               \
+}
+
+/**
+ * I40E_FIND_PD_INDEX_LIMIT - finds page descriptor index limit
+ * @hmc_info: pointer to the HMC configuration information struct
+ * @type: HMC resource type we're examining
+ * @idx: starting index for the object
+ * @cnt: number of objects we're trying to create
+ * @pd_index: pointer to return page descriptor index
+ * @pd_limit: pointer to return page descriptor index limit
+ *
+ * Calculates the page descriptor index and index limit for the resource
+ * defined by i40e_hmc_rsrc_type.
+ **/
+#define I40E_FIND_PD_INDEX_LIMIT(hmc_info, type, idx, cnt, pd_index, pd_limit)\
+{                                                                      \
+       u64 fpm_adr, fpm_limit;                                         \
+       fpm_adr = (hmc_info)->hmc_obj[(type)].base +                    \
+                 (hmc_info)->hmc_obj[(type)].size * (idx);             \
+       fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt); \
+       *(pd_index) = (u32)(fpm_adr / I40E_HMC_PAGED_BP_SIZE);          \
+       *(pd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_PAGED_BP_SIZE);  \
+       /* add one more to the limit to correct our range */            \
+       *(pd_limit) += 1;                                               \
+}
+i40e_status i40e_add_sd_table_entry(struct i40e_hw *hw,
+                                             struct i40e_hmc_info *hmc_info,
+                                             u32 sd_index,
+                                             enum i40e_sd_entry_type type,
+                                             u64 direct_mode_sz);
+
+i40e_status i40e_add_pd_table_entry(struct i40e_hw *hw,
+                                             struct i40e_hmc_info *hmc_info,
+                                             u32 pd_index);
+i40e_status i40e_remove_pd_bp(struct i40e_hw *hw,
+                                       struct i40e_hmc_info *hmc_info,
+                                       u32 idx, bool is_pf);
+i40e_status i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info,
+                                            u32 idx);
+i40e_status i40e_remove_sd_bp_new(struct i40e_hw *hw,
+                                           struct i40e_hmc_info *hmc_info,
+                                           u32 idx, bool is_pf);
+i40e_status i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info,
+                                              u32 idx);
+i40e_status i40e_remove_pd_page_new(struct i40e_hw *hw,
+                                             struct i40e_hmc_info *hmc_info,
+                                             u32 idx, bool is_pf);
+
+#endif /* _I40E_HMC_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h b/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h
new file mode 100644 (file)
index 0000000..17e42ca
--- /dev/null
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_LAN_HMC_H_
+#define _I40E_LAN_HMC_H_
+
+/* forward-declare the HW struct for the compiler */
+struct i40e_hw;
+
+/* HMC element context information */
+
+/* Rx queue context data */
+struct i40e_hmc_obj_rxq {
+       u16 head;
+       u8  cpuid;
+       u64 base;
+       u16 qlen;
+#define I40E_RXQ_CTX_DBUFF_SHIFT 7
+       u8  dbuff;
+#define I40E_RXQ_CTX_HBUFF_SHIFT 6
+       u8  hbuff;
+       u8  dtype;
+       u8  dsize;
+       u8  crcstrip;
+       u8  fc_ena;
+       u8  l2tsel;
+       u8  hsplit_0;
+       u8  hsplit_1;
+       u8  showiv;
+       u16 rxmax;
+       u8  tphrdesc_ena;
+       u8  tphwdesc_ena;
+       u8  tphdata_ena;
+       u8  tphhead_ena;
+       u8  lrxqthresh;
+};
+
+/* Tx queue context data */
+struct i40e_hmc_obj_txq {
+       u16 head;
+       u8  new_context;
+       u64 base;
+       u8  fc_ena;
+       u8  timesync_ena;
+       u8  fd_ena;
+       u8  alt_vlan_ena;
+       u16 thead_wb;
+       u16 cpuid;
+       u8  head_wb_ena;
+       u16 qlen;
+       u8  tphrdesc_ena;
+       u8  tphrpacket_ena;
+       u8  tphwdesc_ena;
+       u64 head_wb_addr;
+       u32 crc;
+       u16 rdylist;
+       u8  rdylist_act;
+};
+
+/* for hsplit_0 field of Rx HMC context */
+enum i40e_hmc_obj_rx_hsplit_0 {
+       I40E_HMC_OBJ_RX_HSPLIT_0_NO_SPLIT      = 0,
+       I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_L2      = 1,
+       I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_IP      = 2,
+       I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_TCP_UDP = 4,
+       I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_SCTP    = 8,
+};
+
+/* fcoe_cntx and fcoe_filt are for debugging purpose only */
+struct i40e_hmc_obj_fcoe_cntx {
+       u32 rsv[32];
+};
+
+struct i40e_hmc_obj_fcoe_filt {
+       u32 rsv[8];
+};
+
+/* Context sizes for LAN objects */
+enum i40e_hmc_lan_object_size {
+       I40E_HMC_LAN_OBJ_SZ_8   = 0x3,
+       I40E_HMC_LAN_OBJ_SZ_16  = 0x4,
+       I40E_HMC_LAN_OBJ_SZ_32  = 0x5,
+       I40E_HMC_LAN_OBJ_SZ_64  = 0x6,
+       I40E_HMC_LAN_OBJ_SZ_128 = 0x7,
+       I40E_HMC_LAN_OBJ_SZ_256 = 0x8,
+       I40E_HMC_LAN_OBJ_SZ_512 = 0x9,
+};
+
+#define I40E_HMC_L2OBJ_BASE_ALIGNMENT 512
+#define I40E_HMC_OBJ_SIZE_TXQ         128
+#define I40E_HMC_OBJ_SIZE_RXQ         32
+#define I40E_HMC_OBJ_SIZE_FCOE_CNTX   128
+#define I40E_HMC_OBJ_SIZE_FCOE_FILT   64
+
+enum i40e_hmc_lan_rsrc_type {
+       I40E_HMC_LAN_FULL  = 0,
+       I40E_HMC_LAN_TX    = 1,
+       I40E_HMC_LAN_RX    = 2,
+       I40E_HMC_FCOE_CTX  = 3,
+       I40E_HMC_FCOE_FILT = 4,
+       I40E_HMC_LAN_MAX   = 5
+};
+
+enum i40e_hmc_model {
+       I40E_HMC_MODEL_DIRECT_PREFERRED = 0,
+       I40E_HMC_MODEL_DIRECT_ONLY      = 1,
+       I40E_HMC_MODEL_PAGED_ONLY       = 2,
+       I40E_HMC_MODEL_UNKNOWN,
+};
+
+struct i40e_hmc_lan_create_obj_info {
+       struct i40e_hmc_info *hmc_info;
+       u32 rsrc_type;
+       u32 start_idx;
+       u32 count;
+       enum i40e_sd_entry_type entry_type;
+       u64 direct_mode_sz;
+};
+
+struct i40e_hmc_lan_delete_obj_info {
+       struct i40e_hmc_info *hmc_info;
+       u32 rsrc_type;
+       u32 start_idx;
+       u32 count;
+};
+
+i40e_status i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num,
+                                       u32 rxq_num, u32 fcoe_cntx_num,
+                                       u32 fcoe_filt_num);
+i40e_status i40e_configure_lan_hmc(struct i40e_hw *hw,
+                                            enum i40e_hmc_model model);
+i40e_status i40e_shutdown_lan_hmc(struct i40e_hw *hw);
+
+i40e_status i40e_clear_lan_tx_queue_context(struct i40e_hw *hw,
+                                                     u16 queue);
+i40e_status i40e_set_lan_tx_queue_context(struct i40e_hw *hw,
+                                                   u16 queue,
+                                                   struct i40e_hmc_obj_txq *s);
+i40e_status i40e_clear_lan_rx_queue_context(struct i40e_hw *hw,
+                                                     u16 queue);
+i40e_status i40e_set_lan_rx_queue_context(struct i40e_hw *hw,
+                                                   u16 queue,
+                                                   struct i40e_hmc_obj_rxq *s);
+
+#endif /* _I40E_LAN_HMC_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h
new file mode 100644 (file)
index 0000000..622f373
--- /dev/null
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_OSDEP_H_
+#define _I40E_OSDEP_H_
+
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/tcp.h>
+#include <linux/pci.h>
+
+/* get readq/writeq support for 32 bit kernels, use the low-first version */
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
+/* File to be the magic between shared code and
+ * actual OS primitives
+ */
+
+#define hw_dbg(hw, S, A...)    do {} while (0)
+
+#define wr32(a, reg, value)    writel((value), ((a)->hw_addr + (reg)))
+#define rd32(a, reg)           readl((a)->hw_addr + (reg))
+
+#define wr64(a, reg, value)    writeq((value), ((a)->hw_addr + (reg)))
+#define rd64(a, reg)           readq((a)->hw_addr + (reg))
+#define i40e_flush(a)          readl((a)->hw_addr + I40E_VFGEN_RSTAT)
+
+/* memory allocation tracking */
+struct i40e_dma_mem {
+       void *va;
+       dma_addr_t pa;
+       u32 size;
+} __packed;
+
+#define i40e_allocate_dma_mem(h, m, unused, s, a) \
+       i40evf_allocate_dma_mem_d(h, m, s, a)
+#define i40e_free_dma_mem(h, m) i40evf_free_dma_mem_d(h, m)
+
+struct i40e_virt_mem {
+       void *va;
+       u32 size;
+} __packed;
+#define i40e_allocate_virt_mem(h, m, s) i40evf_allocate_virt_mem_d(h, m, s)
+#define i40e_free_virt_mem(h, m) i40evf_free_virt_mem_d(h, m)
+
+#define i40e_debug(h, m, s, ...)  i40evf_debug_d(h, m, s, ##__VA_ARGS__)
+extern void i40evf_debug_d(void *hw, u32 mask, char *fmt_str, ...)
+       __attribute__ ((format(gnu_printf, 3, 4)));
+
+typedef enum i40e_status_code i40e_status;
+#endif /* _I40E_OSDEP_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
new file mode 100644 (file)
index 0000000..7841573
--- /dev/null
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_PROTOTYPE_H_
+#define _I40E_PROTOTYPE_H_
+
+#include "i40e_type.h"
+#include "i40e_alloc.h"
+#include "i40e_virtchnl.h"
+
+/* Prototypes for shared code functions that are not in
+ * the standard function pointer structures.  These are
+ * mostly because they are needed even before the init
+ * has happened and will assist in the early SW and FW
+ * setup.
+ */
+
+/* adminq functions */
+i40e_status i40evf_init_adminq(struct i40e_hw *hw);
+i40e_status i40evf_shutdown_adminq(struct i40e_hw *hw);
+void i40e_adminq_init_ring_data(struct i40e_hw *hw);
+i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
+                                            struct i40e_arq_event_info *e,
+                                            u16 *events_pending);
+i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
+                               struct i40e_aq_desc *desc,
+                               void *buff, /* can be NULL */
+                               u16  buff_size,
+                               struct i40e_asq_cmd_details *cmd_details);
+bool i40evf_asq_done(struct i40e_hw *hw);
+
+/* debug function for adminq */
+void i40evf_debug_aq(struct i40e_hw *hw,
+                  enum i40e_debug_mask mask,
+                  void *desc,
+                  void *buffer);
+
+void i40e_idle_aq(struct i40e_hw *hw);
+void i40evf_resume_aq(struct i40e_hw *hw);
+bool i40evf_check_asq_alive(struct i40e_hw *hw);
+i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw,
+                                            bool unloading);
+
+i40e_status i40e_set_mac_type(struct i40e_hw *hw);
+
+/* prototype for functions used for SW locks */
+
+/* i40e_common for VF drivers*/
+void i40e_vf_parse_hw_config(struct i40e_hw *hw,
+                            struct i40e_virtchnl_vf_resource *msg);
+i40e_status i40e_vf_reset(struct i40e_hw *hw);
+i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
+                               enum i40e_virtchnl_ops v_opcode,
+                               i40e_status v_retval,
+                               u8 *msg, u16 msglen,
+                               struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_set_filter_control(struct i40e_hw *hw,
+                               struct i40e_filter_control_settings *settings);
+i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
+                               u8 *mac_addr, u16 ethtype, u16 flags,
+                               u16 vsi_seid, u16 queue, bool is_add,
+                               struct i40e_control_filter_stats *stats,
+                               struct i40e_asq_cmd_details *cmd_details);
+#endif /* _I40E_PROTOTYPE_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_register.h b/drivers/net/ethernet/intel/i40evf/i40e_register.h
new file mode 100644 (file)
index 0000000..30af953
--- /dev/null
@@ -0,0 +1,4667 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_REGISTER_H_
+#define _I40E_REGISTER_H_
+
+#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */
+#define I40E_GL_GP_FUSE_MAX_INDEX 28
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK (0xFFFFFFFF << I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT)
+#define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE 0x0009C600
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
+
+#define I40E_PF_ARQBAH 0x00080180
+#define I40E_PF_ARQBAH_ARQBAH_SHIFT 0
+#define I40E_PF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_PF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_PF_ARQBAL 0x00080080
+#define I40E_PF_ARQBAL_ARQBAL_SHIFT 0
+#define I40E_PF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_PF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_PF_ARQH 0x00080380
+#define I40E_PF_ARQH_ARQH_SHIFT 0
+#define I40E_PF_ARQH_ARQH_MASK (0x3FF << I40E_PF_ARQH_ARQH_SHIFT)
+#define I40E_PF_ARQLEN 0x00080280
+#define I40E_PF_ARQLEN_ARQLEN_SHIFT 0
+#define I40E_PF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_PF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_PF_ARQLEN_ARQVFE_SHIFT 28
+#define I40E_PF_ARQLEN_ARQVFE_MASK (0x1 << I40E_PF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_PF_ARQLEN_ARQOVFL_SHIFT 29
+#define I40E_PF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_PF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_PF_ARQLEN_ARQCRIT_SHIFT 30
+#define I40E_PF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_PF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_PF_ARQLEN_ARQENABLE_SHIFT 31
+#define I40E_PF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_PF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_PF_ARQT 0x00080480
+#define I40E_PF_ARQT_ARQT_SHIFT 0
+#define I40E_PF_ARQT_ARQT_MASK (0x3FF << I40E_PF_ARQT_ARQT_SHIFT)
+#define I40E_PF_ATQBAH 0x00080100
+#define I40E_PF_ATQBAH_ATQBAH_SHIFT 0
+#define I40E_PF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_PF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_PF_ATQBAL 0x00080000
+#define I40E_PF_ATQBAL_ATQBAL_SHIFT 0
+#define I40E_PF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_PF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_PF_ATQH 0x00080300
+#define I40E_PF_ATQH_ATQH_SHIFT 0
+#define I40E_PF_ATQH_ATQH_MASK (0x3FF << I40E_PF_ATQH_ATQH_SHIFT)
+#define I40E_PF_ATQLEN 0x00080200
+#define I40E_PF_ATQLEN_ATQLEN_SHIFT 0
+#define I40E_PF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_PF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_PF_ATQLEN_ATQVFE_SHIFT 28
+#define I40E_PF_ATQLEN_ATQVFE_MASK (0x1 << I40E_PF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_PF_ATQLEN_ATQOVFL_SHIFT 29
+#define I40E_PF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_PF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_PF_ATQLEN_ATQCRIT_SHIFT 30
+#define I40E_PF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_PF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_PF_ATQLEN_ATQENABLE_SHIFT 31
+#define I40E_PF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_PF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_PF_ATQT 0x00080400
+#define I40E_PF_ATQT_ATQT_SHIFT 0
+#define I40E_PF_ATQT_ATQT_MASK (0x3FF << I40E_PF_ATQT_ATQT_SHIFT)
+#define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAH_MAX_INDEX 127
+#define I40E_VF_ARQBAH_ARQBAH_SHIFT 0
+#define I40E_VF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAL_MAX_INDEX 127
+#define I40E_VF_ARQBAL_ARQBAL_SHIFT 0
+#define I40E_VF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQH_MAX_INDEX 127
+#define I40E_VF_ARQH_ARQH_SHIFT 0
+#define I40E_VF_ARQH_ARQH_MASK (0x3FF << I40E_VF_ARQH_ARQH_SHIFT)
+#define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQLEN_MAX_INDEX 127
+#define I40E_VF_ARQLEN_ARQLEN_SHIFT 0
+#define I40E_VF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN_ARQVFE_SHIFT 28
+#define I40E_VF_ARQLEN_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN_ARQOVFL_SHIFT 29
+#define I40E_VF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN_ARQCRIT_SHIFT 30
+#define I40E_VF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN_ARQENABLE_SHIFT 31
+#define I40E_VF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQT_MAX_INDEX 127
+#define I40E_VF_ARQT_ARQT_SHIFT 0
+#define I40E_VF_ARQT_ARQT_MASK (0x3FF << I40E_VF_ARQT_ARQT_SHIFT)
+#define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAH_MAX_INDEX 127
+#define I40E_VF_ATQBAH_ATQBAH_SHIFT 0
+#define I40E_VF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAL_MAX_INDEX 127
+#define I40E_VF_ATQBAL_ATQBAL_SHIFT 0
+#define I40E_VF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQH_MAX_INDEX 127
+#define I40E_VF_ATQH_ATQH_SHIFT 0
+#define I40E_VF_ATQH_ATQH_MASK (0x3FF << I40E_VF_ATQH_ATQH_SHIFT)
+#define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQLEN_MAX_INDEX 127
+#define I40E_VF_ATQLEN_ATQLEN_SHIFT 0
+#define I40E_VF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN_ATQVFE_SHIFT 28
+#define I40E_VF_ATQLEN_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN_ATQOVFL_SHIFT 29
+#define I40E_VF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN_ATQCRIT_SHIFT 30
+#define I40E_VF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN_ATQENABLE_SHIFT 31
+#define I40E_VF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQT_MAX_INDEX 127
+#define I40E_VF_ATQT_ATQT_SHIFT 0
+#define I40E_VF_ATQT_ATQT_MASK (0x3FF << I40E_VF_ATQT_ATQT_SHIFT)
+#define I40E_PRT_L2TAGSEN 0x001C0B20
+#define I40E_PRT_L2TAGSEN_ENABLE_SHIFT 0
+#define I40E_PRT_L2TAGSEN_ENABLE_MASK (0xFF << I40E_PRT_L2TAGSEN_ENABLE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA 0x0010C080
+#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT 0
+#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT 4
+#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT 8
+#define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK (0xFFF << I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO 0x0010C000
+#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT 0
+#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT 4
+#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT 8
+#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT 16
+#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT 24
+#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LANCTXCTL(_pf) (0x0010C300 + ((_pf) * 4))/* _pf=0..15 */
+#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT 0
+#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK (0xFFF << I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT)
+#define I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT 12
+#define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK (0x7 << I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT 15
+#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK (0x3 << I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT 17
+#define I40E_PFCM_LANCTXCTL_OP_CODE_MASK (0x3 << I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT)
+#define I40E_PFCM_LANCTXDATA(_i, _pf) (0x0010C100 + ((_i) * 4) + ((_pf) * 16))/* _i=0...3 _pf=0..15 */
+#define I40E_PFCM_LANCTXDATA_MAX_INDEX 3
+#define I40E_PFCM_LANCTXDATA_DATA_SHIFT 0
+#define I40E_PFCM_LANCTXDATA_DATA_MASK (0xFFFFFFFF << I40E_PFCM_LANCTXDATA_DATA_SHIFT)
+#define I40E_PFCM_LANCTXSTAT(_pf) (0x0010C380 + ((_pf) * 4))/* _pf=0..15 */
+#define I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT 0
+#define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT)
+#define I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT 1
+#define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT)
+#define I40E_PFCM_PE_ERRDATA 0x00138D00
+#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
+#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
+#define I40E_PFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT 8
+#define I40E_PFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT)
+#define I40E_PFCM_PE_ERRINFO 0x00138C80
+#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
+#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
+#define I40E_PFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
+#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
+#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
+#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFCM_PE_ERRDATA1_MAX_INDEX 127
+#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT 0
+#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT 4
+#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT 8
+#define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFCM_PE_ERRINFO1_MAX_INDEX 127
+#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT 0
+#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT 4
+#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT 8
+#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT 16
+#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT 24
+#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT)
+#define I40E_GLDCB_GENC 0x00083044
+#define I40E_GLDCB_GENC_PCIRTT_SHIFT 0
+#define I40E_GLDCB_GENC_PCIRTT_MASK (0xFFFF << I40E_GLDCB_GENC_PCIRTT_SHIFT)
+#define I40E_GLDCB_RUPTI 0x00122618
+#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT 0
+#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK (0xFFFFFFFF << I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT)
+#define I40E_PRTDCB_FCCFG 0x001E4640
+#define I40E_PRTDCB_FCCFG_TFCE_SHIFT 3
+#define I40E_PRTDCB_FCCFG_TFCE_MASK (0x3 << I40E_PRTDCB_FCCFG_TFCE_SHIFT)
+#define I40E_PRTDCB_FCRTV 0x001E4600
+#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT 0
+#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK (0xFFFF << I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT)
+#define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTDCB_FCTTVN_MAX_INDEX 3
+#define I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT 0
+#define I40E_PRTDCB_FCTTVN_TTV_2N_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT)
+#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT 16
+#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT)
+#define I40E_PRTDCB_GENC 0x00083000
+#define I40E_PRTDCB_GENC_RESERVED_1_SHIFT 0
+#define I40E_PRTDCB_GENC_RESERVED_1_MASK (0x3 << I40E_PRTDCB_GENC_RESERVED_1_SHIFT)
+#define I40E_PRTDCB_GENC_NUMTC_SHIFT 2
+#define I40E_PRTDCB_GENC_NUMTC_MASK (0xF << I40E_PRTDCB_GENC_NUMTC_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_SHIFT 6
+#define I40E_PRTDCB_GENC_FCOEUP_MASK (0x7 << I40E_PRTDCB_GENC_FCOEUP_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT 9
+#define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK (0x1 << I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT)
+#define I40E_PRTDCB_GENC_PFCLDA_SHIFT 16
+#define I40E_PRTDCB_GENC_PFCLDA_MASK (0xFFFF << I40E_PRTDCB_GENC_PFCLDA_SHIFT)
+#define I40E_PRTDCB_GENS 0x00083020
+#define I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT 0
+#define I40E_PRTDCB_GENS_DCBX_STATUS_MASK (0x7 << I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT)
+#define I40E_PRTDCB_MFLCN 0x001E2400
+#define I40E_PRTDCB_MFLCN_PMCF_SHIFT 0
+#define I40E_PRTDCB_MFLCN_PMCF_MASK (0x1 << I40E_PRTDCB_MFLCN_PMCF_SHIFT)
+#define I40E_PRTDCB_MFLCN_DPF_SHIFT 1
+#define I40E_PRTDCB_MFLCN_DPF_MASK (0x1 << I40E_PRTDCB_MFLCN_DPF_SHIFT)
+#define I40E_PRTDCB_MFLCN_RPFCM_SHIFT 2
+#define I40E_PRTDCB_MFLCN_RPFCM_MASK (0x1 << I40E_PRTDCB_MFLCN_RPFCM_SHIFT)
+#define I40E_PRTDCB_MFLCN_RFCE_SHIFT 3
+#define I40E_PRTDCB_MFLCN_RFCE_MASK (0x1 << I40E_PRTDCB_MFLCN_RFCE_SHIFT)
+#define I40E_PRTDCB_MFLCN_RPFCE_SHIFT 4
+#define I40E_PRTDCB_MFLCN_RPFCE_MASK (0xFF << I40E_PRTDCB_MFLCN_RPFCE_SHIFT)
+#define I40E_PRTDCB_RETSC 0x001223E0
+#define I40E_PRTDCB_RETSC_ETS_MODE_SHIFT 0
+#define I40E_PRTDCB_RETSC_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT 1
+#define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT 2
+#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK (0xF << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT)
+#define I40E_PRTDCB_RETSC_LLTC_SHIFT 8
+#define I40E_PRTDCB_RETSC_LLTC_MASK (0xFF << I40E_PRTDCB_RETSC_LLTC_SHIFT)
+#define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_RETSTCC_MAX_INDEX 7
+#define I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT 0
+#define I40E_PRTDCB_RETSTCC_BWSHARE_MASK (0x7F << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT 30
+#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK (0x1 << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_ETSTC_SHIFT 31
+#define I40E_PRTDCB_RETSTCC_ETSTC_MASK (0x1 << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT)
+#define I40E_PRTDCB_RPPMC 0x001223A0
+#define I40E_PRTDCB_RPPMC_LANRPPM_SHIFT 0
+#define I40E_PRTDCB_RPPMC_LANRPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_LANRPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT 8
+#define I40E_PRTDCB_RPPMC_RDMARPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT 16
+#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK (0xFF << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT)
+#define I40E_PRTDCB_RUP 0x001C0B00
+#define I40E_PRTDCB_RUP_NOVLANUP_SHIFT 0
+#define I40E_PRTDCB_RUP_NOVLANUP_MASK (0x7 << I40E_PRTDCB_RUP_NOVLANUP_SHIFT)
+#define I40E_PRTDCB_RUP2TC 0x001C09A0
+#define I40E_PRTDCB_RUP2TC_UP0TC_SHIFT 0
+#define I40E_PRTDCB_RUP2TC_UP0TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP0TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP1TC_SHIFT 3
+#define I40E_PRTDCB_RUP2TC_UP1TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP1TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP2TC_SHIFT 6
+#define I40E_PRTDCB_RUP2TC_UP2TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP2TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP3TC_SHIFT 9
+#define I40E_PRTDCB_RUP2TC_UP3TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP3TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP4TC_SHIFT 12
+#define I40E_PRTDCB_RUP2TC_UP4TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP4TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP5TC_SHIFT 15
+#define I40E_PRTDCB_RUP2TC_UP5TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP5TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP6TC_SHIFT 18
+#define I40E_PRTDCB_RUP2TC_UP6TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP6TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP7TC_SHIFT 21
+#define I40E_PRTDCB_RUP2TC_UP7TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP7TC_SHIFT)
+#define I40E_PRTDCB_TC2PFC 0x001C0980
+#define I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT 0
+#define I40E_PRTDCB_TC2PFC_TC2PFC_MASK (0xFF << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT)
+#define I40E_PRTDCB_TCPMC 0x000A21A0
+#define I40E_PRTDCB_TCPMC_CPM_SHIFT 0
+#define I40E_PRTDCB_TCPMC_CPM_MASK (0x1FFF << I40E_PRTDCB_TCPMC_CPM_SHIFT)
+#define I40E_PRTDCB_TCPMC_LLTC_SHIFT 13
+#define I40E_PRTDCB_TCPMC_LLTC_MASK (0xFF << I40E_PRTDCB_TCPMC_LLTC_SHIFT)
+#define I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT 30
+#define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TCWSTC_MAX_INDEX 7
+#define I40E_PRTDCB_TCWSTC_MSTC_SHIFT 0
+#define I40E_PRTDCB_TCWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TCWSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TDPMC 0x000A0180
+#define I40E_PRTDCB_TDPMC_DPM_SHIFT 0
+#define I40E_PRTDCB_TDPMC_DPM_MASK (0xFF << I40E_PRTDCB_TDPMC_DPM_SHIFT)
+#define I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT 30
+#define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TDPUC 0x00044100
+#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT 0
+#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_MASK (0xFFFF << I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB 0x000AE060
+#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT 0
+#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT 8
+#define I40E_PRTDCB_TETSC_TCB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB 0x00098060
+#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT 0
+#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT 8
+#define I40E_PRTDCB_TETSC_TPB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT)
+#define I40E_PRTDCB_TFCS 0x001E4560
+#define I40E_PRTDCB_TFCS_TXOFF_SHIFT 0
+#define I40E_PRTDCB_TFCS_TXOFF_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF0_SHIFT 8
+#define I40E_PRTDCB_TFCS_TXOFF0_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF0_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF1_SHIFT 9
+#define I40E_PRTDCB_TFCS_TXOFF1_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF1_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF2_SHIFT 10
+#define I40E_PRTDCB_TFCS_TXOFF2_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF2_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF3_SHIFT 11
+#define I40E_PRTDCB_TFCS_TXOFF3_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF3_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF4_SHIFT 12
+#define I40E_PRTDCB_TFCS_TXOFF4_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF4_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF5_SHIFT 13
+#define I40E_PRTDCB_TFCS_TXOFF5_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF5_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF6_SHIFT 14
+#define I40E_PRTDCB_TFCS_TXOFF6_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF6_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF7_SHIFT 15
+#define I40E_PRTDCB_TFCS_TXOFF7_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF7_SHIFT)
+#define I40E_PRTDCB_TFWSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TFWSTC_MAX_INDEX 7
+#define I40E_PRTDCB_TFWSTC_MSTC_SHIFT 0
+#define I40E_PRTDCB_TFWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TFWSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TPFCTS_MAX_INDEX 7
+#define I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT 0
+#define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK (0x3FFF << I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT)
+#define I40E_GLFCOE_RCTL 0x00269B94
+#define I40E_GLFCOE_RCTL_FCOEVER_SHIFT 0
+#define I40E_GLFCOE_RCTL_FCOEVER_MASK (0xF << I40E_GLFCOE_RCTL_FCOEVER_SHIFT)
+#define I40E_GLFCOE_RCTL_SAVBAD_SHIFT 4
+#define I40E_GLFCOE_RCTL_SAVBAD_MASK (0x1 << I40E_GLFCOE_RCTL_SAVBAD_SHIFT)
+#define I40E_GLFCOE_RCTL_ICRC_SHIFT 5
+#define I40E_GLFCOE_RCTL_ICRC_MASK (0x1 << I40E_GLFCOE_RCTL_ICRC_SHIFT)
+#define I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT 16
+#define I40E_GLFCOE_RCTL_MAX_SIZE_MASK (0x3FFF << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT)
+#define I40E_GL_FWSTS 0x00083048
+#define I40E_GL_FWSTS_FWS0B_SHIFT 0
+#define I40E_GL_FWSTS_FWS0B_MASK (0xFF << I40E_GL_FWSTS_FWS0B_SHIFT)
+#define I40E_GL_FWSTS_FWRI_SHIFT 9
+#define I40E_GL_FWSTS_FWRI_MASK (0x1 << I40E_GL_FWSTS_FWRI_SHIFT)
+#define I40E_GL_FWSTS_FWS1B_SHIFT 16
+#define I40E_GL_FWSTS_FWS1B_MASK (0xFF << I40E_GL_FWSTS_FWS1B_SHIFT)
+#define I40E_GLGEN_CLKSTAT 0x000B8184
+#define I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT 0
+#define I40E_GLGEN_CLKSTAT_CLKMODE_MASK (0x1 << I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT)
+#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT 4
+#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK (0x3 << I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT 8
+#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT 12
+#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT 16
+#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT 20
+#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */
+#define I40E_GLGEN_GPIO_CTL_MAX_INDEX 29
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT 0
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK (0x3 << I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT 3
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT 4
+#define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT 5
+#define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT 6
+#define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT 7
+#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK (0x7 << I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT 10
+#define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT 11
+#define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT 12
+#define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK (0xF << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT 17
+#define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK (0x3 << I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT 19
+#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT 20
+#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK (0x3F << I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT)
+#define I40E_GLGEN_GPIO_SET 0x00088184
+#define I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT 0
+#define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK (0x1F << I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT)
+#define I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT 5
+#define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK (0x1 << I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT)
+#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT 6
+#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK (0x1 << I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT)
+#define I40E_GLGEN_GPIO_STAT 0x0008817C
+#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT 0
+#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT)
+#define I40E_GLGEN_GPIO_TRANSIT 0x00088180
+#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT 0
+#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT)
+#define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_I2CCMD_MAX_INDEX 3
+#define I40E_GLGEN_I2CCMD_DATA_SHIFT 0
+#define I40E_GLGEN_I2CCMD_DATA_MASK (0xFFFF << I40E_GLGEN_I2CCMD_DATA_SHIFT)
+#define I40E_GLGEN_I2CCMD_REGADD_SHIFT 16
+#define I40E_GLGEN_I2CCMD_REGADD_MASK (0xFF << I40E_GLGEN_I2CCMD_REGADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_PHYADD_SHIFT 24
+#define I40E_GLGEN_I2CCMD_PHYADD_MASK (0x7 << I40E_GLGEN_I2CCMD_PHYADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_OP_SHIFT 27
+#define I40E_GLGEN_I2CCMD_OP_MASK (0x1 << I40E_GLGEN_I2CCMD_OP_SHIFT)
+#define I40E_GLGEN_I2CCMD_RESET_SHIFT 28
+#define I40E_GLGEN_I2CCMD_RESET_MASK (0x1 << I40E_GLGEN_I2CCMD_RESET_SHIFT)
+#define I40E_GLGEN_I2CCMD_R_SHIFT 29
+#define I40E_GLGEN_I2CCMD_R_MASK (0x1 << I40E_GLGEN_I2CCMD_R_SHIFT)
+#define I40E_GLGEN_I2CCMD_E_SHIFT 31
+#define I40E_GLGEN_I2CCMD_E_MASK (0x1 << I40E_GLGEN_I2CCMD_E_SHIFT)
+#define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_I2CPARAMS_MAX_INDEX 3
+#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT 0
+#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK (0x1F << I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT 5
+#define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK (0x7 << I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT 8
+#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_SHIFT 9
+#define I40E_GLGEN_I2CPARAMS_CLK_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT 10
+#define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT 11
+#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT 12
+#define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT 13
+#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT 14
+#define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT 15
+#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT 31
+#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT)
+#define I40E_GLGEN_LED_CTL 0x00088178
+#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT 0
+#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK (0x1 << I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_CTRL_MAX_INDEX 3
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT 0
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK (0x1FFFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT 17
+#define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK (0x1 << I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT 18
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK (0x3FFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_I2C_SEL_MAX_INDEX 3
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT 0
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT 1
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT 5
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT 10
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT 15
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT 20
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT 25
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT 31
+#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT)
+#define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MSCA_MAX_INDEX 3
+#define I40E_GLGEN_MSCA_MDIADD_SHIFT 0
+#define I40E_GLGEN_MSCA_MDIADD_MASK (0xFFFF << I40E_GLGEN_MSCA_MDIADD_SHIFT)
+#define I40E_GLGEN_MSCA_DEVADD_SHIFT 16
+#define I40E_GLGEN_MSCA_DEVADD_MASK (0x1F << I40E_GLGEN_MSCA_DEVADD_SHIFT)
+#define I40E_GLGEN_MSCA_PHYADD_SHIFT 21
+#define I40E_GLGEN_MSCA_PHYADD_MASK (0x1F << I40E_GLGEN_MSCA_PHYADD_SHIFT)
+#define I40E_GLGEN_MSCA_OPCODE_SHIFT 26
+#define I40E_GLGEN_MSCA_OPCODE_MASK (0x3 << I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_GLGEN_MSCA_STCODE_SHIFT 28
+#define I40E_GLGEN_MSCA_STCODE_MASK (0x3 << I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_GLGEN_MSCA_MDICMD_SHIFT 30
+#define I40E_GLGEN_MSCA_MDICMD_MASK (0x1 << I40E_GLGEN_MSCA_MDICMD_SHIFT)
+#define I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT 31
+#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK (0x1 << I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT)
+#define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MSRWD_MAX_INDEX 3
+#define I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT 0
+#define I40E_GLGEN_MSRWD_MDIWRDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT)
+#define I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT 16
+#define I40E_GLGEN_MSRWD_MDIRDDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT 0x001C0AB4
+#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT 0
+#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK (0x1F << I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT 16
+#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK (0xFF << I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
+#define I40E_GLGEN_PE_ENA 0x000B81A0
+#define I40E_GLGEN_PE_ENA_PE_ENA_SHIFT 0
+#define I40E_GLGEN_PE_ENA_PE_ENA_MASK (0x1 << I40E_GLGEN_PE_ENA_PE_ENA_SHIFT)
+#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT 1
+#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_MASK (0x3 << I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT)
+#define I40E_GLGEN_RSTAT 0x000B8188
+#define I40E_GLGEN_RSTAT_DEVSTATE_SHIFT 0
+#define I40E_GLGEN_RSTAT_DEVSTATE_MASK (0x3 << I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
+#define I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT 2
+#define I40E_GLGEN_RSTAT_RESET_TYPE_MASK (0x3 << I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT)
+#define I40E_GLGEN_RSTAT_CORERCNT_SHIFT 4
+#define I40E_GLGEN_RSTAT_CORERCNT_MASK (0x3 << I40E_GLGEN_RSTAT_CORERCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT 6
+#define I40E_GLGEN_RSTAT_GLOBRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_EMPRCNT_SHIFT 8
+#define I40E_GLGEN_RSTAT_EMPRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_EMPRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT 10
+#define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK (0x3F << I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT)
+#define I40E_GLGEN_RSTCTL 0x000B8180
+#define I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT 0
+#define I40E_GLGEN_RSTCTL_GRSTDEL_MASK (0x3F << I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT)
+#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT 8
+#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT)
+#define I40E_GLGEN_RSTENA_EMP 0x000B818C
+#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT 0
+#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT)
+#define I40E_GLGEN_RTRIG 0x000B8190
+#define I40E_GLGEN_RTRIG_CORER_SHIFT 0
+#define I40E_GLGEN_RTRIG_CORER_MASK (0x1 << I40E_GLGEN_RTRIG_CORER_SHIFT)
+#define I40E_GLGEN_RTRIG_GLOBR_SHIFT 1
+#define I40E_GLGEN_RTRIG_GLOBR_MASK (0x1 << I40E_GLGEN_RTRIG_GLOBR_SHIFT)
+#define I40E_GLGEN_RTRIG_EMPFWR_SHIFT 2
+#define I40E_GLGEN_RTRIG_EMPFWR_MASK (0x1 << I40E_GLGEN_RTRIG_EMPFWR_SHIFT)
+#define I40E_GLGEN_STAT 0x000B612C
+#define I40E_GLGEN_STAT_HWRSVD0_SHIFT 0
+#define I40E_GLGEN_STAT_HWRSVD0_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD0_SHIFT)
+#define I40E_GLGEN_STAT_DCBEN_SHIFT 2
+#define I40E_GLGEN_STAT_DCBEN_MASK (0x1 << I40E_GLGEN_STAT_DCBEN_SHIFT)
+#define I40E_GLGEN_STAT_VTEN_SHIFT 3
+#define I40E_GLGEN_STAT_VTEN_MASK (0x1 << I40E_GLGEN_STAT_VTEN_SHIFT)
+#define I40E_GLGEN_STAT_FCOEN_SHIFT 4
+#define I40E_GLGEN_STAT_FCOEN_MASK (0x1 << I40E_GLGEN_STAT_FCOEN_SHIFT)
+#define I40E_GLGEN_STAT_EVBEN_SHIFT 5
+#define I40E_GLGEN_STAT_EVBEN_MASK (0x1 << I40E_GLGEN_STAT_EVBEN_SHIFT)
+#define I40E_GLGEN_STAT_HWRSVD1_SHIFT 6
+#define I40E_GLGEN_STAT_HWRSVD1_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD1_SHIFT)
+#define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_VFLRSTAT_MAX_INDEX 3
+#define I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT 0
+#define I40E_GLGEN_VFLRSTAT_VFLRE_MASK (0xFFFFFFFF << I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT)
+#define I40E_GLVFGEN_TIMER 0x000881BC
+#define I40E_GLVFGEN_TIMER_GTIME_SHIFT 0
+#define I40E_GLVFGEN_TIMER_GTIME_MASK (0xFFFFFFFF << I40E_GLVFGEN_TIMER_GTIME_SHIFT)
+#define I40E_PFGEN_CTRL 0x00092400
+#define I40E_PFGEN_CTRL_PFSWR_SHIFT 0
+#define I40E_PFGEN_CTRL_PFSWR_MASK (0x1 << I40E_PFGEN_CTRL_PFSWR_SHIFT)
+#define I40E_PFGEN_DRUN 0x00092500
+#define I40E_PFGEN_DRUN_DRVUNLD_SHIFT 0
+#define I40E_PFGEN_DRUN_DRVUNLD_MASK (0x1 << I40E_PFGEN_DRUN_DRVUNLD_SHIFT)
+#define I40E_PFGEN_PORTNUM 0x001C0480
+#define I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT 0
+#define I40E_PFGEN_PORTNUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_STATE 0x00088000
+#define I40E_PFGEN_STATE_PFPEEN_SHIFT 0
+#define I40E_PFGEN_STATE_PFPEEN_MASK (0x1 << I40E_PFGEN_STATE_PFPEEN_SHIFT)
+#define I40E_PFGEN_STATE_PFFCEN_SHIFT 1
+#define I40E_PFGEN_STATE_PFFCEN_MASK (0x1 << I40E_PFGEN_STATE_PFFCEN_SHIFT)
+#define I40E_PFGEN_STATE_PFLINKEN_SHIFT 2
+#define I40E_PFGEN_STATE_PFLINKEN_MASK (0x1 << I40E_PFGEN_STATE_PFLINKEN_SHIFT)
+#define I40E_PFGEN_STATE_PFSCEN_SHIFT 3
+#define I40E_PFGEN_STATE_PFSCEN_MASK (0x1 << I40E_PFGEN_STATE_PFSCEN_SHIFT)
+#define I40E_PRTGEN_CNF 0x000B8120
+#define I40E_PRTGEN_CNF_PORT_DIS_SHIFT 0
+#define I40E_PRTGEN_CNF_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT 1
+#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT 2
+#define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF2 0x000B8160
+#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT 0
+#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK (0x1 << I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT)
+#define I40E_PRTGEN_STATUS 0x000B8100
+#define I40E_PRTGEN_STATUS_PORT_VALID_SHIFT 0
+#define I40E_PRTGEN_STATUS_PORT_VALID_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_VALID_SHIFT)
+#define I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT 1
+#define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT)
+#define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFGEN_RSTAT1_MAX_INDEX 127
+#define I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT 0
+#define I40E_VFGEN_RSTAT1_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT)
+#define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPGEN_VFRSTAT_MAX_INDEX 127
+#define I40E_VPGEN_VFRSTAT_VFRD_SHIFT 0
+#define I40E_VPGEN_VFRSTAT_VFRD_MASK (0x1 << I40E_VPGEN_VFRSTAT_VFRD_SHIFT)
+#define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPGEN_VFRTRIG_MAX_INDEX 127
+#define I40E_VPGEN_VFRTRIG_VFSWR_SHIFT 0
+#define I40E_VPGEN_VFRTRIG_VFSWR_MASK (0x1 << I40E_VPGEN_VFRTRIG_VFSWR_SHIFT)
+#define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VSIGEN_RSTAT_MAX_INDEX 383
+#define I40E_VSIGEN_RSTAT_VMRD_SHIFT 0
+#define I40E_VSIGEN_RSTAT_VMRD_MASK (0x1 << I40E_VSIGEN_RSTAT_VMRD_SHIFT)
+#define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VSIGEN_RTRIG_MAX_INDEX 383
+#define I40E_VSIGEN_RTRIG_VMSWR_SHIFT 0
+#define I40E_VSIGEN_RTRIG_VMSWR_MASK (0x1 << I40E_VSIGEN_RTRIG_VMSWR_SHIFT)
+#define I40E_GLHMC_APBVTINUSEBASE(_i) (0x000C4a00 + ((_i) * 4))
+#define I40E_GLHMC_APBVTINUSEBASE_MAX_INDEX 15
+#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
+#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
+#define I40E_GLHMC_CEQPART(_i) (0x001312C0 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_CEQPART_MAX_INDEX 15
+#define I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT 0
+#define I40E_GLHMC_CEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT)
+#define I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT 16
+#define I40E_GLHMC_CEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT)
+#define I40E_GLHMC_DBCQPART(_i) (0x00131240 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_DBCQPART_MAX_INDEX 15
+#define I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT 0
+#define I40E_GLHMC_DBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT)
+#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT 16
+#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT)
+#define I40E_GLHMC_DBQPPART(_i) (0x00138D80 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_DBQPPART_MAX_INDEX 15
+#define I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT 0
+#define I40E_GLHMC_DBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT)
+#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT 16
+#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT)
+#define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPBASE_MAX_INDEX 15
+#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT 0
+#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT)
+#define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPCNT_MAX_INDEX 15
+#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT 0
+#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK (0xFFFFF << I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT)
+#define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010
+#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT 0
+#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK (0xF << I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEFBASE_MAX_INDEX 15
+#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT 0
+#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT)
+#define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEFCNT_MAX_INDEX 15
+#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT 0
+#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK (0x7FFFFF << I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT)
+#define I40E_GLHMC_FCOEFMAX 0x000C20D0
+#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT 0
+#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK (0xFFFF << I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT)
+#define I40E_GLHMC_FCOEFOBJSZ 0x000C2018
+#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT 0
+#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK (0xF << I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEMAX 0x000C2014
+#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT 0
+#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK (0x1FFF << I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT)
+#define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVBASE_MAX_INDEX 15
+#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT 0
+#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT)
+#define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVCNT_MAX_INDEX 15
+#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT 0
+#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT)
+#define I40E_GLHMC_FSIAVCNT_RSVD_SHIFT 29
+#define I40E_GLHMC_FSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_FSIAVCNT_RSVD_SHIFT)
+#define I40E_GLHMC_FSIAVMAX 0x000C2068
+#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT 0
+#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK (0x1FFFF << I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT)
+#define I40E_GLHMC_FSIAVOBJSZ 0x000C2064
+#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT 0
+#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK (0xF << I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT)
+#define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIMCBASE_MAX_INDEX 15
+#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT 0
+#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT)
+#define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIMCCNT_MAX_INDEX 15
+#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT 0
+#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK (0x1FFFFFFF << I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT)
+#define I40E_GLHMC_FSIMCMAX 0x000C2060
+#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT 0
+#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK (0x3FFF << I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT)
+#define I40E_GLHMC_FSIMCOBJSZ 0x000C205c
+#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT 0
+#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK (0xF << I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT)
+#define I40E_GLHMC_LANQMAX 0x000C2008
+#define I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT 0
+#define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK (0x7FF << I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT)
+#define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXBASE_MAX_INDEX 15
+#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT 0
+#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT)
+#define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXCNT_MAX_INDEX 15
+#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT 0
+#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK (0x7FF << I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT)
+#define I40E_GLHMC_LANRXOBJSZ 0x000C200c
+#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT 0
+#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK (0xF << I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT)
+#define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXBASE_MAX_INDEX 15
+#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT 0
+#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT)
+#define I40E_GLHMC_LANTXBASE_RSVD_SHIFT 24
+#define I40E_GLHMC_LANTXBASE_RSVD_MASK (0xFF << I40E_GLHMC_LANTXBASE_RSVD_SHIFT)
+#define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXCNT_MAX_INDEX 15
+#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT 0
+#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK (0x7FF << I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT)
+#define I40E_GLHMC_LANTXOBJSZ 0x000C2004
+#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT 0
+#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK (0xF << I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT)
+#define I40E_GLHMC_PEARPBASE(_i) (0x000C4800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEARPBASE_MAX_INDEX 15
+#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT 0
+#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT)
+#define I40E_GLHMC_PEARPCNT(_i) (0x000C4900 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEARPCNT_MAX_INDEX 15
+#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT 0
+#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT)
+#define I40E_GLHMC_PEARPMAX 0x000C2038
+#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT 0
+#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_MASK (0x1FFFF << I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT)
+#define I40E_GLHMC_PEARPOBJSZ 0x000C2034
+#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT 0
+#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_MASK (0x7 << I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT)
+#define I40E_GLHMC_PECQBASE(_i) (0x000C4200 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PECQBASE_MAX_INDEX 15
+#define I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT 0
+#define I40E_GLHMC_PECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT)
+#define I40E_GLHMC_PECQCNT(_i) (0x000C4300 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PECQCNT_MAX_INDEX 15
+#define I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT 0
+#define I40E_GLHMC_PECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT)
+#define I40E_GLHMC_PECQOBJSZ 0x000C2020
+#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT 0
+#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_MASK (0xF << I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT)
+#define I40E_GLHMC_PEHTCNT(_i) (0x000C4700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEHTCNT_MAX_INDEX 15
+#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT 0
+#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT)
+#define I40E_GLHMC_PEHTEBASE(_i) (0x000C4600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEHTEBASE_MAX_INDEX 15
+#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT 0
+#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT)
+#define I40E_GLHMC_PEHTEOBJSZ 0x000C202c
+#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT 0
+#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_MASK (0xF << I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT)
+#define I40E_GLHMC_PEHTMAX 0x000C2030
+#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT 0
+#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_MASK (0x1FFFFF << I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT)
+#define I40E_GLHMC_PEMRBASE(_i) (0x000C4c00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEMRBASE_MAX_INDEX 15
+#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT 0
+#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT)
+#define I40E_GLHMC_PEMRCNT(_i) (0x000C4d00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEMRCNT_MAX_INDEX 15
+#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT 0
+#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT)
+#define I40E_GLHMC_PEMRMAX 0x000C2040
+#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT 0
+#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_MASK (0x7FFFFF << I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT)
+#define I40E_GLHMC_PEMROBJSZ 0x000C203c
+#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT 0
+#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_MASK (0xF << I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT)
+#define I40E_GLHMC_PEPBLBASE(_i) (0x000C5800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEPBLBASE_MAX_INDEX 15
+#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT 0
+#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT)
+#define I40E_GLHMC_PEPBLCNT(_i) (0x000C5900 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEPBLCNT_MAX_INDEX 15
+#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT 0
+#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT)
+#define I40E_GLHMC_PEPBLMAX 0x000C206c
+#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT 0
+#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT)
+#define I40E_GLHMC_PEQ1BASE(_i) (0x000C5200 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEQ1BASE_MAX_INDEX 15
+#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT 0
+#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT)
+#define I40E_GLHMC_PEQ1CNT(_i) (0x000C5300 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEQ1CNT_MAX_INDEX 15
+#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT 0
+#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT)
+#define I40E_GLHMC_PEQ1FLBASE(_i) (0x000C5400 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEQ1FLBASE_MAX_INDEX 15
+#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
+#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
+#define I40E_GLHMC_PEQ1FLCNT(_i) (0x000C5500 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEQ1FLCNT_MAX_INDEX 15
+#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
+#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
+#define I40E_GLHMC_PEQ1FLMAX 0x000C2058
+#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT 0
+#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT)
+#define I40E_GLHMC_PEQ1MAX 0x000C2054
+#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT 0
+#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT)
+#define I40E_GLHMC_PEQ1OBJSZ 0x000C2050
+#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT 0
+#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_MASK (0xF << I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT)
+#define I40E_GLHMC_PEQPBASE(_i) (0x000C4000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEQPBASE_MAX_INDEX 15
+#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT 0
+#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT)
+#define I40E_GLHMC_PEQPCNT(_i) (0x000C4100 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEQPCNT_MAX_INDEX 15
+#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT 0
+#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT)
+#define I40E_GLHMC_PEQPOBJSZ 0x000C201c
+#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT 0
+#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_MASK (0xF << I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT)
+#define I40E_GLHMC_PESRQBASE(_i) (0x000C4400 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PESRQBASE_MAX_INDEX 15
+#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT 0
+#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT)
+#define I40E_GLHMC_PESRQCNT(_i) (0x000C4500 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PESRQCNT_MAX_INDEX 15
+#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT 0
+#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT)
+#define I40E_GLHMC_PESRQMAX 0x000C2028
+#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT 0
+#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_MASK (0xFFFF << I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT)
+#define I40E_GLHMC_PESRQOBJSZ 0x000C2024
+#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT 0
+#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_MASK (0xF << I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT)
+#define I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT 4
+#define I40E_GLHMC_PESRQOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT)
+#define I40E_GLHMC_PETIMERBASE(_i) (0x000C5A00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PETIMERBASE_MAX_INDEX 15
+#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT 0
+#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT)
+#define I40E_GLHMC_PETIMERCNT(_i) (0x000C5B00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PETIMERCNT_MAX_INDEX 15
+#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT 0
+#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT)
+#define I40E_GLHMC_PETIMERMAX 0x000C2084
+#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT 0
+#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT)
+#define I40E_GLHMC_PETIMEROBJSZ 0x000C2080
+#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT 0
+#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_MASK (0xF << I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT)
+#define I40E_GLHMC_PEXFBASE(_i) (0x000C4e00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEXFBASE_MAX_INDEX 15
+#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT 0
+#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT)
+#define I40E_GLHMC_PEXFCNT(_i) (0x000C4f00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEXFCNT_MAX_INDEX 15
+#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT 0
+#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT)
+#define I40E_GLHMC_PEXFFLBASE(_i) (0x000C5000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEXFFLBASE_MAX_INDEX 15
+#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
+#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT)
+#define I40E_GLHMC_PEXFFLCNT(_i) (0x000C5100 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PEXFFLCNT_MAX_INDEX 15
+#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
+#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT)
+#define I40E_GLHMC_PEXFFLMAX 0x000C204c
+#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT 0
+#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_MASK (0x1FFFFFF << I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT)
+#define I40E_GLHMC_PEXFMAX 0x000C2048
+#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT 0
+#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT)
+#define I40E_GLHMC_PEXFOBJSZ 0x000C2044
+#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT 0
+#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_MASK (0xF << I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT)
+#define I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT 4
+#define I40E_GLHMC_PEXFOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT)
+#define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PFASSIGN_MAX_INDEX 15
+#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT 0
+#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK (0xF << I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT)
+#define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_SDPART_MAX_INDEX 15
+#define I40E_GLHMC_SDPART_PMSDBASE_SHIFT 0
+#define I40E_GLHMC_SDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_SDPART_PMSDBASE_SHIFT)
+#define I40E_GLHMC_SDPART_PMSDSIZE_SHIFT 16
+#define I40E_GLHMC_SDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_SDPART_PMSDSIZE_SHIFT)
+#define I40E_GLHMC_VFAPBVTINUSEBASE(_i) (0x000Cca00 + ((_i) * 4))
+#define I40E_GLHMC_VFAPBVTINUSEBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
+#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
+#define I40E_GLHMC_VFCEQPART(_i) (0x00132240 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFCEQPART_MAX_INDEX 31
+#define I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT 0
+#define I40E_GLHMC_VFCEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT)
+#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT 16
+#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT)
+#define I40E_GLHMC_VFDBCQPART(_i) (0x00132140 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFDBCQPART_MAX_INDEX 31
+#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT 0
+#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT)
+#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT 16
+#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT)
+#define I40E_GLHMC_VFDBQPPART(_i) (0x00138E00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFDBQPPART_MAX_INDEX 31
+#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT 0
+#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT)
+#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT 16
+#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT)
+#define I40E_GLHMC_VFFSIAVBASE(_i) (0x000Cd600 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFFSIAVBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT 0
+#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT)
+#define I40E_GLHMC_VFFSIAVCNT(_i) (0x000Cd700 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFFSIAVCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT 0
+#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT)
+#define I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT 29
+#define I40E_GLHMC_VFFSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT)
+#define I40E_GLHMC_VFPDINV(_i) (0x000C8300 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPDINV_MAX_INDEX 31
+#define I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT 0
+#define I40E_GLHMC_VFPDINV_PMSDIDX_MASK (0xFFF << I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT)
+#define I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT 16
+#define I40E_GLHMC_VFPDINV_PMPDIDX_MASK (0x1FF << I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT)
+#define I40E_GLHMC_VFPEARPBASE(_i) (0x000Cc800 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEARPBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT 0
+#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT)
+#define I40E_GLHMC_VFPEARPCNT(_i) (0x000Cc900 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEARPCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT 0
+#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT)
+#define I40E_GLHMC_VFPECQBASE(_i) (0x000Cc200 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPECQBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT 0
+#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT)
+#define I40E_GLHMC_VFPECQCNT(_i) (0x000Cc300 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPECQCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT 0
+#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT)
+#define I40E_GLHMC_VFPEHTCNT(_i) (0x000Cc700 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEHTCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT 0
+#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT)
+#define I40E_GLHMC_VFPEHTEBASE(_i) (0x000Cc600 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEHTEBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT 0
+#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT)
+#define I40E_GLHMC_VFPEMRBASE(_i) (0x000Ccc00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEMRBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT 0
+#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT)
+#define I40E_GLHMC_VFPEMRCNT(_i) (0x000Ccd00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEMRCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT 0
+#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT)
+#define I40E_GLHMC_VFPEPBLBASE(_i) (0x000Cd800 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEPBLBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT 0
+#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT)
+#define I40E_GLHMC_VFPEPBLCNT(_i) (0x000Cd900 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEPBLCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT 0
+#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT)
+#define I40E_GLHMC_VFPEQ1BASE(_i) (0x000Cd200 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEQ1BASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT 0
+#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT)
+#define I40E_GLHMC_VFPEQ1CNT(_i) (0x000Cd300 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEQ1CNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT 0
+#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT)
+#define I40E_GLHMC_VFPEQ1FLBASE(_i) (0x000Cd400 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEQ1FLBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
+#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
+#define I40E_GLHMC_VFPEQ1FLCNT(_i) (0x000Cd500 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEQ1FLCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
+#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
+#define I40E_GLHMC_VFPEQPBASE(_i) (0x000Cc000 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEQPBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT 0
+#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT)
+#define I40E_GLHMC_VFPEQPCNT(_i) (0x000Cc100 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEQPCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT 0
+#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT)
+#define I40E_GLHMC_VFPESRQBASE(_i) (0x000Cc400 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPESRQBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT 0
+#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT)
+#define I40E_GLHMC_VFPESRQCNT(_i) (0x000Cc500 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPESRQCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT 0
+#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT)
+#define I40E_GLHMC_VFPETIMERBASE(_i) (0x000CDA00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPETIMERBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT 0
+#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT)
+#define I40E_GLHMC_VFPETIMERCNT(_i) (0x000CDB00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPETIMERCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT 0
+#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT)
+#define I40E_GLHMC_VFPEXFBASE(_i) (0x000Cce00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEXFBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT 0
+#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT)
+#define I40E_GLHMC_VFPEXFCNT(_i) (0x000Ccf00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEXFCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT 0
+#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT)
+#define I40E_GLHMC_VFPEXFFLBASE(_i) (0x000Cd000 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEXFFLBASE_MAX_INDEX 31
+#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
+#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT)
+#define I40E_GLHMC_VFPEXFFLCNT(_i) (0x000Cd100 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFPEXFFLCNT_MAX_INDEX 31
+#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
+#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT)
+#define I40E_GLHMC_VFSDPART(_i) (0x000C8800 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLHMC_VFSDPART_MAX_INDEX 31
+#define I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT 0
+#define I40E_GLHMC_VFSDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT)
+#define I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT 16
+#define I40E_GLHMC_VFSDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT)
+#define I40E_PFHMC_ERRORDATA 0x000C0500
+#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT 0
+#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK (0x3FFFFFFF << I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT)
+#define I40E_PFHMC_ERRORINFO 0x000C0400
+#define I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT 0
+#define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK (0x1F << I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT)
+#define I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT 7
+#define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK (0x1 << I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT 8
+#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK (0xF << I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT 16
+#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK (0x1F << I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT 31
+#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK (0x1 << I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT)
+#define I40E_PFHMC_PDINV 0x000C0300
+#define I40E_PFHMC_PDINV_PMSDIDX_SHIFT 0
+#define I40E_PFHMC_PDINV_PMSDIDX_MASK (0xFFF << I40E_PFHMC_PDINV_PMSDIDX_SHIFT)
+#define I40E_PFHMC_PDINV_PMPDIDX_SHIFT 16
+#define I40E_PFHMC_PDINV_PMPDIDX_MASK (0x1FF << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD 0x000C0000
+#define I40E_PFHMC_SDCMD_PMSDIDX_SHIFT 0
+#define I40E_PFHMC_SDCMD_PMSDIDX_MASK (0xFFF << I40E_PFHMC_SDCMD_PMSDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD_PMSDWR_SHIFT 31
+#define I40E_PFHMC_SDCMD_PMSDWR_MASK (0x1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT)
+#define I40E_PFHMC_SDDATAHIGH 0x000C0200
+#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT 0
+#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK (0xFFFFFFFF << I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT)
+#define I40E_PFHMC_SDDATALOW 0x000C0100
+#define I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT 0
+#define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT 1
+#define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT 2
+#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK (0x3FF << I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT 12
+#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK (0xFFFFF << I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT)
+#define I40E_GL_UFUSE 0x00094008
+#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT 1
+#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK (0x1 << I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT)
+#define I40E_GL_UFUSE_NIC_ID_SHIFT 2
+#define I40E_GL_UFUSE_NIC_ID_MASK (0x1 << I40E_GL_UFUSE_NIC_ID_SHIFT)
+#define I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT 10
+#define I40E_GL_UFUSE_ULT_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT)
+#define I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT 11
+#define I40E_GL_UFUSE_CLS_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT)
+#define I40E_EMPINT_GPIO_ENA 0x00088188
+#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
+#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
+#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
+#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
+#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
+#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
+#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
+#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
+#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
+#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
+#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
+#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
+#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
+#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
+#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
+#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
+#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
+#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
+#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
+#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
+#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
+#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
+#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
+#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
+#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
+#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
+#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
+#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
+#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
+#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
+#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM 0x0003F100
+#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT 0
+#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT 4
+#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK (0x1 << I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL 0x00038700
+#define I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT 0
+#define I40E_PFINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_ITR_INDX_SHIFT 11
+#define I40E_PFINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT 13
+#define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT 30
+#define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL_INTEVENT_SHIFT 31
+#define I40E_PFINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_CEQCTL_MAX_INDEX 511
+#define I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT 0
+#define I40E_PFINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_ITR_INDX_SHIFT 11
+#define I40E_PFINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT 13
+#define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT 16
+#define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
+#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT 30
+#define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_CEQCTL_INTEVENT_SHIFT 31
+#define I40E_PFINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_DYN_CTL0 0x00038480
+#define I40E_PFINT_DYN_CTL0_INTENA_SHIFT 0
+#define I40E_PFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT 1
+#define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
+#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT 3
+#define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT 5
+#define I40E_PFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
+#define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_DYN_CTLN_MAX_INDEX 511
+#define I40E_PFINT_DYN_CTLN_INTENA_SHIFT 0
+#define I40E_PFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT 1
+#define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
+#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT 3
+#define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT 5
+#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
+#define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_PFINT_GPIO_ENA 0x00088080
+#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
+#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
+#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
+#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
+#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
+#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
+#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
+#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
+#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
+#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
+#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
+#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
+#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
+#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
+#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
+#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
+#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
+#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
+#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
+#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
+#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
+#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
+#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
+#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
+#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
+#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
+#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
+#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
+#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
+#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
+#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFINT_ICR0 0x00038780
+#define I40E_PFINT_ICR0_INTEVENT_SHIFT 0
+#define I40E_PFINT_ICR0_INTEVENT_MASK (0x1 << I40E_PFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_0_SHIFT 1
+#define I40E_PFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_1_SHIFT 2
+#define I40E_PFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_2_SHIFT 3
+#define I40E_PFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_3_SHIFT 4
+#define I40E_PFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_4_SHIFT 5
+#define I40E_PFINT_ICR0_QUEUE_4_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_4_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_5_SHIFT 6
+#define I40E_PFINT_ICR0_QUEUE_5_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_5_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_6_SHIFT 7
+#define I40E_PFINT_ICR0_QUEUE_6_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_6_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_7_SHIFT 8
+#define I40E_PFINT_ICR0_QUEUE_7_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_7_SHIFT)
+#define I40E_PFINT_ICR0_ECC_ERR_SHIFT 16
+#define I40E_PFINT_ICR0_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_MAL_DETECT_SHIFT 19
+#define I40E_PFINT_ICR0_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_GRST_SHIFT 20
+#define I40E_PFINT_ICR0_GRST_MASK (0x1 << I40E_PFINT_ICR0_GRST_SHIFT)
+#define I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT 21
+#define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_GPIO_SHIFT 22
+#define I40E_PFINT_ICR0_GPIO_MASK (0x1 << I40E_PFINT_ICR0_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_TIMESYNC_SHIFT 23
+#define I40E_PFINT_ICR0_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_STORM_DETECT_MASK (0x1 << I40E_PFINT_ICR0_STORM_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
+#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_HMC_ERR_SHIFT 26
+#define I40E_PFINT_ICR0_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_PE_CRITERR_SHIFT 28
+#define I40E_PFINT_ICR0_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_VFLR_SHIFT 29
+#define I40E_PFINT_ICR0_VFLR_MASK (0x1 << I40E_PFINT_ICR0_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_ADMINQ_SHIFT 30
+#define I40E_PFINT_ICR0_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_SWINT_SHIFT 31
+#define I40E_PFINT_ICR0_SWINT_MASK (0x1 << I40E_PFINT_ICR0_SWINT_SHIFT)
+#define I40E_PFINT_ICR0_ENA 0x00038800
+#define I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT 16
+#define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT 19
+#define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GRST_SHIFT 20
+#define I40E_PFINT_ICR0_ENA_GRST_MASK (0x1 << I40E_PFINT_ICR0_ENA_GRST_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT 21
+#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GPIO_SHIFT 22
+#define I40E_PFINT_ICR0_ENA_GPIO_MASK (0x1 << I40E_PFINT_ICR0_ENA_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT 23
+#define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK (0x1 << I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
+#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT 26
+#define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT 28
+#define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_VFLR_SHIFT 29
+#define I40E_PFINT_ICR0_ENA_VFLR_MASK (0x1 << I40E_PFINT_ICR0_ENA_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT 30
+#define I40E_PFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_ENA_RSVD_SHIFT 31
+#define I40E_PFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_PFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */
+#define I40E_PFINT_ITR0_MAX_INDEX 2
+#define I40E_PFINT_ITR0_INTERVAL_SHIFT 0
+#define I40E_PFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_PFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4))
+#define I40E_PFINT_ITRN_MAX_INDEX 2
+#define I40E_PFINT_ITRN_INTERVAL_SHIFT 0
+#define I40E_PFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_PFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_PFINT_LNKLST0 0x00038500
+#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
+#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
+#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_LNKLSTN_MAX_INDEX 511
+#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
+#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
+#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_RATE0 0x00038580
+#define I40E_PFINT_RATE0_INTERVAL_SHIFT 0
+#define I40E_PFINT_RATE0_INTERVAL_MASK (0x3F << I40E_PFINT_RATE0_INTERVAL_SHIFT)
+#define I40E_PFINT_RATE0_INTRL_ENA_SHIFT 6
+#define I40E_PFINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_RATEN_MAX_INDEX 511
+#define I40E_PFINT_RATEN_INTERVAL_SHIFT 0
+#define I40E_PFINT_RATEN_INTERVAL_MASK (0x3F << I40E_PFINT_RATEN_INTERVAL_SHIFT)
+#define I40E_PFINT_RATEN_INTRL_ENA_SHIFT 6
+#define I40E_PFINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_PFINT_STAT_CTL0 0x00038400
+#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
+#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QINT_RQCTL_MAX_INDEX 1535
+#define I40E_QINT_RQCTL_MSIX_INDX_SHIFT 0
+#define I40E_QINT_RQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_RQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_RQCTL_ITR_INDX_SHIFT 11
+#define I40E_QINT_RQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_RQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL_MSIX0_INDX_SHIFT 13
+#define I40E_QINT_RQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_RQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT 16
+#define I40E_QINT_RQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT 27
+#define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_RQCTL_CAUSE_ENA_SHIFT 30
+#define I40E_QINT_RQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_RQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_RQCTL_INTEVENT_SHIFT 31
+#define I40E_QINT_RQCTL_INTEVENT_MASK (0x1 << I40E_QINT_RQCTL_INTEVENT_SHIFT)
+#define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QINT_TQCTL_MAX_INDEX 1535
+#define I40E_QINT_TQCTL_MSIX_INDX_SHIFT 0
+#define I40E_QINT_TQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_TQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_TQCTL_ITR_INDX_SHIFT 11
+#define I40E_QINT_TQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_TQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_TQCTL_MSIX0_INDX_SHIFT 13
+#define I40E_QINT_TQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_TQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT 16
+#define I40E_QINT_TQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT 27
+#define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_TQCTL_CAUSE_ENA_SHIFT 30
+#define I40E_QINT_TQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_TQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_TQCTL_INTEVENT_SHIFT 31
+#define I40E_QINT_TQCTL_INTEVENT_MASK (0x1 << I40E_QINT_TQCTL_INTEVENT_SHIFT)
+#define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_DYN_CTL0_MAX_INDEX 127
+#define I40E_VFINT_DYN_CTL0_INTENA_SHIFT 0
+#define I40E_VFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT 1
+#define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
+#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT 3
+#define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT 5
+#define I40E_VFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
+#define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VFINT_DYN_CTLN_MAX_INDEX 511
+#define I40E_VFINT_DYN_CTLN_INTENA_SHIFT 0
+#define I40E_VFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT 1
+#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
+#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT 3
+#define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT 5
+#define I40E_VFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
+#define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ICR0_MAX_INDEX 127
+#define I40E_VFINT_ICR0_INTEVENT_SHIFT 0
+#define I40E_VFINT_ICR0_INTEVENT_MASK (0x1 << I40E_VFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_0_SHIFT 1
+#define I40E_VFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_1_SHIFT 2
+#define I40E_VFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_2_SHIFT 3
+#define I40E_VFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_3_SHIFT 4
+#define I40E_VFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
+#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ADMINQ_SHIFT 30
+#define I40E_VFINT_ICR0_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_SWINT_SHIFT 31
+#define I40E_VFINT_ICR0_SWINT_MASK (0x1 << I40E_VFINT_ICR0_SWINT_SHIFT)
+#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ICR0_ENA_MAX_INDEX 127
+#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
+#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT 30
+#define I40E_VFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA_RSVD_SHIFT 31
+#define I40E_VFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */
+#define I40E_VFINT_ITR0_MAX_INDEX 2
+#define I40E_VFINT_ITR0_INTERVAL_SHIFT 0
+#define I40E_VFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4))
+#define I40E_VFINT_ITRN_MAX_INDEX 2
+#define I40E_VFINT_ITRN_INTERVAL_SHIFT 0
+#define I40E_VFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_STAT_CTL0_MAX_INDEX 127
+#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
+#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_AEQCTL_MAX_INDEX 127
+#define I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT 0
+#define I40E_VPINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_ITR_INDX_SHIFT 11
+#define I40E_VPINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT 13
+#define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT 30
+#define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_AEQCTL_INTEVENT_SHIFT 31
+#define I40E_VPINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_CEQCTL_MAX_INDEX 511
+#define I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT 0
+#define I40E_VPINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_ITR_INDX_SHIFT 11
+#define I40E_VPINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT 13
+#define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT 16
+#define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
+#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT 30
+#define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_CEQCTL_INTEVENT_SHIFT 31
+#define I40E_VPINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_LNKLST0_MAX_INDEX 127
+#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
+#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
+#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_LNKLSTN_MAX_INDEX 511
+#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
+#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
+#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_RATE0_MAX_INDEX 127
+#define I40E_VPINT_RATE0_INTERVAL_SHIFT 0
+#define I40E_VPINT_RATE0_INTERVAL_MASK (0x3F << I40E_VPINT_RATE0_INTERVAL_SHIFT)
+#define I40E_VPINT_RATE0_INTRL_ENA_SHIFT 6
+#define I40E_VPINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_RATEN_MAX_INDEX 511
+#define I40E_VPINT_RATEN_INTERVAL_SHIFT 0
+#define I40E_VPINT_RATEN_INTERVAL_MASK (0x3F << I40E_VPINT_RATEN_INTERVAL_SHIFT)
+#define I40E_VPINT_RATEN_INTRL_ENA_SHIFT 6
+#define I40E_VPINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_GL_RDPU_CNTRL 0x00051060
+#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT 0
+#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK (0x1 << I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT)
+#define I40E_GL_RDPU_CNTRL_ECO_SHIFT 1
+#define I40E_GL_RDPU_CNTRL_ECO_MASK (0x7FFFFFFF << I40E_GL_RDPU_CNTRL_ECO_SHIFT)
+#define I40E_GLLAN_RCTL_0 0x0012A500
+#define I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT 0
+#define I40E_GLLAN_RCTL_0_PXE_MODE_MASK (0x1 << I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT)
+#define I40E_GLLAN_TSOMSK_F 0x000442D8
+#define I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT 0
+#define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK (0xFFF << I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT)
+#define I40E_GLLAN_TSOMSK_L 0x000442E0
+#define I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT 0
+#define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK (0xFFF << I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT)
+#define I40E_GLLAN_TSOMSK_M 0x000442DC
+#define I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT 0
+#define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK (0xFFF << I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT)
+#define I40E_PFLAN_QALLOC 0x001C0400
+#define I40E_PFLAN_QALLOC_FIRSTQ_SHIFT 0
+#define I40E_PFLAN_QALLOC_FIRSTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_FIRSTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_LASTQ_SHIFT 16
+#define I40E_PFLAN_QALLOC_LASTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_LASTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_VALID_SHIFT 31
+#define I40E_PFLAN_QALLOC_VALID_MASK (0x1 << I40E_PFLAN_QALLOC_VALID_SHIFT)
+#define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_ENA_MAX_INDEX 1535
+#define I40E_QRX_ENA_QENA_REQ_SHIFT 0
+#define I40E_QRX_ENA_QENA_REQ_MASK (0x1 << I40E_QRX_ENA_QENA_REQ_SHIFT)
+#define I40E_QRX_ENA_FAST_QDIS_SHIFT 1
+#define I40E_QRX_ENA_FAST_QDIS_MASK (0x1 << I40E_QRX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QRX_ENA_QENA_STAT_SHIFT 2
+#define I40E_QRX_ENA_QENA_STAT_MASK (0x1 << I40E_QRX_ENA_QENA_STAT_SHIFT)
+#define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_TAIL_MAX_INDEX 1535
+#define I40E_QRX_TAIL_TAIL_SHIFT 0
+#define I40E_QRX_TAIL_TAIL_MASK (0x1FFF << I40E_QRX_TAIL_TAIL_SHIFT)
+#define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_CTL_MAX_INDEX 1535
+#define I40E_QTX_CTL_PFVF_Q_SHIFT 0
+#define I40E_QTX_CTL_PFVF_Q_MASK (0x3 << I40E_QTX_CTL_PFVF_Q_SHIFT)
+#define I40E_QTX_CTL_PF_INDX_SHIFT 2
+#define I40E_QTX_CTL_PF_INDX_MASK (0xF << I40E_QTX_CTL_PF_INDX_SHIFT)
+#define I40E_QTX_CTL_VFVM_INDX_SHIFT 7
+#define I40E_QTX_CTL_VFVM_INDX_MASK (0x1FF << I40E_QTX_CTL_VFVM_INDX_SHIFT)
+#define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_ENA_MAX_INDEX 1535
+#define I40E_QTX_ENA_QENA_REQ_SHIFT 0
+#define I40E_QTX_ENA_QENA_REQ_MASK (0x1 << I40E_QTX_ENA_QENA_REQ_SHIFT)
+#define I40E_QTX_ENA_FAST_QDIS_SHIFT 1
+#define I40E_QTX_ENA_FAST_QDIS_MASK (0x1 << I40E_QTX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QTX_ENA_QENA_STAT_SHIFT 2
+#define I40E_QTX_ENA_QENA_STAT_MASK (0x1 << I40E_QTX_ENA_QENA_STAT_SHIFT)
+#define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_HEAD_MAX_INDEX 1535
+#define I40E_QTX_HEAD_HEAD_SHIFT 0
+#define I40E_QTX_HEAD_HEAD_MASK (0x1FFF << I40E_QTX_HEAD_HEAD_SHIFT)
+#define I40E_QTX_HEAD_RS_PENDING_SHIFT 16
+#define I40E_QTX_HEAD_RS_PENDING_MASK (0x1 << I40E_QTX_HEAD_RS_PENDING_SHIFT)
+#define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_TAIL_MAX_INDEX 1535
+#define I40E_QTX_TAIL_TAIL_SHIFT 0
+#define I40E_QTX_TAIL_TAIL_MASK (0x1FFF << I40E_QTX_TAIL_TAIL_SHIFT)
+#define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPLAN_MAPENA_MAX_INDEX 127
+#define I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT 0
+#define I40E_VPLAN_MAPENA_TXRX_ENA_MASK (0x1 << I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT)
+#define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VPLAN_QTABLE_MAX_INDEX 15
+#define I40E_VPLAN_QTABLE_QINDEX_SHIFT 0
+#define I40E_VPLAN_QTABLE_QINDEX_MASK (0x7FF << I40E_VPLAN_QTABLE_QINDEX_SHIFT)
+#define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VSILAN_QBASE_MAX_INDEX 383
+#define I40E_VSILAN_QBASE_VSIBASE_SHIFT 0
+#define I40E_VSILAN_QBASE_VSIBASE_MASK (0x7FF << I40E_VSILAN_QBASE_VSIBASE_SHIFT)
+#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT 11
+#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK (0x1 << I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
+#define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSILAN_QTABLE_MAX_INDEX 7
+#define I40E_VSILAN_QTABLE_QINDEX_0_SHIFT 0
+#define I40E_VSILAN_QTABLE_QINDEX_0_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
+#define I40E_VSILAN_QTABLE_QINDEX_1_SHIFT 16
+#define I40E_VSILAN_QTABLE_QINDEX_1_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_1_SHIFT)
+#define I40E_PRTGL_SAH 0x001E2140
+#define I40E_PRTGL_SAH_FC_SAH_SHIFT 0
+#define I40E_PRTGL_SAH_FC_SAH_MASK (0xFFFF << I40E_PRTGL_SAH_FC_SAH_SHIFT)
+#define I40E_PRTGL_SAH_MFS_SHIFT 16
+#define I40E_PRTGL_SAH_MFS_MASK (0xFFFF << I40E_PRTGL_SAH_MFS_SHIFT)
+#define I40E_PRTGL_SAL 0x001E2120
+#define I40E_PRTGL_SAL_FC_SAL_SHIFT 0
+#define I40E_PRTGL_SAL_FC_SAL_MASK (0xFFFFFFFF << I40E_PRTGL_SAL_FC_SAL_SHIFT)
+#define I40E_PRTMAC_HLCTLA 0x001E4760
+#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT 0
+#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT)
+#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT 1
+#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_MASK (0x1 << I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT)
+#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT 2
+#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT)
+#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT 4
+#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT)
+#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT 7
+#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP 0x001E3130
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP 0x001E3290
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP 0x001E3310
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP 0x001E3100
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP 0x001E3280
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP 0x001E3300
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE 0x001E3000
+#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX 8
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX 8
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT 0
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT)
+#define I40E_PRTMAC_HSECTL1 0x001E3560
+#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT 0
+#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT)
+#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT 3
+#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT)
+#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT 4
+#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT)
+#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT 7
+#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT)
+#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT 30
+#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT)
+#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT 31
+#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT 0
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT 2
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT 4
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT 6
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT 8
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT 10
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT 12
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT 14
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT 0
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT 2
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT 4
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT 6
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT 8
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT 10
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT 12
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT 14
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
+#define I40E_GL_MNG_FWSM 0x000B6134
+#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 1
+#define I40E_GL_MNG_FWSM_FW_MODES_MASK (0x7 << I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 6
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK (0x1 << I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
+#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT 11
+#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK (0xF << I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
+#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT 15
+#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK (0x1 << I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
+#define I40E_GL_MNG_FWSM_RESET_CNT_SHIFT 16
+#define I40E_GL_MNG_FWSM_RESET_CNT_MASK (0x7 << I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
+#define I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT 19
+#define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK (0x3F << I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
+#define I40E_GL_MNG_FWSM_RSVD_SHIFT 25
+#define I40E_GL_MNG_FWSM_RSVD_MASK (0x1 << I40E_GL_MNG_FWSM_RSVD_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT 26
+#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT 27
+#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT 28
+#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT 29
+#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_HWARB_CTRL 0x000B6130
+#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT 0
+#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK (0x1 << I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT)
+#define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */
+#define I40E_PRT_MNG_FTFT_DATA_MAX_INDEX 31
+#define I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT 0
+#define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK (0xFFFFFFFF << I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT)
+#define I40E_PRT_MNG_FTFT_LENGTH 0x00085260
+#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT 0
+#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK (0xFF << I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_FTFT_MASK_MAX_INDEX 7
+#define I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT 0
+#define I40E_PRT_MNG_FTFT_MASK_MASK_MASK (0xFFFF << I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT)
+#define I40E_PRT_MNG_MANC 0x00256A20
+#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT 0
+#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT 1
+#define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT 17
+#define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_ALL_SHIFT 19
+#define I40E_PRT_MNG_MANC_RCV_ALL_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_ALL_SHIFT)
+#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT 25
+#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_NET_TYPE_SHIFT 26
+#define I40E_PRT_MNG_MANC_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT 28
+#define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT)
+#define I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT 29
+#define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT)
+#define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_MAVTV_MAX_INDEX 7
+#define I40E_PRT_MNG_MAVTV_VID_SHIFT 0
+#define I40E_PRT_MNG_MAVTV_VID_MASK (0xFFF << I40E_PRT_MNG_MAVTV_VID_SHIFT)
+#define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32))
+#define I40E_PRT_MNG_MDEF_MAX_INDEX 7
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT 0
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT 4
+#define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT 5
+#define I40E_PRT_MNG_MDEF_VLAN_AND_MASK (0xFF << I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT 13
+#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT 17
+#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT 21
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT 25
+#define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT 26
+#define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT 27
+#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT 28
+#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT 29
+#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT 30
+#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT 31
+#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32))
+#define I40E_PRT_MNG_MDEF_EXT_MAX_INDEX 7
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT 0
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT 4
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT 8
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK (0xFFFF << I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT 24
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT 25
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT 26
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT 27
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT 28
+#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT 29
+#define I40E_PRT_MNG_MDEF_EXT_MLD_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT 30
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT 31
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MDEFVSI_MAX_INDEX 3
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT 0
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT 16
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT)
+#define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_METF_MAX_INDEX 3
+#define I40E_PRT_MNG_METF_ETYPE_SHIFT 0
+#define I40E_PRT_MNG_METF_ETYPE_MASK (0xFFFF << I40E_PRT_MNG_METF_ETYPE_SHIFT)
+#define I40E_PRT_MNG_METF_POLARITY_SHIFT 30
+#define I40E_PRT_MNG_METF_POLARITY_MASK (0x1 << I40E_PRT_MNG_METF_POLARITY_SHIFT)
+#define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_MFUTP_MAX_INDEX 15
+#define I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT 0
+#define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK (0xFFFF << I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT)
+#define I40E_PRT_MNG_MFUTP_UDP_SHIFT 16
+#define I40E_PRT_MNG_MFUTP_UDP_MASK (0x1 << I40E_PRT_MNG_MFUTP_UDP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_TCP_SHIFT 17
+#define I40E_PRT_MNG_MFUTP_TCP_MASK (0x1 << I40E_PRT_MNG_MFUTP_TCP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT 18
+#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK (0x1 << I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT)
+#define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MIPAF4_MAX_INDEX 3
+#define I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT 0
+#define I40E_PRT_MNG_MIPAF4_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_MIPAF6_MAX_INDEX 15
+#define I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT 0
+#define I40E_PRT_MNG_MIPAF6_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MMAH_MAX_INDEX 3
+#define I40E_PRT_MNG_MMAH_MMAH_SHIFT 0
+#define I40E_PRT_MNG_MMAH_MMAH_MASK (0xFFFF << I40E_PRT_MNG_MMAH_MMAH_SHIFT)
+#define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MMAL_MAX_INDEX 3
+#define I40E_PRT_MNG_MMAL_MMAL_SHIFT 0
+#define I40E_PRT_MNG_MMAL_MMAL_MASK (0xFFFFFFFF << I40E_PRT_MNG_MMAL_MMAL_SHIFT)
+#define I40E_PRT_MNG_MNGONLY 0x00256A60
+#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT 0
+#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK (0xFF << I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT)
+#define I40E_PRT_MNG_MSFM 0x00256AA0
+#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT 0
+#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT 1
+#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT 2
+#define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT 3
+#define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT 4
+#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT 5
+#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT 6
+#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT 7
+#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT)
+#define I40E_MSIX_PBA(_i) (0x00004900 + ((_i) * 4)) /* _i=0...5 */
+#define I40E_MSIX_PBA_MAX_INDEX 5
+#define I40E_MSIX_PBA_PENBIT_SHIFT 0
+#define I40E_MSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_MSIX_PBA_PENBIT_SHIFT)
+#define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TADD_MAX_INDEX 128
+#define I40E_MSIX_TADD_MSIXTADD10_SHIFT 0
+#define I40E_MSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_MSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_MSIX_TADD_MSIXTADD_SHIFT 2
+#define I40E_MSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_MSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TMSG_MAX_INDEX 128
+#define I40E_MSIX_TMSG_MSIXTMSG_SHIFT 0
+#define I40E_MSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_MSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TUADD_MAX_INDEX 128
+#define I40E_MSIX_TUADD_MSIXTUADD_SHIFT 0
+#define I40E_MSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_MSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TVCTRL_MAX_INDEX 128
+#define I40E_MSIX_TVCTRL_MASK_SHIFT 0
+#define I40E_MSIX_TVCTRL_MASK_MASK (0x1 << I40E_MSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFMSIX_PBA1(_i) (0x00004944 + ((_i) * 4)) /* _i=0...19 */
+#define I40E_VFMSIX_PBA1_MAX_INDEX 19
+#define I40E_VFMSIX_PBA1_PENBIT_SHIFT 0
+#define I40E_VFMSIX_PBA1_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA1_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TADD1_MAX_INDEX 639
+#define I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT 0
+#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD1_MSIXTADD_SHIFT 2
+#define I40E_VFMSIX_TADD1_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TMSG1_MAX_INDEX 639
+#define I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT 0
+#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TUADD1_MAX_INDEX 639
+#define I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT 0
+#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TVCTRL1_MAX_INDEX 639
+#define I40E_VFMSIX_TVCTRL1_MASK_SHIFT 0
+#define I40E_VFMSIX_TVCTRL1_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
+#define I40E_GLNVM_FLA 0x000B6108
+#define I40E_GLNVM_FLA_FL_SCK_SHIFT 0
+#define I40E_GLNVM_FLA_FL_SCK_MASK (0x1 << I40E_GLNVM_FLA_FL_SCK_SHIFT)
+#define I40E_GLNVM_FLA_FL_CE_SHIFT 1
+#define I40E_GLNVM_FLA_FL_CE_MASK (0x1 << I40E_GLNVM_FLA_FL_CE_SHIFT)
+#define I40E_GLNVM_FLA_FL_SI_SHIFT 2
+#define I40E_GLNVM_FLA_FL_SI_MASK (0x1 << I40E_GLNVM_FLA_FL_SI_SHIFT)
+#define I40E_GLNVM_FLA_FL_SO_SHIFT 3
+#define I40E_GLNVM_FLA_FL_SO_MASK (0x1 << I40E_GLNVM_FLA_FL_SO_SHIFT)
+#define I40E_GLNVM_FLA_FL_REQ_SHIFT 4
+#define I40E_GLNVM_FLA_FL_REQ_MASK (0x1 << I40E_GLNVM_FLA_FL_REQ_SHIFT)
+#define I40E_GLNVM_FLA_FL_GNT_SHIFT 5
+#define I40E_GLNVM_FLA_FL_GNT_MASK (0x1 << I40E_GLNVM_FLA_FL_GNT_SHIFT)
+#define I40E_GLNVM_FLA_LOCKED_SHIFT 6
+#define I40E_GLNVM_FLA_LOCKED_MASK (0x1 << I40E_GLNVM_FLA_LOCKED_SHIFT)
+#define I40E_GLNVM_FLA_FL_SADDR_SHIFT 18
+#define I40E_GLNVM_FLA_FL_SADDR_MASK (0x7FF << I40E_GLNVM_FLA_FL_SADDR_SHIFT)
+#define I40E_GLNVM_FLA_FL_BUSY_SHIFT 30
+#define I40E_GLNVM_FLA_FL_BUSY_MASK (0x1 << I40E_GLNVM_FLA_FL_BUSY_SHIFT)
+#define I40E_GLNVM_FLA_FL_DER_SHIFT 31
+#define I40E_GLNVM_FLA_FL_DER_MASK (0x1 << I40E_GLNVM_FLA_FL_DER_SHIFT)
+#define I40E_GLNVM_FLASHID 0x000B6104
+#define I40E_GLNVM_FLASHID_FLASHID_SHIFT 0
+#define I40E_GLNVM_FLASHID_FLASHID_MASK (0xFFFFFF << I40E_GLNVM_FLASHID_FLASHID_SHIFT)
+#define I40E_GLNVM_GENS 0x000B6100
+#define I40E_GLNVM_GENS_NVM_PRES_SHIFT 0
+#define I40E_GLNVM_GENS_NVM_PRES_MASK (0x1 << I40E_GLNVM_GENS_NVM_PRES_SHIFT)
+#define I40E_GLNVM_GENS_SR_SIZE_SHIFT 5
+#define I40E_GLNVM_GENS_SR_SIZE_MASK (0x7 << I40E_GLNVM_GENS_SR_SIZE_SHIFT)
+#define I40E_GLNVM_GENS_BANK1VAL_SHIFT 8
+#define I40E_GLNVM_GENS_BANK1VAL_MASK (0x1 << I40E_GLNVM_GENS_BANK1VAL_SHIFT)
+#define I40E_GLNVM_GENS_ALT_PRST_SHIFT 23
+#define I40E_GLNVM_GENS_ALT_PRST_MASK (0x1 << I40E_GLNVM_GENS_ALT_PRST_SHIFT)
+#define I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT 25
+#define I40E_GLNVM_GENS_FL_AUTO_RD_MASK (0x1 << I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT)
+#define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */
+#define I40E_GLNVM_PROTCSR_MAX_INDEX 59
+#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT 0
+#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK (0xFFFFFF << I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT)
+#define I40E_GLNVM_SRCTL 0x000B6110
+#define I40E_GLNVM_SRCTL_SRBUSY_SHIFT 0
+#define I40E_GLNVM_SRCTL_SRBUSY_MASK (0x1 << I40E_GLNVM_SRCTL_SRBUSY_SHIFT)
+#define I40E_GLNVM_SRCTL_ADDR_SHIFT 14
+#define I40E_GLNVM_SRCTL_ADDR_MASK (0x7FFF << I40E_GLNVM_SRCTL_ADDR_SHIFT)
+#define I40E_GLNVM_SRCTL_WRITE_SHIFT 29
+#define I40E_GLNVM_SRCTL_WRITE_MASK (0x1 << I40E_GLNVM_SRCTL_WRITE_SHIFT)
+#define I40E_GLNVM_SRCTL_START_SHIFT 30
+#define I40E_GLNVM_SRCTL_START_MASK (0x1 << I40E_GLNVM_SRCTL_START_SHIFT)
+#define I40E_GLNVM_SRCTL_DONE_SHIFT 31
+#define I40E_GLNVM_SRCTL_DONE_MASK (0x1 << I40E_GLNVM_SRCTL_DONE_SHIFT)
+#define I40E_GLNVM_SRDATA 0x000B6114
+#define I40E_GLNVM_SRDATA_WRDATA_SHIFT 0
+#define I40E_GLNVM_SRDATA_WRDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_WRDATA_SHIFT)
+#define I40E_GLNVM_SRDATA_RDDATA_SHIFT 16
+#define I40E_GLNVM_SRDATA_RDDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_RDDATA_SHIFT)
+#define I40E_GLNVM_ULD 0x000B6008
+#define I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT 0
+#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT 1
+#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT 2
+#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT 3
+#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT 4
+#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT 5
+#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT 6
+#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT 7
+#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT 8
+#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT 9
+#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
+
+#define I40E_GLPCI_BYTCTH 0x0009C484
+#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT 0
+#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_BYTCTL 0x0009C488
+#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT 0
+#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_CAPCTRL 0x000BE4A4
+#define I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT 0
+#define I40E_GLPCI_CAPCTRL_VPD_EN_MASK (0x1 << I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP 0x000BE4A8
+#define I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT 0
+#define I40E_GLPCI_CAPSUP_PCIE_VER_MASK (0x1 << I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT)
+#define I40E_GLPCI_CAPSUP_LTR_EN_SHIFT 2
+#define I40E_GLPCI_CAPSUP_LTR_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_LTR_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_TPH_EN_SHIFT 3
+#define I40E_GLPCI_CAPSUP_TPH_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_TPH_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ARI_EN_SHIFT 4
+#define I40E_GLPCI_CAPSUP_ARI_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ARI_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IOV_EN_SHIFT 5
+#define I40E_GLPCI_CAPSUP_IOV_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IOV_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ACS_EN_SHIFT 6
+#define I40E_GLPCI_CAPSUP_ACS_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ACS_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_SEC_EN_SHIFT 7
+#define I40E_GLPCI_CAPSUP_SEC_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_SEC_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT 16
+#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT 17
+#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IDO_EN_SHIFT 18
+#define I40E_GLPCI_CAPSUP_IDO_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IDO_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT 19
+#define I40E_GLPCI_CAPSUP_MSI_MASK_MASK (0x1 << I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT)
+#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT 20
+#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT 30
+#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT)
+#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT 31
+#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT)
+#define I40E_GLPCI_CNF 0x000BE4C0
+#define I40E_GLPCI_CNF_FLEX10_SHIFT 1
+#define I40E_GLPCI_CNF_FLEX10_MASK (0x1 << I40E_GLPCI_CNF_FLEX10_SHIFT)
+#define I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT 2
+#define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK (0x1 << I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT)
+#define I40E_GLPCI_CNF2 0x000BE494
+#define I40E_GLPCI_CNF2_RO_DIS_SHIFT 0
+#define I40E_GLPCI_CNF2_RO_DIS_MASK (0x1 << I40E_GLPCI_CNF2_RO_DIS_SHIFT)
+#define I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT 1
+#define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK (0x1 << I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT)
+#define I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT 2
+#define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT)
+#define I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT 13
+#define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT)
+#define I40E_GLPCI_DREVID 0x0009C480
+#define I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT 0
+#define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK (0xFF << I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT)
+#define I40E_GLPCI_GSCL_1 0x0009C48C
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT 0
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT 1
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT 2
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT 3
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT 4
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT 5
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT 6
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT 7
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT 8
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT 9
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT 14
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT 15
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT 28
+#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT 29
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT 30
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT 31
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT)
+#define I40E_GLPCI_GSCL_2 0x0009C490
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT 0
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT 8
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT 16
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT 24
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT)
+#define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCL_5_8_MAX_INDEX 3
+#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT 0
+#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT)
+#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT 16
+#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT)
+#define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCN_0_3_MAX_INDEX 3
+#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT 0
+#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK (0xFFFFFFFF << I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT)
+#define I40E_GLPCI_LATCT 0x0009C4B4
+#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT 0
+#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_MASK (0xFFFFFFFF << I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT)
+#define I40E_GLPCI_LBARCTRL 0x000BE484
+#define I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT 0
+#define I40E_GLPCI_LBARCTRL_PREFBAR_MASK (0x1 << I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT)
+#define I40E_GLPCI_LBARCTRL_BAR32_SHIFT 1
+#define I40E_GLPCI_LBARCTRL_BAR32_MASK (0x1 << I40E_GLPCI_LBARCTRL_BAR32_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT 3
+#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK (0x1 << I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT 4
+#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_MASK (0x3 << I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT 6
+#define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT 10
+#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_MASK (0x1 << I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT 11
+#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT)
+#define I40E_GLPCI_LINKCAP 0x000BE4AC
+#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT 0
+#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK (0x3F << I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT)
+#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT 6
+#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK (0x7 << I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT)
+#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT 9
+#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK (0xF << I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT)
+#define I40E_GLPCI_PCIERR 0x000BE4FC
+#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT 0
+#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK (0xFFFFFFFF << I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
+#define I40E_GLPCI_PCITEST2 0x000BE4BC
+#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT 0
+#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_MASK (0x1 << I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT)
+#define I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT 1
+#define I40E_GLPCI_PCITEST2_TAG_ALLOC_MASK (0x1 << I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT)
+
+#define I40E_GLPCI_PKTCT 0x0009C4BC
+#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT 0
+#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK (0xFFFFFFFF << I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
+#define I40E_GLPCI_PMSUP 0x000BE4B0
+#define I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT 0
+#define I40E_GLPCI_PMSUP_ASPM_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT 2
+#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT 5
+#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT 8
+#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT 11
+#define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT 14
+#define I40E_GLPCI_PMSUP_SLOT_CLK_MASK (0x1 << I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT)
+#define I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT 15
+#define I40E_GLPCI_PMSUP_OBFF_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT)
+#define I40E_GLPCI_PWRDATA 0x000BE490
+#define I40E_GLPCI_PWRDATA_D0_POWER_SHIFT 0
+#define I40E_GLPCI_PWRDATA_D0_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D0_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT 8
+#define I40E_GLPCI_PWRDATA_COMM_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_D3_POWER_SHIFT 16
+#define I40E_GLPCI_PWRDATA_D3_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D3_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT 24
+#define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK (0x3 << I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT)
+#define I40E_GLPCI_REVID 0x000BE4B4
+#define I40E_GLPCI_REVID_NVM_REVID_SHIFT 0
+#define I40E_GLPCI_REVID_NVM_REVID_MASK (0xFF << I40E_GLPCI_REVID_NVM_REVID_SHIFT)
+#define I40E_GLPCI_SERH 0x000BE49C
+#define I40E_GLPCI_SERH_SER_NUM_H_SHIFT 0
+#define I40E_GLPCI_SERH_SER_NUM_H_MASK (0xFFFF << I40E_GLPCI_SERH_SER_NUM_H_SHIFT)
+#define I40E_GLPCI_SERL 0x000BE498
+#define I40E_GLPCI_SERL_SER_NUM_L_SHIFT 0
+#define I40E_GLPCI_SERL_SER_NUM_L_MASK (0xFFFFFFFF << I40E_GLPCI_SERL_SER_NUM_L_SHIFT)
+#define I40E_GLPCI_SUBSYSID 0x000BE48C
+#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT 0
+#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT)
+#define I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT 16
+#define I40E_GLPCI_SUBSYSID_SUB_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT)
+#define I40E_GLPCI_UPADD 0x000BE4F8
+#define I40E_GLPCI_UPADD_ADDRESS_SHIFT 1
+#define I40E_GLPCI_UPADD_ADDRESS_MASK (0x7FFFFFFF << I40E_GLPCI_UPADD_ADDRESS_SHIFT)
+#define I40E_GLPCI_VFSUP 0x000BE4B8
+#define I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT 0
+#define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK (0x1 << I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT)
+#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT 1
+#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK (0x1 << I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT)
+#define I40E_PF_FUNC_RID 0x0009C000
+#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT 0
+#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK (0x7 << I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT 3
+#define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK (0x1F << I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT 8
+#define I40E_PF_FUNC_RID_BUS_NUMBER_MASK (0xFF << I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT)
+#define I40E_PF_PCI_CIAA 0x0009C080
+#define I40E_PF_PCI_CIAA_ADDRESS_SHIFT 0
+#define I40E_PF_PCI_CIAA_ADDRESS_MASK (0xFFF << I40E_PF_PCI_CIAA_ADDRESS_SHIFT)
+#define I40E_PF_PCI_CIAA_VF_NUM_SHIFT 12
+#define I40E_PF_PCI_CIAA_VF_NUM_MASK (0x7F << I40E_PF_PCI_CIAA_VF_NUM_SHIFT)
+#define I40E_PF_PCI_CIAD 0x0009C100
+#define I40E_PF_PCI_CIAD_DATA_SHIFT 0
+#define I40E_PF_PCI_CIAD_DATA_MASK (0xFFFFFFFF << I40E_PF_PCI_CIAD_DATA_SHIFT)
+#define I40E_PFPCI_CLASS 0x000BE400
+#define I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT 0
+#define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK (0x1 << I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT)
+#define I40E_PFPCI_CNF 0x000BE000
+#define I40E_PFPCI_CNF_MSI_EN_SHIFT 2
+#define I40E_PFPCI_CNF_MSI_EN_MASK (0x1 << I40E_PFPCI_CNF_MSI_EN_SHIFT)
+#define I40E_PFPCI_CNF_EXROM_DIS_SHIFT 3
+#define I40E_PFPCI_CNF_EXROM_DIS_MASK (0x1 << I40E_PFPCI_CNF_EXROM_DIS_SHIFT)
+#define I40E_PFPCI_CNF_IO_BAR_SHIFT 4
+#define I40E_PFPCI_CNF_IO_BAR_MASK (0x1 << I40E_PFPCI_CNF_IO_BAR_SHIFT)
+#define I40E_PFPCI_CNF_INT_PIN_SHIFT 5
+#define I40E_PFPCI_CNF_INT_PIN_MASK (0x3 << I40E_PFPCI_CNF_INT_PIN_SHIFT)
+#define I40E_PFPCI_FACTPS 0x0009C180
+#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT 0
+#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK (0x3 << I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT)
+#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT 3
+#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK (0x1 << I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT)
+#define I40E_PFPCI_FUNC 0x000BE200
+#define I40E_PFPCI_FUNC_FUNC_DIS_SHIFT 0
+#define I40E_PFPCI_FUNC_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT 1
+#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT 2
+#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK (0x1 << I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT)
+#define I40E_PFPCI_FUNC2 0x000BE180
+#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT 0
+#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_ICAUSE 0x0009C200
+#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT 0
+#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK (0xFFFFFFFF << I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT)
+#define I40E_PFPCI_IENA 0x0009C280
+#define I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT 0
+#define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK (0xFFFFFFFF << I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT)
+#define I40E_PFPCI_PFDEVID 0x000BE080
+#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT 0
+#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT)
+#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT 16
+#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT)
+#define I40E_PFPCI_PM 0x000BE300
+#define I40E_PFPCI_PM_PME_EN_SHIFT 0
+#define I40E_PFPCI_PM_PME_EN_MASK (0x1 << I40E_PFPCI_PM_PME_EN_SHIFT)
+#define I40E_PFPCI_STATUS1 0x000BE280
+#define I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT 0
+#define I40E_PFPCI_STATUS1_FUNC_VALID_MASK (0x1 << I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT)
+#define I40E_PFPCI_VFDEVID 0x000BE100
+#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT 0
+#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT)
+#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT 16
+#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT)
+#define I40E_PFPCI_VMINDEX 0x0009C300
+#define I40E_PFPCI_VMINDEX_VMINDEX_SHIFT 0
+#define I40E_PFPCI_VMINDEX_VMINDEX_MASK (0x1FF << I40E_PFPCI_VMINDEX_VMINDEX_SHIFT)
+#define I40E_PFPCI_VMPEND 0x0009C380
+#define I40E_PFPCI_VMPEND_PENDING_SHIFT 0
+#define I40E_PFPCI_VMPEND_PENDING_MASK (0x1 << I40E_PFPCI_VMPEND_PENDING_SHIFT)
+#define I40E_GLPE_CPUSTATUS0 0x0000D040
+#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT 0
+#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT)
+#define I40E_GLPE_CPUSTATUS1 0x0000D044
+#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT 0
+#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT)
+#define I40E_GLPE_CPUSTATUS2 0x0000D048
+#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT 0
+#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT)
+#define I40E_GLPE_PFFLMOBJCTRL(_i) (0x0000D480 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPE_PFFLMOBJCTRL_MAX_INDEX 15
+#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
+#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
+#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
+#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
+#define I40E_GLPE_VFFLMOBJCTRL(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPE_VFFLMOBJCTRL_MAX_INDEX 31
+#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
+#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
+#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
+#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
+#define I40E_GLPE_VFFLMQ1ALLOCERR(_i) (0x0000C700 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPE_VFFLMQ1ALLOCERR_MAX_INDEX 31
+#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
+#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
+#define I40E_GLPE_VFFLMXMITALLOCERR(_i) (0x0000C600 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPE_VFFLMXMITALLOCERR_MAX_INDEX 31
+#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
+#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT)
+#define I40E_GLPE_VFUDACTRL(_i) (0x0000C000 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPE_VFUDACTRL_MAX_INDEX 31
+#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT 0
+#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT)
+#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT 1
+#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT)
+#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT 2
+#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT)
+#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT 3
+#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT)
+#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
+#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT)
+#define I40E_GLPE_VFUDAUCFBQPN(_i) (0x0000C100 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPE_VFUDAUCFBQPN_MAX_INDEX 31
+#define I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT 0
+#define I40E_GLPE_VFUDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT)
+#define I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT 31
+#define I40E_GLPE_VFUDAUCFBQPN_VALID_MASK (0x1 << I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT)
+#define I40E_PFPE_AEQALLOC 0x00131180
+#define I40E_PFPE_AEQALLOC_AECOUNT_SHIFT 0
+#define I40E_PFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_PFPE_AEQALLOC_AECOUNT_SHIFT)
+#define I40E_PFPE_CCQPHIGH 0x00008200
+#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
+#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
+#define I40E_PFPE_CCQPLOW 0x00008180
+#define I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT 0
+#define I40E_PFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT)
+#define I40E_PFPE_CCQPSTATUS 0x00008100
+#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
+#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
+#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
+#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
+#define I40E_PFPE_CQACK 0x00131100
+#define I40E_PFPE_CQACK_PECQID_SHIFT 0
+#define I40E_PFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_PFPE_CQACK_PECQID_SHIFT)
+#define I40E_PFPE_CQARM 0x00131080
+#define I40E_PFPE_CQARM_PECQID_SHIFT 0
+#define I40E_PFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_PFPE_CQARM_PECQID_SHIFT)
+#define I40E_PFPE_CQPDB 0x00008000
+#define I40E_PFPE_CQPDB_WQHEAD_SHIFT 0
+#define I40E_PFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_PFPE_CQPDB_WQHEAD_SHIFT)
+#define I40E_PFPE_CQPERRCODES 0x00008880
+#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
+#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
+#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
+#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
+#define I40E_PFPE_CQPTAIL 0x00008080
+#define I40E_PFPE_CQPTAIL_WQTAIL_SHIFT 0
+#define I40E_PFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_PFPE_CQPTAIL_WQTAIL_SHIFT)
+#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
+#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
+#define I40E_PFPE_FLMQ1ALLOCERR 0x00008980
+#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
+#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
+#define I40E_PFPE_FLMXMITALLOCERR 0x00008900
+#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
+#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT)
+#define I40E_PFPE_IPCONFIG0 0x00008280
+#define I40E_PFPE_IPCONFIG0_PEIPID_SHIFT 0
+#define I40E_PFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_PFPE_IPCONFIG0_PEIPID_SHIFT)
+#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
+#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
+
+#define I40E_PFPE_MRTEIDXMASK 0x00008600
+#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
+#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
+#define I40E_PFPE_RCVUNEXPECTEDERROR 0x00008680
+#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
+#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
+#define I40E_PFPE_TCPNOWTIMER 0x00008580
+#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
+#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
+#define I40E_PFPE_UDACTRL 0x00008700
+#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT 0
+#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT)
+#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT 1
+#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT)
+#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT 2
+#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT)
+#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT 3
+#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT)
+#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
+#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT)
+#define I40E_PFPE_UDAUCFBQPN 0x00008780
+#define I40E_PFPE_UDAUCFBQPN_QPN_SHIFT 0
+#define I40E_PFPE_UDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_PFPE_UDAUCFBQPN_QPN_SHIFT)
+#define I40E_PFPE_UDAUCFBQPN_VALID_SHIFT 31
+#define I40E_PFPE_UDAUCFBQPN_VALID_MASK (0x1 << I40E_PFPE_UDAUCFBQPN_VALID_SHIFT)
+#define I40E_PFPE_WQEALLOC 0x00138C00
+#define I40E_PFPE_WQEALLOC_PEQPID_SHIFT 0
+#define I40E_PFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_PFPE_WQEALLOC_PEQPID_SHIFT)
+#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
+#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
+#define I40E_VFPE_AEQALLOC(_VF) (0x00130C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_AEQALLOC_MAX_INDEX 127
+#define I40E_VFPE_AEQALLOC_AECOUNT_SHIFT 0
+#define I40E_VFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC_AECOUNT_SHIFT)
+#define I40E_VFPE_CCQPHIGH(_VF) (0x00001000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_CCQPHIGH_MAX_INDEX 127
+#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
+#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
+#define I40E_VFPE_CCQPLOW(_VF) (0x00000C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_CCQPLOW_MAX_INDEX 127
+#define I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT 0
+#define I40E_VFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT)
+#define I40E_VFPE_CCQPSTATUS(_VF) (0x00000800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_CCQPSTATUS_MAX_INDEX 127
+#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
+#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
+#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
+#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
+#define I40E_VFPE_CQACK(_VF) (0x00130800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_CQACK_MAX_INDEX 127
+#define I40E_VFPE_CQACK_PECQID_SHIFT 0
+#define I40E_VFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK_PECQID_SHIFT)
+#define I40E_VFPE_CQARM(_VF) (0x00130400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_CQARM_MAX_INDEX 127
+#define I40E_VFPE_CQARM_PECQID_SHIFT 0
+#define I40E_VFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM_PECQID_SHIFT)
+#define I40E_VFPE_CQPDB(_VF) (0x00000000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_CQPDB_MAX_INDEX 127
+#define I40E_VFPE_CQPDB_WQHEAD_SHIFT 0
+#define I40E_VFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB_WQHEAD_SHIFT)
+#define I40E_VFPE_CQPERRCODES(_VF) (0x00001800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_CQPERRCODES_MAX_INDEX 127
+#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
+#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
+#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
+#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
+#define I40E_VFPE_CQPTAIL(_VF) (0x00000400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_CQPTAIL_MAX_INDEX 127
+#define I40E_VFPE_CQPTAIL_WQTAIL_SHIFT 0
+#define I40E_VFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL_WQTAIL_SHIFT)
+#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
+#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
+#define I40E_VFPE_IPCONFIG0(_VF) (0x00001400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_IPCONFIG0_MAX_INDEX 127
+#define I40E_VFPE_IPCONFIG0_PEIPID_SHIFT 0
+#define I40E_VFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG0_PEIPID_SHIFT)
+#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
+#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
+#define I40E_VFPE_MRTEIDXMASK(_VF) (0x00003000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_MRTEIDXMASK_MAX_INDEX 127
+#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
+#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
+#define I40E_VFPE_RCVUNEXPECTEDERROR(_VF) (0x00003400 + ((_VF) * 4))
+#define I40E_VFPE_RCVUNEXPECTEDERROR_MAX_INDEX 127
+#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
+#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
+#define I40E_VFPE_TCPNOWTIMER(_VF) (0x00002C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_TCPNOWTIMER_MAX_INDEX 127
+#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
+#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
+#define I40E_VFPE_WQEALLOC(_VF) (0x00138000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFPE_WQEALLOC_MAX_INDEX 127
+#define I40E_VFPE_WQEALLOC_PEQPID_SHIFT 0
+#define I40E_VFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC_PEQPID_SHIFT)
+#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
+#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
+#define I40E_GLPES_PFIP4RXDISCARD(_i) (0x00010600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4RXDISCARD_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
+#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
+#define I40E_GLPES_PFIP4RXFRAGSHI(_i) (0x00010804 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4RXFRAGSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
+#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
+#define I40E_GLPES_PFIP4RXFRAGSLO(_i) (0x00010800 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4RXFRAGSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
+#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
+#define I40E_GLPES_PFIP4RXMCOCTSHI(_i) (0x00010A04 + ((_i) * 8))
+#define I40E_GLPES_PFIP4RXMCOCTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
+#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
+#define I40E_GLPES_PFIP4RXMCOCTSLO(_i) (0x00010A00 + ((_i) * 8))
+#define I40E_GLPES_PFIP4RXMCOCTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
+#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
+#define I40E_GLPES_PFIP4RXMCPKTSHI(_i) (0x00010C04 + ((_i) * 8))
+#define I40E_GLPES_PFIP4RXMCPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
+#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
+#define I40E_GLPES_PFIP4RXMCPKTSLO(_i) (0x00010C00 + ((_i) * 8))
+#define I40E_GLPES_PFIP4RXMCPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
+#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
+#define I40E_GLPES_PFIP4RXOCTSHI(_i) (0x00010204 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4RXOCTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
+#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
+#define I40E_GLPES_PFIP4RXOCTSLO(_i) (0x00010200 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4RXOCTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
+#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
+#define I40E_GLPES_PFIP4RXPKTSHI(_i) (0x00010404 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4RXPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
+#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
+#define I40E_GLPES_PFIP4RXPKTSLO(_i) (0x00010400 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4RXPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
+#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
+#define I40E_GLPES_PFIP4RXTRUNC(_i) (0x00010700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4RXTRUNC_MAX_INDEX 15
+#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
+#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
+#define I40E_GLPES_PFIP4TXFRAGSHI(_i) (0x00011E04 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4TXFRAGSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
+#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
+#define I40E_GLPES_PFIP4TXFRAGSLO(_i) (0x00011E00 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4TXFRAGSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
+#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
+#define I40E_GLPES_PFIP4TXMCOCTSHI(_i) (0x00012004 + ((_i) * 8))
+#define I40E_GLPES_PFIP4TXMCOCTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
+#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
+#define I40E_GLPES_PFIP4TXMCOCTSLO(_i) (0x00012000 + ((_i) * 8))
+#define I40E_GLPES_PFIP4TXMCOCTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
+#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
+#define I40E_GLPES_PFIP4TXMCPKTSHI(_i) (0x00012204 + ((_i) * 8))
+#define I40E_GLPES_PFIP4TXMCPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
+#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
+#define I40E_GLPES_PFIP4TXMCPKTSLO(_i) (0x00012200 + ((_i) * 8))
+#define I40E_GLPES_PFIP4TXMCPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
+#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
+#define I40E_GLPES_PFIP4TXNOROUTE(_i) (0x00012E00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4TXNOROUTE_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
+#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
+#define I40E_GLPES_PFIP4TXOCTSHI(_i) (0x00011A04 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4TXOCTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
+#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
+#define I40E_GLPES_PFIP4TXOCTSLO(_i) (0x00011A00 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4TXOCTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
+#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
+#define I40E_GLPES_PFIP4TXPKTSHI(_i) (0x00011C04 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4TXPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
+#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
+#define I40E_GLPES_PFIP4TXPKTSLO(_i) (0x00011C00 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP4TXPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
+#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
+#define I40E_GLPES_PFIP6RXDISCARD(_i) (0x00011200 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6RXDISCARD_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
+#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
+#define I40E_GLPES_PFIP6RXFRAGSHI(_i) (0x00011404 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6RXFRAGSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
+#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
+#define I40E_GLPES_PFIP6RXFRAGSLO(_i) (0x00011400 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6RXFRAGSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
+#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
+#define I40E_GLPES_PFIP6RXMCOCTSHI(_i) (0x00011604 + ((_i) * 8))
+#define I40E_GLPES_PFIP6RXMCOCTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
+#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
+#define I40E_GLPES_PFIP6RXMCOCTSLO(_i) (0x00011600 + ((_i) * 8))
+#define I40E_GLPES_PFIP6RXMCOCTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
+#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
+#define I40E_GLPES_PFIP6RXMCPKTSHI(_i) (0x00011804 + ((_i) * 8))
+#define I40E_GLPES_PFIP6RXMCPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
+#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
+#define I40E_GLPES_PFIP6RXMCPKTSLO(_i) (0x00011800 + ((_i) * 8))
+#define I40E_GLPES_PFIP6RXMCPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
+#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
+#define I40E_GLPES_PFIP6RXOCTSHI(_i) (0x00010E04 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6RXOCTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
+#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
+#define I40E_GLPES_PFIP6RXOCTSLO(_i) (0x00010E00 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6RXOCTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
+#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
+#define I40E_GLPES_PFIP6RXPKTSHI(_i) (0x00011004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6RXPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
+#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
+#define I40E_GLPES_PFIP6RXPKTSLO(_i) (0x00011000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6RXPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
+#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
+#define I40E_GLPES_PFIP6RXTRUNC(_i) (0x00011300 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6RXTRUNC_MAX_INDEX 15
+#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
+#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
+#define I40E_GLPES_PFIP6TXFRAGSHI(_i) (0x00012804 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6TXFRAGSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
+#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
+#define I40E_GLPES_PFIP6TXFRAGSLO(_i) (0x00012800 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6TXFRAGSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
+#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
+#define I40E_GLPES_PFIP6TXMCOCTSHI(_i) (0x00012A04 + ((_i) * 8))
+#define I40E_GLPES_PFIP6TXMCOCTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
+#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
+#define I40E_GLPES_PFIP6TXMCOCTSLO(_i) (0x00012A00 + ((_i) * 8))
+#define I40E_GLPES_PFIP6TXMCOCTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
+#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
+#define I40E_GLPES_PFIP6TXMCPKTSHI(_i) (0x00012C04 + ((_i) * 8))
+#define I40E_GLPES_PFIP6TXMCPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
+#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
+#define I40E_GLPES_PFIP6TXMCPKTSLO(_i) (0x00012C00 + ((_i) * 8))
+#define I40E_GLPES_PFIP6TXMCPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
+#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
+#define I40E_GLPES_PFIP6TXNOROUTE(_i) (0x00012F00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6TXNOROUTE_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
+#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
+#define I40E_GLPES_PFIP6TXOCTSHI(_i) (0x00012404 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6TXOCTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
+#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
+#define I40E_GLPES_PFIP6TXOCTSLO(_i) (0x00012400 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6TXOCTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
+#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
+#define I40E_GLPES_PFIP6TXPKTSHI(_i) (0x00012604 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6TXPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
+#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
+#define I40E_GLPES_PFIP6TXPKTSLO(_i) (0x00012600 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFIP6TXPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
+#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
+#define I40E_GLPES_PFRDMARXRDSHI(_i) (0x00013E04 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMARXRDSHI_MAX_INDEX 15
+#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
+#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
+#define I40E_GLPES_PFRDMARXRDSLO(_i) (0x00013E00 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMARXRDSLO_MAX_INDEX 15
+#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
+#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
+#define I40E_GLPES_PFRDMARXSNDSHI(_i) (0x00014004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMARXSNDSHI_MAX_INDEX 15
+#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
+#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
+#define I40E_GLPES_PFRDMARXSNDSLO(_i) (0x00014000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMARXSNDSLO_MAX_INDEX 15
+#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
+#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
+#define I40E_GLPES_PFRDMARXWRSHI(_i) (0x00013C04 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMARXWRSHI_MAX_INDEX 15
+#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
+#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
+#define I40E_GLPES_PFRDMARXWRSLO(_i) (0x00013C00 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMARXWRSLO_MAX_INDEX 15
+#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
+#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
+#define I40E_GLPES_PFRDMATXRDSHI(_i) (0x00014404 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMATXRDSHI_MAX_INDEX 15
+#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
+#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
+#define I40E_GLPES_PFRDMATXRDSLO(_i) (0x00014400 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMATXRDSLO_MAX_INDEX 15
+#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
+#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
+#define I40E_GLPES_PFRDMATXSNDSHI(_i) (0x00014604 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMATXSNDSHI_MAX_INDEX 15
+#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
+#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
+#define I40E_GLPES_PFRDMATXSNDSLO(_i) (0x00014600 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMATXSNDSLO_MAX_INDEX 15
+#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
+#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
+#define I40E_GLPES_PFRDMATXWRSHI(_i) (0x00014204 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMATXWRSHI_MAX_INDEX 15
+#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
+#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
+#define I40E_GLPES_PFRDMATXWRSLO(_i) (0x00014200 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMATXWRSLO_MAX_INDEX 15
+#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
+#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
+#define I40E_GLPES_PFRDMAVBNDHI(_i) (0x00014804 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMAVBNDHI_MAX_INDEX 15
+#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
+#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
+#define I40E_GLPES_PFRDMAVBNDLO(_i) (0x00014800 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMAVBNDLO_MAX_INDEX 15
+#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
+#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
+#define I40E_GLPES_PFRDMAVINVHI(_i) (0x00014A04 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMAVINVHI_MAX_INDEX 15
+#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT 0
+#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT)
+#define I40E_GLPES_PFRDMAVINVLO(_i) (0x00014A00 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFRDMAVINVLO_MAX_INDEX 15
+#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT 0
+#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT)
+#define I40E_GLPES_PFRXVLANERR(_i) (0x00010000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPES_PFRXVLANERR_MAX_INDEX 15
+#define I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT 0
+#define I40E_GLPES_PFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT)
+#define I40E_GLPES_PFTCPRTXSEG(_i) (0x00013600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPES_PFTCPRTXSEG_MAX_INDEX 15
+#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT 0
+#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT)
+#define I40E_GLPES_PFTCPRXOPTERR(_i) (0x00013200 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLPES_PFTCPRXOPTERR_MAX_INDEX 15
+#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
+#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
+#define I40E_GLPES_PFTCPRXPROTOERR(_i) (0x00013300 + ((_i) * 4))
+#define I40E_GLPES_PFTCPRXPROTOERR_MAX_INDEX 15
+#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
+#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
+#define I40E_GLPES_PFTCPRXSEGSHI(_i) (0x00013004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFTCPRXSEGSHI_MAX_INDEX 15
+#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
+#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
+#define I40E_GLPES_PFTCPRXSEGSLO(_i) (0x00013000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFTCPRXSEGSLO_MAX_INDEX 15
+#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
+#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
+#define I40E_GLPES_PFTCPTXSEGHI(_i) (0x00013404 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFTCPTXSEGHI_MAX_INDEX 15
+#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
+#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
+#define I40E_GLPES_PFTCPTXSEGLO(_i) (0x00013400 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFTCPTXSEGLO_MAX_INDEX 15
+#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
+#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
+#define I40E_GLPES_PFUDPRXPKTSHI(_i) (0x00013804 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFUDPRXPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
+#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
+#define I40E_GLPES_PFUDPRXPKTSLO(_i) (0x00013800 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFUDPRXPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
+#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
+#define I40E_GLPES_PFUDPTXPKTSHI(_i) (0x00013A04 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFUDPTXPKTSHI_MAX_INDEX 15
+#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
+#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
+#define I40E_GLPES_PFUDPTXPKTSLO(_i) (0x00013A00 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPES_PFUDPTXPKTSLO_MAX_INDEX 15
+#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
+#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
+#define I40E_GLPES_RDMARXMULTFPDUSHI 0x0001E014
+#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT 0
+#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT)
+#define I40E_GLPES_RDMARXMULTFPDUSLO 0x0001E010
+#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT 0
+#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT)
+#define I40E_GLPES_RDMARXOOODDPHI 0x0001E01C
+#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT 0
+#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT)
+#define I40E_GLPES_RDMARXOOODDPLO 0x0001E018
+#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT 0
+#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT)
+#define I40E_GLPES_RDMARXOOONOMARK 0x0001E004
+#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT 0
+#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT)
+#define I40E_GLPES_RDMARXUNALIGN 0x0001E000
+#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT 0
+#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT)
+#define I40E_GLPES_TCPRXFOURHOLEHI 0x0001E044
+#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT 0
+#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT)
+#define I40E_GLPES_TCPRXFOURHOLELO 0x0001E040
+#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT 0
+#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT)
+#define I40E_GLPES_TCPRXONEHOLEHI 0x0001E02C
+#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT 0
+#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT)
+#define I40E_GLPES_TCPRXONEHOLELO 0x0001E028
+#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT 0
+#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT)
+#define I40E_GLPES_TCPRXPUREACKHI 0x0001E024
+#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT 0
+#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT)
+#define I40E_GLPES_TCPRXPUREACKSLO 0x0001E020
+#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT 0
+#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT)
+#define I40E_GLPES_TCPRXTHREEHOLEHI 0x0001E03C
+#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT 0
+#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT)
+#define I40E_GLPES_TCPRXTHREEHOLELO 0x0001E038
+#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT 0
+#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT)
+#define I40E_GLPES_TCPRXTWOHOLEHI 0x0001E034
+#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT 0
+#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT)
+#define I40E_GLPES_TCPRXTWOHOLELO 0x0001E030
+#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT 0
+#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT)
+#define I40E_GLPES_TCPRXUNEXPERR 0x0001E008
+#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT 0
+#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_MASK (0xFFFFFF << I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT)
+#define I40E_GLPES_TCPTXRETRANSFASTHI 0x0001E04C
+#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT 0
+#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT)
+#define I40E_GLPES_TCPTXRETRANSFASTLO 0x0001E048
+#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT 0
+#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT)
+#define I40E_GLPES_TCPTXTOUTSFASTHI 0x0001E054
+#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT 0
+#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT)
+#define I40E_GLPES_TCPTXTOUTSFASTLO 0x0001E050
+#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT 0
+#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT)
+#define I40E_GLPES_TCPTXTOUTSHI 0x0001E05C
+#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT 0
+#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT)
+#define I40E_GLPES_TCPTXTOUTSLO 0x0001E058
+#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT 0
+#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT)
+#define I40E_GLPES_VFIP4RXDISCARD(_i) (0x00018600 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4RXDISCARD_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
+#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
+#define I40E_GLPES_VFIP4RXFRAGSHI(_i) (0x00018804 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4RXFRAGSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
+#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
+#define I40E_GLPES_VFIP4RXFRAGSLO(_i) (0x00018800 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4RXFRAGSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
+#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
+#define I40E_GLPES_VFIP4RXMCOCTSHI(_i) (0x00018A04 + ((_i) * 4))
+#define I40E_GLPES_VFIP4RXMCOCTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
+#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
+#define I40E_GLPES_VFIP4RXMCOCTSLO(_i) (0x00018A00 + ((_i) * 4))
+#define I40E_GLPES_VFIP4RXMCOCTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
+#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
+#define I40E_GLPES_VFIP4RXMCPKTSHI(_i) (0x00018C04 + ((_i) * 4))
+#define I40E_GLPES_VFIP4RXMCPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
+#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
+#define I40E_GLPES_VFIP4RXMCPKTSLO(_i) (0x00018C00 + ((_i) * 4))
+#define I40E_GLPES_VFIP4RXMCPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
+#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
+#define I40E_GLPES_VFIP4RXOCTSHI(_i) (0x00018204 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4RXOCTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
+#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
+#define I40E_GLPES_VFIP4RXOCTSLO(_i) (0x00018200 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4RXOCTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
+#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
+#define I40E_GLPES_VFIP4RXPKTSHI(_i) (0x00018404 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4RXPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
+#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
+#define I40E_GLPES_VFIP4RXPKTSLO(_i) (0x00018400 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4RXPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
+#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
+#define I40E_GLPES_VFIP4RXTRUNC(_i) (0x00018700 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4RXTRUNC_MAX_INDEX 31
+#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
+#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
+#define I40E_GLPES_VFIP4TXFRAGSHI(_i) (0x00019E04 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4TXFRAGSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
+#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
+#define I40E_GLPES_VFIP4TXFRAGSLO(_i) (0x00019E00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4TXFRAGSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
+#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
+#define I40E_GLPES_VFIP4TXMCOCTSHI(_i) (0x0001A004 + ((_i) * 4))
+#define I40E_GLPES_VFIP4TXMCOCTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
+#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
+#define I40E_GLPES_VFIP4TXMCOCTSLO(_i) (0x0001A000 + ((_i) * 4))
+#define I40E_GLPES_VFIP4TXMCOCTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
+#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
+#define I40E_GLPES_VFIP4TXMCPKTSHI(_i) (0x0001A204 + ((_i) * 4))
+#define I40E_GLPES_VFIP4TXMCPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
+#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
+#define I40E_GLPES_VFIP4TXMCPKTSLO(_i) (0x0001A200 + ((_i) * 4))
+#define I40E_GLPES_VFIP4TXMCPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
+#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
+#define I40E_GLPES_VFIP4TXNOROUTE(_i) (0x0001AE00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4TXNOROUTE_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
+#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
+#define I40E_GLPES_VFIP4TXOCTSHI(_i) (0x00019A04 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4TXOCTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
+#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
+#define I40E_GLPES_VFIP4TXOCTSLO(_i) (0x00019A00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4TXOCTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
+#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
+#define I40E_GLPES_VFIP4TXPKTSHI(_i) (0x00019C04 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4TXPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
+#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
+#define I40E_GLPES_VFIP4TXPKTSLO(_i) (0x00019C00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP4TXPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
+#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
+#define I40E_GLPES_VFIP6RXDISCARD(_i) (0x00019200 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6RXDISCARD_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
+#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
+#define I40E_GLPES_VFIP6RXFRAGSHI(_i) (0x00019404 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6RXFRAGSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
+#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
+#define I40E_GLPES_VFIP6RXFRAGSLO(_i) (0x00019400 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6RXFRAGSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
+#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
+#define I40E_GLPES_VFIP6RXMCOCTSHI(_i) (0x00019604 + ((_i) * 4))
+#define I40E_GLPES_VFIP6RXMCOCTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
+#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
+#define I40E_GLPES_VFIP6RXMCOCTSLO(_i) (0x00019600 + ((_i) * 4))
+#define I40E_GLPES_VFIP6RXMCOCTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
+#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
+#define I40E_GLPES_VFIP6RXMCPKTSHI(_i) (0x00019804 + ((_i) * 4))
+#define I40E_GLPES_VFIP6RXMCPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
+#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
+#define I40E_GLPES_VFIP6RXMCPKTSLO(_i) (0x00019800 + ((_i) * 4))
+#define I40E_GLPES_VFIP6RXMCPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
+#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
+#define I40E_GLPES_VFIP6RXOCTSHI(_i) (0x00018E04 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6RXOCTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
+#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
+#define I40E_GLPES_VFIP6RXOCTSLO(_i) (0x00018E00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6RXOCTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
+#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
+#define I40E_GLPES_VFIP6RXPKTSHI(_i) (0x00019004 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6RXPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
+#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
+#define I40E_GLPES_VFIP6RXPKTSLO(_i) (0x00019000 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6RXPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
+#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
+#define I40E_GLPES_VFIP6RXTRUNC(_i) (0x00019300 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6RXTRUNC_MAX_INDEX 31
+#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
+#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
+#define I40E_GLPES_VFIP6TXFRAGSHI(_i) (0x0001A804 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6TXFRAGSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
+#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
+#define I40E_GLPES_VFIP6TXFRAGSLO(_i) (0x0001A800 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6TXFRAGSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
+#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
+#define I40E_GLPES_VFIP6TXMCOCTSHI(_i) (0x0001AA04 + ((_i) * 4))
+#define I40E_GLPES_VFIP6TXMCOCTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
+#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
+#define I40E_GLPES_VFIP6TXMCOCTSLO(_i) (0x0001AA00 + ((_i) * 4))
+#define I40E_GLPES_VFIP6TXMCOCTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
+#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
+#define I40E_GLPES_VFIP6TXMCPKTSHI(_i) (0x0001AC04 + ((_i) * 4))
+#define I40E_GLPES_VFIP6TXMCPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
+#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
+#define I40E_GLPES_VFIP6TXMCPKTSLO(_i) (0x0001AC00 + ((_i) * 4))
+#define I40E_GLPES_VFIP6TXMCPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
+#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
+#define I40E_GLPES_VFIP6TXNOROUTE(_i) (0x0001AF00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6TXNOROUTE_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
+#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
+#define I40E_GLPES_VFIP6TXOCTSHI(_i) (0x0001A404 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6TXOCTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
+#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
+#define I40E_GLPES_VFIP6TXOCTSLO(_i) (0x0001A400 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6TXOCTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
+#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
+#define I40E_GLPES_VFIP6TXPKTSHI(_i) (0x0001A604 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6TXPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
+#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
+#define I40E_GLPES_VFIP6TXPKTSLO(_i) (0x0001A600 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFIP6TXPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
+#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
+#define I40E_GLPES_VFRDMARXRDSHI(_i) (0x0001BE04 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMARXRDSHI_MAX_INDEX 31
+#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
+#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
+#define I40E_GLPES_VFRDMARXRDSLO(_i) (0x0001BE00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMARXRDSLO_MAX_INDEX 31
+#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
+#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
+#define I40E_GLPES_VFRDMARXSNDSHI(_i) (0x0001C004 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMARXSNDSHI_MAX_INDEX 31
+#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
+#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
+#define I40E_GLPES_VFRDMARXSNDSLO(_i) (0x0001C000 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMARXSNDSLO_MAX_INDEX 31
+#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
+#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
+#define I40E_GLPES_VFRDMARXWRSHI(_i) (0x0001BC04 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMARXWRSHI_MAX_INDEX 31
+#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
+#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
+#define I40E_GLPES_VFRDMARXWRSLO(_i) (0x0001BC00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMARXWRSLO_MAX_INDEX 31
+#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
+#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
+#define I40E_GLPES_VFRDMATXRDSHI(_i) (0x0001C404 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMATXRDSHI_MAX_INDEX 31
+#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
+#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
+#define I40E_GLPES_VFRDMATXRDSLO(_i) (0x0001C400 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMATXRDSLO_MAX_INDEX 31
+#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
+#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
+#define I40E_GLPES_VFRDMATXSNDSHI(_i) (0x0001C604 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMATXSNDSHI_MAX_INDEX 31
+#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
+#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
+#define I40E_GLPES_VFRDMATXSNDSLO(_i) (0x0001C600 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMATXSNDSLO_MAX_INDEX 31
+#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
+#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
+#define I40E_GLPES_VFRDMATXWRSHI(_i) (0x0001C204 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMATXWRSHI_MAX_INDEX 31
+#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
+#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
+#define I40E_GLPES_VFRDMATXWRSLO(_i) (0x0001C200 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMATXWRSLO_MAX_INDEX 31
+#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
+#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
+#define I40E_GLPES_VFRDMAVBNDHI(_i) (0x0001C804 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMAVBNDHI_MAX_INDEX 31
+#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
+#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
+#define I40E_GLPES_VFRDMAVBNDLO(_i) (0x0001C800 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMAVBNDLO_MAX_INDEX 31
+#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
+#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
+#define I40E_GLPES_VFRDMAVINVHI(_i) (0x0001CA04 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMAVINVHI_MAX_INDEX 31
+#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT 0
+#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT)
+#define I40E_GLPES_VFRDMAVINVLO(_i) (0x0001CA00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRDMAVINVLO_MAX_INDEX 31
+#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT 0
+#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT)
+#define I40E_GLPES_VFRXVLANERR(_i) (0x00018000 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFRXVLANERR_MAX_INDEX 31
+#define I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT 0
+#define I40E_GLPES_VFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT)
+#define I40E_GLPES_VFTCPRTXSEG(_i) (0x0001B600 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFTCPRTXSEG_MAX_INDEX 31
+#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT 0
+#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT)
+#define I40E_GLPES_VFTCPRXOPTERR(_i) (0x0001B200 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFTCPRXOPTERR_MAX_INDEX 31
+#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
+#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
+#define I40E_GLPES_VFTCPRXPROTOERR(_i) (0x0001B300 + ((_i) * 4))
+#define I40E_GLPES_VFTCPRXPROTOERR_MAX_INDEX 31
+#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
+#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
+#define I40E_GLPES_VFTCPRXSEGSHI(_i) (0x0001B004 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFTCPRXSEGSHI_MAX_INDEX 31
+#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
+#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
+#define I40E_GLPES_VFTCPRXSEGSLO(_i) (0x0001B000 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFTCPRXSEGSLO_MAX_INDEX 31
+#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
+#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
+#define I40E_GLPES_VFTCPTXSEGHI(_i) (0x0001B404 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFTCPTXSEGHI_MAX_INDEX 31
+#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
+#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
+#define I40E_GLPES_VFTCPTXSEGLO(_i) (0x0001B400 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFTCPTXSEGLO_MAX_INDEX 31
+#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
+#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
+#define I40E_GLPES_VFUDPRXPKTSHI(_i) (0x0001B804 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFUDPRXPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
+#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
+#define I40E_GLPES_VFUDPRXPKTSLO(_i) (0x0001B800 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFUDPRXPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
+#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
+#define I40E_GLPES_VFUDPTXPKTSHI(_i) (0x0001BA04 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFUDPTXPKTSHI_MAX_INDEX 31
+#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
+#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
+#define I40E_GLPES_VFUDPTXPKTSLO(_i) (0x0001BA00 + ((_i) * 4)) /* _i=0...31 */
+#define I40E_GLPES_VFUDPTXPKTSLO_MAX_INDEX 31
+#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
+#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
+#define I40E_PRTPM_EEE_STAT 0x001E4320
+#define I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT 29
+#define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK (0x1 << I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
+#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT 30
+#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT 31
+#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEEC 0x001E4380
+#define I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT 16
+#define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK (0x3F << I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT)
+#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT 24
+#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK (0x3 << I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT)
+#define I40E_PRTPM_EEEC_TEEE_DLY_SHIFT 26
+#define I40E_PRTPM_EEEC_TEEE_DLY_MASK (0x3F << I40E_PRTPM_EEEC_TEEE_DLY_SHIFT)
+#define I40E_PRTPM_EEEFWD 0x001E4400
+#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT 31
+#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK (0x1 << I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT)
+#define I40E_PRTPM_EEER 0x001E4360
+#define I40E_PRTPM_EEER_TW_SYSTEM_SHIFT 0
+#define I40E_PRTPM_EEER_TW_SYSTEM_MASK (0xFFFF << I40E_PRTPM_EEER_TW_SYSTEM_SHIFT)
+#define I40E_PRTPM_EEER_TX_LPI_EN_SHIFT 16
+#define I40E_PRTPM_EEER_TX_LPI_EN_MASK (0x1 << I40E_PRTPM_EEER_TX_LPI_EN_SHIFT)
+#define I40E_PRTPM_EEETXC 0x001E43E0
+#define I40E_PRTPM_EEETXC_TW_PHY_SHIFT 0
+#define I40E_PRTPM_EEETXC_TW_PHY_MASK (0xFFFF << I40E_PRTPM_EEETXC_TW_PHY_SHIFT)
+#define I40E_PRTPM_GC 0x000B8140
+#define I40E_PRTPM_GC_EMP_LINK_ON_SHIFT 0
+#define I40E_PRTPM_GC_EMP_LINK_ON_MASK (0x1 << I40E_PRTPM_GC_EMP_LINK_ON_SHIFT)
+#define I40E_PRTPM_GC_MNG_VETO_SHIFT 1
+#define I40E_PRTPM_GC_MNG_VETO_MASK (0x1 << I40E_PRTPM_GC_MNG_VETO_SHIFT)
+#define I40E_PRTPM_GC_RATD_SHIFT 2
+#define I40E_PRTPM_GC_RATD_MASK (0x1 << I40E_PRTPM_GC_RATD_SHIFT)
+#define I40E_PRTPM_GC_LCDMP_SHIFT 3
+#define I40E_PRTPM_GC_LCDMP_MASK (0x1 << I40E_PRTPM_GC_LCDMP_SHIFT)
+#define I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT 31
+#define I40E_PRTPM_GC_LPLU_ASSERTED_MASK (0x1 << I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
+#define I40E_PRTPM_RLPIC 0x001E43A0
+#define I40E_PRTPM_RLPIC_ERLPIC_SHIFT 0
+#define I40E_PRTPM_RLPIC_ERLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
+#define I40E_PRTPM_TLPIC 0x001E43C0
+#define I40E_PRTPM_TLPIC_ETLPIC_SHIFT 0
+#define I40E_PRTPM_TLPIC_ETLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_TLPIC_ETLPIC_SHIFT)
+#define I40E_GLRPB_DPSS 0x000AC828
+#define I40E_GLRPB_DPSS_DPS_TCN_SHIFT 0
+#define I40E_GLRPB_DPSS_DPS_TCN_MASK (0xFFFFF << I40E_GLRPB_DPSS_DPS_TCN_SHIFT)
+#define I40E_GLRPB_GHW 0x000AC830
+#define I40E_GLRPB_GHW_GHW_SHIFT 0
+#define I40E_GLRPB_GHW_GHW_MASK (0xFFFFF << I40E_GLRPB_GHW_GHW_SHIFT)
+#define I40E_GLRPB_GLW 0x000AC834
+#define I40E_GLRPB_GLW_GLW_SHIFT 0
+#define I40E_GLRPB_GLW_GLW_MASK (0xFFFFF << I40E_GLRPB_GLW_GLW_SHIFT)
+#define I40E_GLRPB_PHW 0x000AC844
+#define I40E_GLRPB_PHW_PHW_SHIFT 0
+#define I40E_GLRPB_PHW_PHW_MASK (0xFFFFF << I40E_GLRPB_PHW_PHW_SHIFT)
+#define I40E_GLRPB_PLW 0x000AC848
+#define I40E_GLRPB_PLW_PLW_SHIFT 0
+#define I40E_GLRPB_PLW_PLW_MASK (0xFFFFF << I40E_GLRPB_PLW_PLW_SHIFT)
+#define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DHW_MAX_INDEX 7
+#define I40E_PRTRPB_DHW_DHW_TCN_SHIFT 0
+#define I40E_PRTRPB_DHW_DHW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DHW_DHW_TCN_SHIFT)
+#define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DLW_MAX_INDEX 7
+#define I40E_PRTRPB_DLW_DLW_TCN_SHIFT 0
+#define I40E_PRTRPB_DLW_DLW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DLW_DLW_TCN_SHIFT)
+#define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DPS_MAX_INDEX 7
+#define I40E_PRTRPB_DPS_DPS_TCN_SHIFT 0
+#define I40E_PRTRPB_DPS_DPS_TCN_MASK (0xFFFFF << I40E_PRTRPB_DPS_DPS_TCN_SHIFT)
+#define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_SHT_MAX_INDEX 7
+#define I40E_PRTRPB_SHT_SHT_TCN_SHIFT 0
+#define I40E_PRTRPB_SHT_SHT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SHT_SHT_TCN_SHIFT)
+#define I40E_PRTRPB_SHW 0x000AC580
+#define I40E_PRTRPB_SHW_SHW_SHIFT 0
+#define I40E_PRTRPB_SHW_SHW_MASK (0xFFFFF << I40E_PRTRPB_SHW_SHW_SHIFT)
+#define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_SLT_MAX_INDEX 7
+#define I40E_PRTRPB_SLT_SLT_TCN_SHIFT 0
+#define I40E_PRTRPB_SLT_SLT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SLT_SLT_TCN_SHIFT)
+#define I40E_PRTRPB_SLW 0x000AC6A0
+#define I40E_PRTRPB_SLW_SLW_SHIFT 0
+#define I40E_PRTRPB_SLW_SLW_MASK (0xFFFFF << I40E_PRTRPB_SLW_SLW_SHIFT)
+#define I40E_PRTRPB_SPS 0x000AC7C0
+#define I40E_PRTRPB_SPS_SPS_SHIFT 0
+#define I40E_PRTRPB_SPS_SPS_MASK (0xFFFFF << I40E_PRTRPB_SPS_SPS_SHIFT)
+#define I40E_GLQF_APBVT(_i) (0x00260000 + ((_i) * 4)) /* _i=0...2047 */
+#define I40E_GLQF_APBVT_MAX_INDEX 2047
+#define I40E_GLQF_APBVT_APBVT_SHIFT 0
+#define I40E_GLQF_APBVT_APBVT_MASK (0xFFFFFFFF << I40E_GLQF_APBVT_APBVT_SHIFT)
+#define I40E_GLQF_CTL 0x00269BA4
+#define I40E_GLQF_CTL_HTOEP_SHIFT 1
+#define I40E_GLQF_CTL_HTOEP_MASK (0x1 << I40E_GLQF_CTL_HTOEP_SHIFT)
+#define I40E_GLQF_CTL_HTOEP_FCOE_SHIFT 2
+#define I40E_GLQF_CTL_HTOEP_FCOE_MASK (0x1 << I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
+#define I40E_GLQF_CTL_PCNT_ALLOC_SHIFT 3
+#define I40E_GLQF_CTL_PCNT_ALLOC_MASK (0x7 << I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
+#define I40E_GLQF_CTL_RSVD_SHIFT 7
+#define I40E_GLQF_CTL_RSVD_MASK (0x1 << I40E_GLQF_CTL_RSVD_SHIFT)
+#define I40E_GLQF_CTL_MAXPEBLEN_SHIFT 8
+#define I40E_GLQF_CTL_MAXPEBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFCBLEN_SHIFT 11
+#define I40E_GLQF_CTL_MAXFCBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFCBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFDBLEN_SHIFT 14
+#define I40E_GLQF_CTL_MAXFDBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFDBLEN_SHIFT)
+#define I40E_GLQF_CTL_FDBEST_SHIFT 17
+#define I40E_GLQF_CTL_FDBEST_MASK (0xFF << I40E_GLQF_CTL_FDBEST_SHIFT)
+#define I40E_GLQF_CTL_PROGPRIO_SHIFT 25
+#define I40E_GLQF_CTL_PROGPRIO_MASK (0x1 << I40E_GLQF_CTL_PROGPRIO_SHIFT)
+#define I40E_GLQF_CTL_INVALPRIO_SHIFT 26
+#define I40E_GLQF_CTL_INVALPRIO_MASK (0x1 << I40E_GLQF_CTL_INVALPRIO_SHIFT)
+#define I40E_GLQF_CTL_IGNORE_IP_SHIFT 27
+#define I40E_GLQF_CTL_IGNORE_IP_MASK (0x1 << I40E_GLQF_CTL_IGNORE_IP_SHIFT)
+#define I40E_GLQF_FDCNT_0 0x00269BAC
+#define I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT 0
+#define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT)
+#define I40E_GLQF_FDCNT_0_BESTCNT_SHIFT 13
+#define I40E_GLQF_FDCNT_0_BESTCNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_BESTCNT_SHIFT)
+#define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */
+#define I40E_GLQF_HSYM_MAX_INDEX 63
+#define I40E_GLQF_HSYM_SYMH_ENA_SHIFT 0
+#define I40E_GLQF_HSYM_SYMH_ENA_MASK (0x1 << I40E_GLQF_HSYM_SYMH_ENA_SHIFT)
+#define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */
+#define I40E_GLQF_PCNT_MAX_INDEX 511
+#define I40E_GLQF_PCNT_PCNT_SHIFT 0
+#define I40E_GLQF_PCNT_PCNT_MASK (0xFFFFFFFF << I40E_GLQF_PCNT_PCNT_SHIFT)
+#define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */
+#define I40E_GLQF_SWAP_MAX_INDEX 1
+#define I40E_GLQF_SWAP_OFF0_SRC0_SHIFT 0
+#define I40E_GLQF_SWAP_OFF0_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF0_SRC1_SHIFT 6
+#define I40E_GLQF_SWAP_OFF0_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_FLEN0_SHIFT 12
+#define I40E_GLQF_SWAP_FLEN0_MASK (0xF << I40E_GLQF_SWAP_FLEN0_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC0_SHIFT 16
+#define I40E_GLQF_SWAP_OFF1_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC1_SHIFT 22
+#define I40E_GLQF_SWAP_OFF1_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_FLEN1_SHIFT 28
+#define I40E_GLQF_SWAP_FLEN1_MASK (0xF << I40E_GLQF_SWAP_FLEN1_SHIFT)
+#define I40E_PFQF_CTL_0 0x001C0AC0
+#define I40E_PFQF_CTL_0_PEHSIZE_SHIFT 0
+#define I40E_PFQF_CTL_0_PEHSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PEDSIZE_SHIFT 5
+#define I40E_PFQF_CTL_0_PEDSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT 10
+#define I40E_PFQF_CTL_0_PFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT 14
+#define I40E_PFQF_CTL_0_PFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT 16
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK (0x1 << I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_FD_ENA_SHIFT 17
+#define I40E_PFQF_CTL_0_FD_ENA_MASK (0x1 << I40E_PFQF_CTL_0_FD_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT 18
+#define I40E_PFQF_CTL_0_ETYPE_ENA_MASK (0x1 << I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT 19
+#define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK (0x1 << I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT 20
+#define I40E_PFQF_CTL_0_VFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT 24
+#define I40E_PFQF_CTL_0_VFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_1 0x00245D80
+#define I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT 0
+#define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK (0x1 << I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT)
+#define I40E_PFQF_FDALLOC 0x00246280
+#define I40E_PFQF_FDALLOC_FDALLOC_SHIFT 0
+#define I40E_PFQF_FDALLOC_FDALLOC_MASK (0xFF << I40E_PFQF_FDALLOC_FDALLOC_SHIFT)
+#define I40E_PFQF_FDALLOC_FDBEST_SHIFT 8
+#define I40E_PFQF_FDALLOC_FDBEST_MASK (0xFF << I40E_PFQF_FDALLOC_FDBEST_SHIFT)
+#define I40E_PFQF_FDSTAT 0x00246380
+#define I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT 0
+#define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT)
+#define I40E_PFQF_FDSTAT_BEST_CNT_SHIFT 16
+#define I40E_PFQF_FDSTAT_BEST_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_BEST_CNT_SHIFT)
+#define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */
+#define I40E_PFQF_HENA_MAX_INDEX 1
+#define I40E_PFQF_HENA_PTYPE_ENA_SHIFT 0
+#define I40E_PFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_PFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */
+#define I40E_PFQF_HKEY_MAX_INDEX 12
+#define I40E_PFQF_HKEY_KEY_0_SHIFT 0
+#define I40E_PFQF_HKEY_KEY_0_MASK (0xFF << I40E_PFQF_HKEY_KEY_0_SHIFT)
+#define I40E_PFQF_HKEY_KEY_1_SHIFT 8
+#define I40E_PFQF_HKEY_KEY_1_MASK (0xFF << I40E_PFQF_HKEY_KEY_1_SHIFT)
+#define I40E_PFQF_HKEY_KEY_2_SHIFT 16
+#define I40E_PFQF_HKEY_KEY_2_MASK (0xFF << I40E_PFQF_HKEY_KEY_2_SHIFT)
+#define I40E_PFQF_HKEY_KEY_3_SHIFT 24
+#define I40E_PFQF_HKEY_KEY_3_MASK (0xFF << I40E_PFQF_HKEY_KEY_3_SHIFT)
+#define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */
+#define I40E_PFQF_HLUT_MAX_INDEX 127
+#define I40E_PFQF_HLUT_LUT0_SHIFT 0
+#define I40E_PFQF_HLUT_LUT0_MASK (0x3F << I40E_PFQF_HLUT_LUT0_SHIFT)
+#define I40E_PFQF_HLUT_LUT1_SHIFT 8
+#define I40E_PFQF_HLUT_LUT1_MASK (0x3F << I40E_PFQF_HLUT_LUT1_SHIFT)
+#define I40E_PFQF_HLUT_LUT2_SHIFT 16
+#define I40E_PFQF_HLUT_LUT2_MASK (0x3F << I40E_PFQF_HLUT_LUT2_SHIFT)
+#define I40E_PFQF_HLUT_LUT3_SHIFT 24
+#define I40E_PFQF_HLUT_LUT3_MASK (0x3F << I40E_PFQF_HLUT_LUT3_SHIFT)
+#define I40E_PFQF_HREGION(_i) (0x00245400 + ((_i) * 128)) /* _i=0...7 */
+#define I40E_PFQF_HREGION_MAX_INDEX 7
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
+#define I40E_PFQF_HREGION_REGION_0_SHIFT 1
+#define I40E_PFQF_HREGION_REGION_0_MASK (0x7 << I40E_PFQF_HREGION_REGION_0_SHIFT)
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
+#define I40E_PFQF_HREGION_REGION_1_SHIFT 5
+#define I40E_PFQF_HREGION_REGION_1_MASK (0x7 << I40E_PFQF_HREGION_REGION_1_SHIFT)
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
+#define I40E_PFQF_HREGION_REGION_2_SHIFT 9
+#define I40E_PFQF_HREGION_REGION_2_MASK (0x7 << I40E_PFQF_HREGION_REGION_2_SHIFT)
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
+#define I40E_PFQF_HREGION_REGION_3_SHIFT 13
+#define I40E_PFQF_HREGION_REGION_3_MASK (0x7 << I40E_PFQF_HREGION_REGION_3_SHIFT)
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
+#define I40E_PFQF_HREGION_REGION_4_SHIFT 17
+#define I40E_PFQF_HREGION_REGION_4_MASK (0x7 << I40E_PFQF_HREGION_REGION_4_SHIFT)
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
+#define I40E_PFQF_HREGION_REGION_5_SHIFT 21
+#define I40E_PFQF_HREGION_REGION_5_MASK (0x7 << I40E_PFQF_HREGION_REGION_5_SHIFT)
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
+#define I40E_PFQF_HREGION_REGION_6_SHIFT 25
+#define I40E_PFQF_HREGION_REGION_6_MASK (0x7 << I40E_PFQF_HREGION_REGION_6_SHIFT)
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
+#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
+#define I40E_PFQF_HREGION_REGION_7_SHIFT 29
+#define I40E_PFQF_HREGION_REGION_7_MASK (0x7 << I40E_PFQF_HREGION_REGION_7_SHIFT)
+#define I40E_PRTQF_CTL_0 0x00256E60
+#define I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT 0
+#define I40E_PRTQF_CTL_0_HSYM_ENA_MASK (0x1 << I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT)
+#define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */
+#define I40E_PRTQF_FD_FLXINSET_MAX_INDEX 63
+#define I40E_PRTQF_FD_FLXINSET_INSET_SHIFT 0
+#define I40E_PRTQF_FD_FLXINSET_INSET_MASK (0xFF << I40E_PRTQF_FD_FLXINSET_INSET_SHIFT)
+#define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */
+#define I40E_PRTQF_FD_MSK_MAX_INDEX 63
+#define I40E_PRTQF_FD_MSK_MASK_SHIFT 0
+#define I40E_PRTQF_FD_MSK_MASK_MASK (0xFFFF << I40E_PRTQF_FD_MSK_MASK_SHIFT)
+#define I40E_PRTQF_FD_MSK_OFFSET_SHIFT 16
+#define I40E_PRTQF_FD_MSK_OFFSET_MASK (0x3F << I40E_PRTQF_FD_MSK_OFFSET_SHIFT)
+#define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */
+#define I40E_PRTQF_FLX_PIT_MAX_INDEX 8
+#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT 0
+#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK (0x1F << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
+#define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 5
+#define I40E_PRTQF_FLX_PIT_FSIZE_MASK (0x1F << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
+#define I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT 10
+#define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK (0x3F << I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
+#define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_VFQF_HENA1_MAX_INDEX 1
+#define I40E_VFQF_HENA1_PTYPE_ENA_SHIFT 0
+#define I40E_VFQF_HENA1_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA1_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */
+#define I40E_VFQF_HKEY1_MAX_INDEX 12
+#define I40E_VFQF_HKEY1_KEY_0_SHIFT 0
+#define I40E_VFQF_HKEY1_KEY_0_MASK (0xFF << I40E_VFQF_HKEY1_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_1_SHIFT 8
+#define I40E_VFQF_HKEY1_KEY_1_MASK (0xFF << I40E_VFQF_HKEY1_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_2_SHIFT 16
+#define I40E_VFQF_HKEY1_KEY_2_MASK (0xFF << I40E_VFQF_HKEY1_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_3_SHIFT 24
+#define I40E_VFQF_HKEY1_KEY_3_MASK (0xFF << I40E_VFQF_HKEY1_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VFQF_HLUT1_MAX_INDEX 15
+#define I40E_VFQF_HLUT1_LUT0_SHIFT 0
+#define I40E_VFQF_HLUT1_LUT0_MASK (0xF << I40E_VFQF_HLUT1_LUT0_SHIFT)
+#define I40E_VFQF_HLUT1_LUT1_SHIFT 8
+#define I40E_VFQF_HLUT1_LUT1_MASK (0xF << I40E_VFQF_HLUT1_LUT1_SHIFT)
+#define I40E_VFQF_HLUT1_LUT2_SHIFT 16
+#define I40E_VFQF_HLUT1_LUT2_MASK (0xF << I40E_VFQF_HLUT1_LUT2_SHIFT)
+#define I40E_VFQF_HLUT1_LUT3_SHIFT 24
+#define I40E_VFQF_HLUT1_LUT3_MASK (0xF << I40E_VFQF_HLUT1_LUT3_SHIFT)
+#define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_VFQF_HREGION1_MAX_INDEX 7
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT 0
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_0_SHIFT 1
+#define I40E_VFQF_HREGION1_REGION_0_MASK (0x7 << I40E_VFQF_HREGION1_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT 4
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_1_SHIFT 5
+#define I40E_VFQF_HREGION1_REGION_1_MASK (0x7 << I40E_VFQF_HREGION1_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT 8
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_2_SHIFT 9
+#define I40E_VFQF_HREGION1_REGION_2_MASK (0x7 << I40E_VFQF_HREGION1_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT 12
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_3_SHIFT 13
+#define I40E_VFQF_HREGION1_REGION_3_MASK (0x7 << I40E_VFQF_HREGION1_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT 16
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_4_SHIFT 17
+#define I40E_VFQF_HREGION1_REGION_4_MASK (0x7 << I40E_VFQF_HREGION1_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT 20
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_5_SHIFT 21
+#define I40E_VFQF_HREGION1_REGION_5_MASK (0x7 << I40E_VFQF_HREGION1_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT 24
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_6_SHIFT 25
+#define I40E_VFQF_HREGION1_REGION_6_MASK (0x7 << I40E_VFQF_HREGION1_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT 28
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_7_SHIFT 29
+#define I40E_VFQF_HREGION1_REGION_7_MASK (0x7 << I40E_VFQF_HREGION1_REGION_7_SHIFT)
+#define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPQF_CTL_MAX_INDEX 127
+#define I40E_VPQF_CTL_PEHSIZE_SHIFT 0
+#define I40E_VPQF_CTL_PEHSIZE_MASK (0x1F << I40E_VPQF_CTL_PEHSIZE_SHIFT)
+#define I40E_VPQF_CTL_PEDSIZE_SHIFT 5
+#define I40E_VPQF_CTL_PEDSIZE_MASK (0x1F << I40E_VPQF_CTL_PEDSIZE_SHIFT)
+#define I40E_VPQF_CTL_FCHSIZE_SHIFT 10
+#define I40E_VPQF_CTL_FCHSIZE_MASK (0xF << I40E_VPQF_CTL_FCHSIZE_SHIFT)
+#define I40E_VPQF_CTL_FCDSIZE_SHIFT 14
+#define I40E_VPQF_CTL_FCDSIZE_MASK (0x3 << I40E_VPQF_CTL_FCDSIZE_SHIFT)
+#define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VSIQF_CTL_MAX_INDEX 383
+#define I40E_VSIQF_CTL_FCOE_ENA_SHIFT 0
+#define I40E_VSIQF_CTL_FCOE_ENA_MASK (0x1 << I40E_VSIQF_CTL_FCOE_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PETCP_ENA_SHIFT 1
+#define I40E_VSIQF_CTL_PETCP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PETCP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT 2
+#define I40E_VSIQF_CTL_PEUUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT 3
+#define I40E_VSIQF_CTL_PEMUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT 4
+#define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT 5
+#define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
+#define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSIQF_TCREGION_MAX_INDEX 3
+#define I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT 0
+#define I40E_VSIQF_TCREGION_TC_OFFSET_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_SIZE_SHIFT 9
+#define I40E_VSIQF_TCREGION_TC_SIZE_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT 16
+#define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT 25
+#define I40E_VSIQF_TCREGION_TC_SIZE2_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT)
+#define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOECRC_MAX_INDEX 143
+#define I40E_GL_FCOECRC_FCOECRC_SHIFT 0
+#define I40E_GL_FCOECRC_FCOECRC_MASK (0xFFFFFFFF << I40E_GL_FCOECRC_FCOECRC_SHIFT)
+#define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDDPC_MAX_INDEX 143
+#define I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT 0
+#define I40E_GL_FCOEDDPC_FCOEDDPC_MASK (0xFFFFFFFF << I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
+/* _i=0...143 */
+#define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFEC_MAX_INDEX 143
+#define I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT 0
+#define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT)
+#define I40E_GL_FCOEDIFRC(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFRC_MAX_INDEX 143
+#define I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT 0
+#define I40E_GL_FCOEDIFRC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT)
+#define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFTCL_MAX_INDEX 143
+#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT 0
+#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT)
+#define I40E_GL_FCOEDIXAC(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXAC_MAX_INDEX 143
+#define I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT 0
+#define I40E_GL_FCOEDIXAC_FCOEDIXAC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT)
+#define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXEC_MAX_INDEX 143
+#define I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT 0
+#define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT)
+#define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXVC_MAX_INDEX 143
+#define I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT 0
+#define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT)
+#define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCH_MAX_INDEX 143
+#define I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT 0
+#define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK (0xFFFF << I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT)
+#define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCL_MAX_INDEX 143
+#define I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT 0
+#define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT)
+#define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCH_MAX_INDEX 143
+#define I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT 0
+#define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK (0xFFFF << I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT)
+#define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCL_MAX_INDEX 143
+#define I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT 0
+#define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT)
+#define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOELAST_MAX_INDEX 143
+#define I40E_GL_FCOELAST_FCOELAST_SHIFT 0
+#define I40E_GL_FCOELAST_FCOELAST_MASK (0xFFFFFFFF << I40E_GL_FCOELAST_FCOELAST_SHIFT)
+#define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPRC_MAX_INDEX 143
+#define I40E_GL_FCOEPRC_FCOEPRC_SHIFT 0
+#define I40E_GL_FCOEPRC_FCOEPRC_MASK (0xFFFFFFFF << I40E_GL_FCOEPRC_FCOEPRC_SHIFT)
+#define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPTC_MAX_INDEX 143
+#define I40E_GL_FCOEPTC_FCOEPTC_SHIFT 0
+#define I40E_GL_FCOEPTC_FCOEPTC_MASK (0xFFFFFFFF << I40E_GL_FCOEPTC_FCOEPTC_SHIFT)
+#define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOERPDC_MAX_INDEX 143
+#define I40E_GL_FCOERPDC_FCOERPDC_SHIFT 0
+#define I40E_GL_FCOERPDC_FCOERPDC_MASK (0xFFFFFFFF << I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
+#define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCH_MAX_INDEX 3
+#define I40E_GLPRT_BPRCH_UPRCH_SHIFT 0
+#define I40E_GLPRT_BPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCL_MAX_INDEX 3
+#define I40E_GLPRT_BPRCL_UPRCH_SHIFT 0
+#define I40E_GLPRT_BPRCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPRCL_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCH_MAX_INDEX 3
+#define I40E_GLPRT_BPTCH_UPRCH_SHIFT 0
+#define I40E_GLPRT_BPTCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPTCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCL_MAX_INDEX 3
+#define I40E_GLPRT_BPTCL_UPRCH_SHIFT 0
+#define I40E_GLPRT_BPTCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPTCL_UPRCH_SHIFT)
+#define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_CRCERRS_MAX_INDEX 3
+#define I40E_GLPRT_CRCERRS_CRCERRS_SHIFT 0
+#define I40E_GLPRT_CRCERRS_CRCERRS_MASK (0xFFFFFFFF << I40E_GLPRT_CRCERRS_CRCERRS_SHIFT)
+#define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCH_MAX_INDEX 3
+#define I40E_GLPRT_GORCH_GORCH_SHIFT 0
+#define I40E_GLPRT_GORCH_GORCH_MASK (0xFFFF << I40E_GLPRT_GORCH_GORCH_SHIFT)
+#define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCL_MAX_INDEX 3
+#define I40E_GLPRT_GORCL_GORCL_SHIFT 0
+#define I40E_GLPRT_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLPRT_GORCL_GORCL_SHIFT)
+#define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCH_MAX_INDEX 3
+#define I40E_GLPRT_GOTCH_GOTCH_SHIFT 0
+#define I40E_GLPRT_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLPRT_GOTCH_GOTCH_SHIFT)
+#define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCL_MAX_INDEX 3
+#define I40E_GLPRT_GOTCL_GOTCL_SHIFT 0
+#define I40E_GLPRT_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLPRT_GOTCL_GOTCL_SHIFT)
+#define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ILLERRC_MAX_INDEX 3
+#define I40E_GLPRT_ILLERRC_ILLERRC_SHIFT 0
+#define I40E_GLPRT_ILLERRC_ILLERRC_MASK (0xFFFFFFFF << I40E_GLPRT_ILLERRC_ILLERRC_SHIFT)
+#define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LDPC_MAX_INDEX 3
+#define I40E_GLPRT_LDPC_LDPC_SHIFT 0
+#define I40E_GLPRT_LDPC_LDPC_MASK (0xFFFFFFFF << I40E_GLPRT_LDPC_LDPC_SHIFT)
+#define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFRXC_MAX_INDEX 3
+#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT 0
+#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFTXC_MAX_INDEX 3
+#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT 0
+#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT)
+#define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONRXC_MAX_INDEX 3
+#define I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT 0
+#define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT)
+#define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONTXC_MAX_INDEX 3
+#define I40E_GLPRT_LXONTXC_LXONTXC_SHIFT 0
+#define I40E_GLPRT_LXONTXC_LXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXONTXC_LXONTXC_SHIFT)
+#define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MLFC_MAX_INDEX 3
+#define I40E_GLPRT_MLFC_MLFC_SHIFT 0
+#define I40E_GLPRT_MLFC_MLFC_MASK (0xFFFFFFFF << I40E_GLPRT_MLFC_MLFC_SHIFT)
+#define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCH_MAX_INDEX 3
+#define I40E_GLPRT_MPRCH_MPRCH_SHIFT 0
+#define I40E_GLPRT_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLPRT_MPRCH_MPRCH_SHIFT)
+#define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCL_MAX_INDEX 3
+#define I40E_GLPRT_MPRCL_MPRCL_SHIFT 0
+#define I40E_GLPRT_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPRCL_MPRCL_SHIFT)
+#define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCH_MAX_INDEX 3
+#define I40E_GLPRT_MPTCH_MPTCH_SHIFT 0
+#define I40E_GLPRT_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLPRT_MPTCH_MPTCH_SHIFT)
+#define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCL_MAX_INDEX 3
+#define I40E_GLPRT_MPTCL_MPTCL_SHIFT 0
+#define I40E_GLPRT_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPTCL_MPTCL_SHIFT)
+#define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MRFC_MAX_INDEX 3
+#define I40E_GLPRT_MRFC_MRFC_SHIFT 0
+#define I40E_GLPRT_MRFC_MRFC_MASK (0xFFFFFFFF << I40E_GLPRT_MRFC_MRFC_SHIFT)
+#define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023H_MAX_INDEX 3
+#define I40E_GLPRT_PRC1023H_PRC1023H_SHIFT 0
+#define I40E_GLPRT_PRC1023H_PRC1023H_MASK (0xFFFF << I40E_GLPRT_PRC1023H_PRC1023H_SHIFT)
+#define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023L_MAX_INDEX 3
+#define I40E_GLPRT_PRC1023L_PRC1023L_SHIFT 0
+#define I40E_GLPRT_PRC1023L_PRC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1023L_PRC1023L_SHIFT)
+#define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127H_MAX_INDEX 3
+#define I40E_GLPRT_PRC127H_PRC127H_SHIFT 0
+#define I40E_GLPRT_PRC127H_PRC127H_MASK (0xFFFF << I40E_GLPRT_PRC127H_PRC127H_SHIFT)
+#define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127L_MAX_INDEX 3
+#define I40E_GLPRT_PRC127L_PRC127L_SHIFT 0
+#define I40E_GLPRT_PRC127L_PRC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC127L_PRC127L_SHIFT)
+#define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522H_MAX_INDEX 3
+#define I40E_GLPRT_PRC1522H_PRC1522H_SHIFT 0
+#define I40E_GLPRT_PRC1522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC1522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522L_MAX_INDEX 3
+#define I40E_GLPRT_PRC1522L_PRC1522L_SHIFT 0
+#define I40E_GLPRT_PRC1522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255H_MAX_INDEX 3
+#define I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT 0
+#define I40E_GLPRT_PRC255H_PRTPRC255H_MASK (0xFFFF << I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT)
+#define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255L_MAX_INDEX 3
+#define I40E_GLPRT_PRC255L_PRC255L_SHIFT 0
+#define I40E_GLPRT_PRC255L_PRC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC255L_PRC255L_SHIFT)
+#define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511H_MAX_INDEX 3
+#define I40E_GLPRT_PRC511H_PRC511H_SHIFT 0
+#define I40E_GLPRT_PRC511H_PRC511H_MASK (0xFFFF << I40E_GLPRT_PRC511H_PRC511H_SHIFT)
+#define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511L_MAX_INDEX 3
+#define I40E_GLPRT_PRC511L_PRC511L_SHIFT 0
+#define I40E_GLPRT_PRC511L_PRC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC511L_PRC511L_SHIFT)
+#define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64H_MAX_INDEX 3
+#define I40E_GLPRT_PRC64H_PRC64H_SHIFT 0
+#define I40E_GLPRT_PRC64H_PRC64H_MASK (0xFFFF << I40E_GLPRT_PRC64H_PRC64H_SHIFT)
+#define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64L_MAX_INDEX 3
+#define I40E_GLPRT_PRC64L_PRC64L_SHIFT 0
+#define I40E_GLPRT_PRC64L_PRC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC64L_PRC64L_SHIFT)
+#define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522H_MAX_INDEX 3
+#define I40E_GLPRT_PRC9522H_PRC1522H_SHIFT 0
+#define I40E_GLPRT_PRC9522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC9522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522L_MAX_INDEX 3
+#define I40E_GLPRT_PRC9522L_PRC1522L_SHIFT 0
+#define I40E_GLPRT_PRC9522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC9522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023H_MAX_INDEX 3
+#define I40E_GLPRT_PTC1023H_PTC1023H_SHIFT 0
+#define I40E_GLPRT_PTC1023H_PTC1023H_MASK (0xFFFF << I40E_GLPRT_PTC1023H_PTC1023H_SHIFT)
+#define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023L_MAX_INDEX 3
+#define I40E_GLPRT_PTC1023L_PTC1023L_SHIFT 0
+#define I40E_GLPRT_PTC1023L_PTC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1023L_PTC1023L_SHIFT)
+#define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127H_MAX_INDEX 3
+#define I40E_GLPRT_PTC127H_PTC127H_SHIFT 0
+#define I40E_GLPRT_PTC127H_PTC127H_MASK (0xFFFF << I40E_GLPRT_PTC127H_PTC127H_SHIFT)
+#define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127L_MAX_INDEX 3
+#define I40E_GLPRT_PTC127L_PTC127L_SHIFT 0
+#define I40E_GLPRT_PTC127L_PTC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC127L_PTC127L_SHIFT)
+#define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522H_MAX_INDEX 3
+#define I40E_GLPRT_PTC1522H_PTC1522H_SHIFT 0
+#define I40E_GLPRT_PTC1522H_PTC1522H_MASK (0xFFFF << I40E_GLPRT_PTC1522H_PTC1522H_SHIFT)
+#define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522L_MAX_INDEX 3
+#define I40E_GLPRT_PTC1522L_PTC1522L_SHIFT 0
+#define I40E_GLPRT_PTC1522L_PTC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1522L_PTC1522L_SHIFT)
+#define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255H_MAX_INDEX 3
+#define I40E_GLPRT_PTC255H_PTC255H_SHIFT 0
+#define I40E_GLPRT_PTC255H_PTC255H_MASK (0xFFFF << I40E_GLPRT_PTC255H_PTC255H_SHIFT)
+#define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255L_MAX_INDEX 3
+#define I40E_GLPRT_PTC255L_PTC255L_SHIFT 0
+#define I40E_GLPRT_PTC255L_PTC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC255L_PTC255L_SHIFT)
+#define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511H_MAX_INDEX 3
+#define I40E_GLPRT_PTC511H_PTC511H_SHIFT 0
+#define I40E_GLPRT_PTC511H_PTC511H_MASK (0xFFFF << I40E_GLPRT_PTC511H_PTC511H_SHIFT)
+#define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511L_MAX_INDEX 3
+#define I40E_GLPRT_PTC511L_PTC511L_SHIFT 0
+#define I40E_GLPRT_PTC511L_PTC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC511L_PTC511L_SHIFT)
+#define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64H_MAX_INDEX 3
+#define I40E_GLPRT_PTC64H_PTC64H_SHIFT 0
+#define I40E_GLPRT_PTC64H_PTC64H_MASK (0xFFFF << I40E_GLPRT_PTC64H_PTC64H_SHIFT)
+#define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64L_MAX_INDEX 3
+#define I40E_GLPRT_PTC64L_PTC64L_SHIFT 0
+#define I40E_GLPRT_PTC64L_PTC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC64L_PTC64L_SHIFT)
+#define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC9522H_MAX_INDEX 3
+#define I40E_GLPRT_PTC9522H_PTC9522H_SHIFT 0
+#define I40E_GLPRT_PTC9522H_PTC9522H_MASK (0xFFFF << I40E_GLPRT_PTC9522H_PTC9522H_SHIFT)
+#define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC9522L_MAX_INDEX 3
+#define I40E_GLPRT_PTC9522L_PTC9522L_SHIFT 0
+#define I40E_GLPRT_PTC9522L_PTC9522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC9522L_PTC9522L_SHIFT)
+#define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFRXC_MAX_INDEX 3
+#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT 0
+#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFTXC_MAX_INDEX 3
+#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT 0
+#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT)
+#define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXONRXC_MAX_INDEX 3
+#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT 0
+#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT)
+#define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXONTXC_MAX_INDEX 3
+#define I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT 0
+#define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT)
+#define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RDPC_MAX_INDEX 3
+#define I40E_GLPRT_RDPC_RDPC_SHIFT 0
+#define I40E_GLPRT_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLPRT_RDPC_RDPC_SHIFT)
+#define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RFC_MAX_INDEX 3
+#define I40E_GLPRT_RFC_RFC_SHIFT 0
+#define I40E_GLPRT_RFC_RFC_MASK (0xFFFFFFFF << I40E_GLPRT_RFC_RFC_SHIFT)
+#define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RJC_MAX_INDEX 3
+#define I40E_GLPRT_RJC_RJC_SHIFT 0
+#define I40E_GLPRT_RJC_RJC_MASK (0xFFFFFFFF << I40E_GLPRT_RJC_RJC_SHIFT)
+#define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RLEC_MAX_INDEX 3
+#define I40E_GLPRT_RLEC_RLEC_SHIFT 0
+#define I40E_GLPRT_RLEC_RLEC_MASK (0xFFFFFFFF << I40E_GLPRT_RLEC_RLEC_SHIFT)
+#define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ROC_MAX_INDEX 3
+#define I40E_GLPRT_ROC_ROC_SHIFT 0
+#define I40E_GLPRT_ROC_ROC_MASK (0xFFFFFFFF << I40E_GLPRT_ROC_ROC_SHIFT)
+#define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RUC_MAX_INDEX 3
+#define I40E_GLPRT_RUC_RUC_SHIFT 0
+#define I40E_GLPRT_RUC_RUC_MASK (0xFFFFFFFF << I40E_GLPRT_RUC_RUC_SHIFT)
+#define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RUPP_MAX_INDEX 3
+#define I40E_GLPRT_RUPP_RUPP_SHIFT 0
+#define I40E_GLPRT_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLPRT_RUPP_RUPP_SHIFT)
+#define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_RXON2OFFCNT_MAX_INDEX 3
+#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT 0
+#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK (0xFFFFFFFF << I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT)
+#define I40E_GLPRT_STDC(_i) (0x00300640 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_STDC_MAX_INDEX 3
+#define I40E_GLPRT_STDC_STDC_SHIFT 0
+#define I40E_GLPRT_STDC_STDC_MASK (0xFFFFFFFF << I40E_GLPRT_STDC_STDC_SHIFT)
+#define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDOLD_MAX_INDEX 3
+#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT 0
+#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK (0xFFFFFFFF << I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT)
+#define I40E_GLPRT_TDPC(_i) (0x00375400 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDPC_MAX_INDEX 3
+#define I40E_GLPRT_TDPC_TDPC_SHIFT 0
+#define I40E_GLPRT_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLPRT_TDPC_TDPC_SHIFT)
+#define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCH_MAX_INDEX 3
+#define I40E_GLPRT_UPRCH_UPRCH_SHIFT 0
+#define I40E_GLPRT_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_UPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCL_MAX_INDEX 3
+#define I40E_GLPRT_UPRCL_UPRCL_SHIFT 0
+#define I40E_GLPRT_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_UPRCL_UPRCL_SHIFT)
+#define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPTCH_MAX_INDEX 3
+#define I40E_GLPRT_UPTCH_UPTCH_SHIFT 0
+#define I40E_GLPRT_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLPRT_UPTCH_UPTCH_SHIFT)
+#define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPTCL_MAX_INDEX 3
+#define I40E_GLPRT_UPTCL_VUPTCH_SHIFT 0
+#define I40E_GLPRT_UPTCL_VUPTCH_MASK (0xFFFFFFFF << I40E_GLPRT_UPTCL_VUPTCH_SHIFT)
+#define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCH_MAX_INDEX 15
+#define I40E_GLSW_BPRCH_BPRCH_SHIFT 0
+#define I40E_GLSW_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLSW_BPRCH_BPRCH_SHIFT)
+#define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCL_MAX_INDEX 15
+#define I40E_GLSW_BPRCL_BPRCL_SHIFT 0
+#define I40E_GLSW_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLSW_BPRCL_BPRCL_SHIFT)
+#define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCH_MAX_INDEX 15
+#define I40E_GLSW_BPTCH_BPTCH_SHIFT 0
+#define I40E_GLSW_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLSW_BPTCH_BPTCH_SHIFT)
+#define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCL_MAX_INDEX 15
+#define I40E_GLSW_BPTCL_BPTCL_SHIFT 0
+#define I40E_GLSW_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLSW_BPTCL_BPTCL_SHIFT)
+#define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCH_MAX_INDEX 15
+#define I40E_GLSW_GORCH_GORCH_SHIFT 0
+#define I40E_GLSW_GORCH_GORCH_MASK (0xFFFF << I40E_GLSW_GORCH_GORCH_SHIFT)
+#define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCL_MAX_INDEX 15
+#define I40E_GLSW_GORCL_GORCL_SHIFT 0
+#define I40E_GLSW_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLSW_GORCL_GORCL_SHIFT)
+#define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCH_MAX_INDEX 15
+#define I40E_GLSW_GOTCH_GOTCH_SHIFT 0
+#define I40E_GLSW_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLSW_GOTCH_GOTCH_SHIFT)
+#define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCL_MAX_INDEX 15
+#define I40E_GLSW_GOTCL_GOTCL_SHIFT 0
+#define I40E_GLSW_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLSW_GOTCL_GOTCL_SHIFT)
+#define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCH_MAX_INDEX 15
+#define I40E_GLSW_MPRCH_MPRCH_SHIFT 0
+#define I40E_GLSW_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLSW_MPRCH_MPRCH_SHIFT)
+#define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCL_MAX_INDEX 15
+#define I40E_GLSW_MPRCL_MPRCL_SHIFT 0
+#define I40E_GLSW_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLSW_MPRCL_MPRCL_SHIFT)
+#define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCH_MAX_INDEX 15
+#define I40E_GLSW_MPTCH_MPTCH_SHIFT 0
+#define I40E_GLSW_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLSW_MPTCH_MPTCH_SHIFT)
+#define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCL_MAX_INDEX 15
+#define I40E_GLSW_MPTCL_MPTCL_SHIFT 0
+#define I40E_GLSW_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLSW_MPTCL_MPTCL_SHIFT)
+#define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_RUPP_MAX_INDEX 15
+#define I40E_GLSW_RUPP_RUPP_SHIFT 0
+#define I40E_GLSW_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLSW_RUPP_RUPP_SHIFT)
+#define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_TDPC_MAX_INDEX 15
+#define I40E_GLSW_TDPC_TDPC_SHIFT 0
+#define I40E_GLSW_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLSW_TDPC_TDPC_SHIFT)
+#define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCH_MAX_INDEX 15
+#define I40E_GLSW_UPRCH_UPRCH_SHIFT 0
+#define I40E_GLSW_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLSW_UPRCH_UPRCH_SHIFT)
+#define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCL_MAX_INDEX 15
+#define I40E_GLSW_UPRCL_UPRCL_SHIFT 0
+#define I40E_GLSW_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLSW_UPRCL_UPRCL_SHIFT)
+#define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPTCH_MAX_INDEX 15
+#define I40E_GLSW_UPTCH_UPTCH_SHIFT 0
+#define I40E_GLSW_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLSW_UPTCH_UPTCH_SHIFT)
+#define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPTCL_MAX_INDEX 15
+#define I40E_GLSW_UPTCL_UPTCL_SHIFT 0
+#define I40E_GLSW_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLSW_UPTCL_UPTCL_SHIFT)
+#define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCH_MAX_INDEX 383
+#define I40E_GLV_BPRCH_BPRCH_SHIFT 0
+#define I40E_GLV_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLV_BPRCH_BPRCH_SHIFT)
+#define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCL_MAX_INDEX 383
+#define I40E_GLV_BPRCL_BPRCL_SHIFT 0
+#define I40E_GLV_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLV_BPRCL_BPRCL_SHIFT)
+#define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCH_MAX_INDEX 383
+#define I40E_GLV_BPTCH_BPTCH_SHIFT 0
+#define I40E_GLV_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLV_BPTCH_BPTCH_SHIFT)
+#define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCL_MAX_INDEX 383
+#define I40E_GLV_BPTCL_BPTCL_SHIFT 0
+#define I40E_GLV_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLV_BPTCL_BPTCL_SHIFT)
+#define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCH_MAX_INDEX 383
+#define I40E_GLV_GORCH_GORCH_SHIFT 0
+#define I40E_GLV_GORCH_GORCH_MASK (0xFFFF << I40E_GLV_GORCH_GORCH_SHIFT)
+#define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCL_MAX_INDEX 383
+#define I40E_GLV_GORCL_GORCL_SHIFT 0
+#define I40E_GLV_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLV_GORCL_GORCL_SHIFT)
+#define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCH_MAX_INDEX 383
+#define I40E_GLV_GOTCH_GOTCH_SHIFT 0
+#define I40E_GLV_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLV_GOTCH_GOTCH_SHIFT)
+#define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCL_MAX_INDEX 383
+#define I40E_GLV_GOTCL_GOTCL_SHIFT 0
+#define I40E_GLV_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLV_GOTCL_GOTCL_SHIFT)
+#define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCH_MAX_INDEX 383
+#define I40E_GLV_MPRCH_MPRCH_SHIFT 0
+#define I40E_GLV_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLV_MPRCH_MPRCH_SHIFT)
+#define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCL_MAX_INDEX 383
+#define I40E_GLV_MPRCL_MPRCL_SHIFT 0
+#define I40E_GLV_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLV_MPRCL_MPRCL_SHIFT)
+#define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCH_MAX_INDEX 383
+#define I40E_GLV_MPTCH_MPTCH_SHIFT 0
+#define I40E_GLV_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLV_MPTCH_MPTCH_SHIFT)
+#define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCL_MAX_INDEX 383
+#define I40E_GLV_MPTCL_MPTCL_SHIFT 0
+#define I40E_GLV_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLV_MPTCL_MPTCL_SHIFT)
+#define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_RDPC_MAX_INDEX 383
+#define I40E_GLV_RDPC_RDPC_SHIFT 0
+#define I40E_GLV_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLV_RDPC_RDPC_SHIFT)
+#define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_RUPP_MAX_INDEX 383
+#define I40E_GLV_RUPP_RUPP_SHIFT 0
+#define I40E_GLV_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLV_RUPP_RUPP_SHIFT)
+#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 8)) /* _i=0...383 */
+#define I40E_GLV_TEPC_MAX_INDEX 383
+#define I40E_GLV_TEPC_TEPC_SHIFT 0
+#define I40E_GLV_TEPC_TEPC_MASK (0xFFFFFFFF << I40E_GLV_TEPC_TEPC_SHIFT)
+#define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCH_MAX_INDEX 383
+#define I40E_GLV_UPRCH_UPRCH_SHIFT 0
+#define I40E_GLV_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLV_UPRCH_UPRCH_SHIFT)
+#define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCL_MAX_INDEX 383
+#define I40E_GLV_UPRCL_UPRCL_SHIFT 0
+#define I40E_GLV_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLV_UPRCL_UPRCL_SHIFT)
+#define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPTCH_MAX_INDEX 383
+#define I40E_GLV_UPTCH_GLVUPTCH_SHIFT 0
+#define I40E_GLV_UPTCH_GLVUPTCH_MASK (0xFFFF << I40E_GLV_UPTCH_GLVUPTCH_SHIFT)
+#define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPTCL_MAX_INDEX 383
+#define I40E_GLV_UPTCL_UPTCL_SHIFT 0
+#define I40E_GLV_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLV_UPTCL_UPTCL_SHIFT)
+#define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCH_MAX_INDEX 7
+#define I40E_GLVEBTC_RBCH_TCBCH_SHIFT 0
+#define I40E_GLVEBTC_RBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_RBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCL_MAX_INDEX 7
+#define I40E_GLVEBTC_RBCL_TCBCL_SHIFT 0
+#define I40E_GLVEBTC_RBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCH_MAX_INDEX 7
+#define I40E_GLVEBTC_RPCH_TCPCH_SHIFT 0
+#define I40E_GLVEBTC_RPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_RPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCL_MAX_INDEX 7
+#define I40E_GLVEBTC_RPCL_TCPCL_SHIFT 0
+#define I40E_GLVEBTC_RPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RPCL_TCPCL_SHIFT)
+#define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCH_MAX_INDEX 7
+#define I40E_GLVEBTC_TBCH_TCBCH_SHIFT 0
+#define I40E_GLVEBTC_TBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_TBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCL_MAX_INDEX 7
+#define I40E_GLVEBTC_TBCL_TCBCL_SHIFT 0
+#define I40E_GLVEBTC_TBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TPCH_MAX_INDEX 7
+#define I40E_GLVEBTC_TPCH_TCPCH_SHIFT 0
+#define I40E_GLVEBTC_TPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_TPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TPCL_MAX_INDEX 7
+#define I40E_GLVEBTC_TPCL_TCPCL_SHIFT 0
+#define I40E_GLVEBTC_TPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TPCL_TCPCL_SHIFT)
+#define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCH_MAX_INDEX 127
+#define I40E_GLVEBVL_BPCH_VLBPCH_SHIFT 0
+#define I40E_GLVEBVL_BPCH_VLBPCH_MASK (0xFFFF << I40E_GLVEBVL_BPCH_VLBPCH_SHIFT)
+#define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCL_MAX_INDEX 127
+#define I40E_GLVEBVL_BPCL_VLBPCL_SHIFT 0
+#define I40E_GLVEBVL_BPCL_VLBPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_BPCL_VLBPCL_SHIFT)
+#define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCH_MAX_INDEX 127
+#define I40E_GLVEBVL_GORCH_VLBCH_SHIFT 0
+#define I40E_GLVEBVL_GORCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GORCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCL_MAX_INDEX 127
+#define I40E_GLVEBVL_GORCL_VLBCL_SHIFT 0
+#define I40E_GLVEBVL_GORCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GORCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCH_MAX_INDEX 127
+#define I40E_GLVEBVL_GOTCH_VLBCH_SHIFT 0
+#define I40E_GLVEBVL_GOTCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GOTCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCL_MAX_INDEX 127
+#define I40E_GLVEBVL_GOTCL_VLBCL_SHIFT 0
+#define I40E_GLVEBVL_GOTCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GOTCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCH_MAX_INDEX 127
+#define I40E_GLVEBVL_MPCH_VLMPCH_SHIFT 0
+#define I40E_GLVEBVL_MPCH_VLMPCH_MASK (0xFFFF << I40E_GLVEBVL_MPCH_VLMPCH_SHIFT)
+#define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCL_MAX_INDEX 127
+#define I40E_GLVEBVL_MPCL_VLMPCL_SHIFT 0
+#define I40E_GLVEBVL_MPCL_VLMPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_MPCL_VLMPCL_SHIFT)
+#define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_UPCH_MAX_INDEX 127
+#define I40E_GLVEBVL_UPCH_VLUPCH_SHIFT 0
+#define I40E_GLVEBVL_UPCH_VLUPCH_MASK (0xFFFF << I40E_GLVEBVL_UPCH_VLUPCH_SHIFT)
+#define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_UPCL_MAX_INDEX 127
+#define I40E_GLVEBVL_UPCL_VLUPCL_SHIFT 0
+#define I40E_GLVEBVL_UPCL_VLUPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_UPCL_VLUPCL_SHIFT)
+#define I40E_GL_MTG_FLU_MSK_H 0x00269F4C
+#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT 0
+#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK (0xFFFF << I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT)
+#define I40E_GL_MTG_FLU_MSK_L 0x00269F44
+#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT 0
+#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_MASK (0xFFFFFFFF << I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT)
+#define I40E_GL_SWR_DEF_ACT(_i) (0x0026CF00 + ((_i) * 4)) /* _i=0...25 */
+#define I40E_GL_SWR_DEF_ACT_MAX_INDEX 25
+#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT 0
+#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT)
+#define I40E_GL_SWR_DEF_ACT_EN 0x0026CF84
+#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT 0
+#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT)
+#define I40E_PRT_MSCCNT 0x00256BA0
+#define I40E_PRT_MSCCNT_CCOUNT_SHIFT 0
+#define I40E_PRT_MSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_MSCCNT_CCOUNT_SHIFT)
+#define I40E_PRT_SCSTS 0x00256C20
+#define I40E_PRT_SCSTS_BSCA_SHIFT 0
+#define I40E_PRT_SCSTS_BSCA_MASK (0x1 << I40E_PRT_SCSTS_BSCA_SHIFT)
+#define I40E_PRT_SCSTS_BSCAP_SHIFT 1
+#define I40E_PRT_SCSTS_BSCAP_MASK (0x1 << I40E_PRT_SCSTS_BSCAP_SHIFT)
+#define I40E_PRT_SCSTS_MSCA_SHIFT 2
+#define I40E_PRT_SCSTS_MSCA_MASK (0x1 << I40E_PRT_SCSTS_MSCA_SHIFT)
+#define I40E_PRT_SCSTS_MSCAP_SHIFT 3
+#define I40E_PRT_SCSTS_MSCAP_MASK (0x1 << I40E_PRT_SCSTS_MSCAP_SHIFT)
+#define I40E_PRT_SWT_BSCCNT 0x00256C60
+#define I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT 0
+#define I40E_PRT_SWT_BSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT)
+#define I40E_PRTTSYN_ADJ 0x001E4280
+#define I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT 0
+#define I40E_PRTTSYN_ADJ_TSYNADJ_MASK (0x7FFFFFFF << I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT)
+#define I40E_PRTTSYN_ADJ_SIGN_SHIFT 31
+#define I40E_PRTTSYN_ADJ_SIGN_MASK (0x1 << I40E_PRTTSYN_ADJ_SIGN_SHIFT)
+#define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_0_MAX_INDEX 1
+#define I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT 0
+#define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT 1
+#define I40E_PRTTSYN_AUX_0_OUTMOD_MASK (0x3 << I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT 3
+#define I40E_PRTTSYN_AUX_0_OUTLVL_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_0_PULSEW_SHIFT 8
+#define I40E_PRTTSYN_AUX_0_PULSEW_MASK (0xF << I40E_PRTTSYN_AUX_0_PULSEW_SHIFT)
+#define I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT 16
+#define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK (0x3 << I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_1_MAX_INDEX 1
+#define I40E_PRTTSYN_AUX_1_INSTNT_SHIFT 0
+#define I40E_PRTTSYN_AUX_1_INSTNT_MASK (0x1 << I40E_PRTTSYN_AUX_1_INSTNT_SHIFT)
+#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT 1
+#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK (0x1 << I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT)
+#define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_CLKO_MAX_INDEX 1
+#define I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT 0
+#define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK (0xFFFFFFFF << I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT)
+#define I40E_PRTTSYN_CTL0 0x001E4200
+#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT 0
+#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK (0x1 << I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT)
+#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT 1
+#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT 2
+#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT 3
+#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_PF_ID_SHIFT 8
+#define I40E_PRTTSYN_CTL0_PF_ID_MASK (0xF << I40E_PRTTSYN_CTL0_PF_ID_SHIFT)
+#define I40E_PRTTSYN_CTL0_TSYNACT_SHIFT 12
+#define I40E_PRTTSYN_CTL0_TSYNACT_MASK (0x3 << I40E_PRTTSYN_CTL0_TSYNACT_SHIFT)
+#define I40E_PRTTSYN_CTL0_TSYNENA_SHIFT 31
+#define I40E_PRTTSYN_CTL0_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_CTL1 0x00085020
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT 0
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT 8
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT 16
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT 20
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT 24
+#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK (0x3 << I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
+#define I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT 26
+#define I40E_PRTTSYN_CTL1_UDP_ENA_MASK (0x3 << I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL1_TSYNENA_SHIFT 31
+#define I40E_PRTTSYN_CTL1_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL1_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_EVNT_H_MAX_INDEX 1
+#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT 0
+#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT)
+#define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_EVNT_L_MAX_INDEX 1
+#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT 0
+#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT)
+#define I40E_PRTTSYN_INC_H 0x001E4060
+#define I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT 0
+#define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK (0x3F << I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT)
+#define I40E_PRTTSYN_INC_L 0x001E4040
+#define I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT 0
+#define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT)
+#define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_RXTIME_H_MAX_INDEX 3
+#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT 0
+#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_RXTIME_L_MAX_INDEX 3
+#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT 0
+#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT)
+#define I40E_PRTTSYN_STAT_0 0x001E4220
+#define I40E_PRTTSYN_STAT_0_EVENT0_SHIFT 0
+#define I40E_PRTTSYN_STAT_0_EVENT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_EVENT1_SHIFT 1
+#define I40E_PRTTSYN_STAT_0_EVENT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT0_SHIFT 2
+#define I40E_PRTTSYN_STAT_0_TGT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT1_SHIFT 3
+#define I40E_PRTTSYN_STAT_0_TGT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TXTIME_SHIFT 4
+#define I40E_PRTTSYN_STAT_0_TXTIME_MASK (0x1 << I40E_PRTTSYN_STAT_0_TXTIME_SHIFT)
+#define I40E_PRTTSYN_STAT_1 0x00085140
+#define I40E_PRTTSYN_STAT_1_RXT0_SHIFT 0
+#define I40E_PRTTSYN_STAT_1_RXT0_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT0_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT1_SHIFT 1
+#define I40E_PRTTSYN_STAT_1_RXT1_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT1_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT2_SHIFT 2
+#define I40E_PRTTSYN_STAT_1_RXT2_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT2_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT3_SHIFT 3
+#define I40E_PRTTSYN_STAT_1_RXT3_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT3_SHIFT)
+#define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_TGT_H_MAX_INDEX 1
+#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT 0
+#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT)
+#define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_TGT_L_MAX_INDEX 1
+#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT 0
+#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT)
+#define I40E_PRTTSYN_TIME_H 0x001E4120
+#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT 0
+#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT)
+#define I40E_PRTTSYN_TIME_L 0x001E4100
+#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT 0
+#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT)
+#define I40E_PRTTSYN_TXTIME_H 0x001E41E0
+#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT 0
+#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_TXTIME_L 0x001E41C0
+#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT 0
+#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT)
+#define I40E_GLSCD_QUANTA 0x000B2080
+#define I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT 0
+#define I40E_GLSCD_QUANTA_TSCDQUANTA_MASK (0x7 << I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT)
+#define I40E_GL_MDET_RX 0x0012A510
+#define I40E_GL_MDET_RX_FUNCTION_SHIFT 0
+#define I40E_GL_MDET_RX_FUNCTION_MASK (0xFF << I40E_GL_MDET_RX_FUNCTION_SHIFT)
+#define I40E_GL_MDET_RX_EVENT_SHIFT 8
+#define I40E_GL_MDET_RX_EVENT_MASK (0x1FF << I40E_GL_MDET_RX_EVENT_SHIFT)
+#define I40E_GL_MDET_RX_QUEUE_SHIFT 17
+#define I40E_GL_MDET_RX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_RX_QUEUE_SHIFT)
+#define I40E_GL_MDET_RX_VALID_SHIFT 31
+#define I40E_GL_MDET_RX_VALID_MASK (0x1 << I40E_GL_MDET_RX_VALID_SHIFT)
+#define I40E_GL_MDET_TX 0x000E6480
+#define I40E_GL_MDET_TX_FUNCTION_SHIFT 0
+#define I40E_GL_MDET_TX_FUNCTION_MASK (0xFF << I40E_GL_MDET_TX_FUNCTION_SHIFT)
+#define I40E_GL_MDET_TX_EVENT_SHIFT 8
+#define I40E_GL_MDET_TX_EVENT_MASK (0x1FF << I40E_GL_MDET_TX_EVENT_SHIFT)
+#define I40E_GL_MDET_TX_QUEUE_SHIFT 17
+#define I40E_GL_MDET_TX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_TX_QUEUE_SHIFT)
+#define I40E_GL_MDET_TX_VALID_SHIFT 31
+#define I40E_GL_MDET_TX_VALID_MASK (0x1 << I40E_GL_MDET_TX_VALID_SHIFT)
+#define I40E_PF_MDET_RX 0x0012A400
+#define I40E_PF_MDET_RX_VALID_SHIFT 0
+#define I40E_PF_MDET_RX_VALID_MASK (0x1 << I40E_PF_MDET_RX_VALID_SHIFT)
+#define I40E_PF_MDET_TX 0x000E6400
+#define I40E_PF_MDET_TX_VALID_SHIFT 0
+#define I40E_PF_MDET_TX_VALID_MASK (0x1 << I40E_PF_MDET_TX_VALID_SHIFT)
+#define I40E_PF_VT_PFALLOC 0x001C0500
+#define I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT 0
+#define I40E_PF_VT_PFALLOC_FIRSTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_LASTVF_SHIFT 8
+#define I40E_PF_VT_PFALLOC_LASTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_LASTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_VALID_SHIFT 31
+#define I40E_PF_VT_PFALLOC_VALID_MASK (0x1 << I40E_PF_VT_PFALLOC_VALID_SHIFT)
+#define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VP_MDET_RX_MAX_INDEX 127
+#define I40E_VP_MDET_RX_VALID_SHIFT 0
+#define I40E_VP_MDET_RX_VALID_MASK (0x1 << I40E_VP_MDET_RX_VALID_SHIFT)
+#define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VP_MDET_TX_MAX_INDEX 127
+#define I40E_VP_MDET_TX_VALID_SHIFT 0
+#define I40E_VP_MDET_TX_VALID_MASK (0x1 << I40E_VP_MDET_TX_VALID_SHIFT)
+#define I40E_GLPM_WUMC 0x0006C800
+#define I40E_GLPM_WUMC_NOTCO_SHIFT 0
+#define I40E_GLPM_WUMC_NOTCO_MASK (0x1 << I40E_GLPM_WUMC_NOTCO_SHIFT)
+#define I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT 1
+#define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK (0x1 << I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT)
+#define I40E_GLPM_WUMC_ROL_MODE_SHIFT 2
+#define I40E_GLPM_WUMC_ROL_MODE_MASK (0x1 << I40E_GLPM_WUMC_ROL_MODE_SHIFT)
+#define I40E_GLPM_WUMC_RESERVED_4_SHIFT 3
+#define I40E_GLPM_WUMC_RESERVED_4_MASK (0x1FFF << I40E_GLPM_WUMC_RESERVED_4_SHIFT)
+#define I40E_GLPM_WUMC_MNG_WU_PF_SHIFT 16
+#define I40E_GLPM_WUMC_MNG_WU_PF_MASK (0xFFFF << I40E_GLPM_WUMC_MNG_WU_PF_SHIFT)
+#define I40E_PFPM_APM 0x000B8080
+#define I40E_PFPM_APM_APME_SHIFT 0
+#define I40E_PFPM_APM_APME_MASK (0x1 << I40E_PFPM_APM_APME_SHIFT)
+#define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */
+#define I40E_PFPM_FHFT_LENGTH_MAX_INDEX 7
+#define I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT 0
+#define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK (0xFF << I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PFPM_WUC 0x0006B200
+#define I40E_PFPM_WUC_EN_APM_D0_SHIFT 5
+#define I40E_PFPM_WUC_EN_APM_D0_MASK (0x1 << I40E_PFPM_WUC_EN_APM_D0_SHIFT)
+#define I40E_PFPM_WUFC 0x0006B400
+#define I40E_PFPM_WUFC_LNKC_SHIFT 0
+#define I40E_PFPM_WUFC_LNKC_MASK (0x1 << I40E_PFPM_WUFC_LNKC_SHIFT)
+#define I40E_PFPM_WUFC_MAG_SHIFT 1
+#define I40E_PFPM_WUFC_MAG_MASK (0x1 << I40E_PFPM_WUFC_MAG_SHIFT)
+#define I40E_PFPM_WUFC_MNG_SHIFT 3
+#define I40E_PFPM_WUFC_MNG_MASK (0x1 << I40E_PFPM_WUFC_MNG_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_ACT_SHIFT 4
+#define I40E_PFPM_WUFC_FLX0_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX0_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_ACT_SHIFT 5
+#define I40E_PFPM_WUFC_FLX1_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX1_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_ACT_SHIFT 6
+#define I40E_PFPM_WUFC_FLX2_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX2_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_ACT_SHIFT 7
+#define I40E_PFPM_WUFC_FLX3_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX3_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_ACT_SHIFT 8
+#define I40E_PFPM_WUFC_FLX4_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX4_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_ACT_SHIFT 9
+#define I40E_PFPM_WUFC_FLX5_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX5_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_ACT_SHIFT 10
+#define I40E_PFPM_WUFC_FLX6_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX6_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_ACT_SHIFT 11
+#define I40E_PFPM_WUFC_FLX7_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX7_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_SHIFT 16
+#define I40E_PFPM_WUFC_FLX0_MASK (0x1 << I40E_PFPM_WUFC_FLX0_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_SHIFT 17
+#define I40E_PFPM_WUFC_FLX1_MASK (0x1 << I40E_PFPM_WUFC_FLX1_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_SHIFT 18
+#define I40E_PFPM_WUFC_FLX2_MASK (0x1 << I40E_PFPM_WUFC_FLX2_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_SHIFT 19
+#define I40E_PFPM_WUFC_FLX3_MASK (0x1 << I40E_PFPM_WUFC_FLX3_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_SHIFT 20
+#define I40E_PFPM_WUFC_FLX4_MASK (0x1 << I40E_PFPM_WUFC_FLX4_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_SHIFT 21
+#define I40E_PFPM_WUFC_FLX5_MASK (0x1 << I40E_PFPM_WUFC_FLX5_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_SHIFT 22
+#define I40E_PFPM_WUFC_FLX6_MASK (0x1 << I40E_PFPM_WUFC_FLX6_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_SHIFT 23
+#define I40E_PFPM_WUFC_FLX7_MASK (0x1 << I40E_PFPM_WUFC_FLX7_SHIFT)
+#define I40E_PFPM_WUFC_FW_RST_WK_SHIFT 31
+#define I40E_PFPM_WUFC_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUFC_FW_RST_WK_SHIFT)
+#define I40E_PFPM_WUS 0x0006B600
+#define I40E_PFPM_WUS_LNKC_SHIFT 0
+#define I40E_PFPM_WUS_LNKC_MASK (0x1 << I40E_PFPM_WUS_LNKC_SHIFT)
+#define I40E_PFPM_WUS_MAG_SHIFT 1
+#define I40E_PFPM_WUS_MAG_MASK (0x1 << I40E_PFPM_WUS_MAG_SHIFT)
+#define I40E_PFPM_WUS_PME_STATUS_SHIFT 2
+#define I40E_PFPM_WUS_PME_STATUS_MASK (0x1 << I40E_PFPM_WUS_PME_STATUS_SHIFT)
+#define I40E_PFPM_WUS_MNG_SHIFT 3
+#define I40E_PFPM_WUS_MNG_MASK (0x1 << I40E_PFPM_WUS_MNG_SHIFT)
+#define I40E_PFPM_WUS_FLX0_SHIFT 16
+#define I40E_PFPM_WUS_FLX0_MASK (0x1 << I40E_PFPM_WUS_FLX0_SHIFT)
+#define I40E_PFPM_WUS_FLX1_SHIFT 17
+#define I40E_PFPM_WUS_FLX1_MASK (0x1 << I40E_PFPM_WUS_FLX1_SHIFT)
+#define I40E_PFPM_WUS_FLX2_SHIFT 18
+#define I40E_PFPM_WUS_FLX2_MASK (0x1 << I40E_PFPM_WUS_FLX2_SHIFT)
+#define I40E_PFPM_WUS_FLX3_SHIFT 19
+#define I40E_PFPM_WUS_FLX3_MASK (0x1 << I40E_PFPM_WUS_FLX3_SHIFT)
+#define I40E_PFPM_WUS_FLX4_SHIFT 20
+#define I40E_PFPM_WUS_FLX4_MASK (0x1 << I40E_PFPM_WUS_FLX4_SHIFT)
+#define I40E_PFPM_WUS_FLX5_SHIFT 21
+#define I40E_PFPM_WUS_FLX5_MASK (0x1 << I40E_PFPM_WUS_FLX5_SHIFT)
+#define I40E_PFPM_WUS_FLX6_SHIFT 22
+#define I40E_PFPM_WUS_FLX6_MASK (0x1 << I40E_PFPM_WUS_FLX6_SHIFT)
+#define I40E_PFPM_WUS_FLX7_SHIFT 23
+#define I40E_PFPM_WUS_FLX7_MASK (0x1 << I40E_PFPM_WUS_FLX7_SHIFT)
+#define I40E_PFPM_WUS_FW_RST_WK_SHIFT 31
+#define I40E_PFPM_WUS_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUS_FW_RST_WK_SHIFT)
+#define I40E_PRTPM_FHFHR 0x0006C000
+#define I40E_PRTPM_FHFHR_UNICAST_SHIFT 0
+#define I40E_PRTPM_FHFHR_UNICAST_MASK (0x1 << I40E_PRTPM_FHFHR_UNICAST_SHIFT)
+#define I40E_PRTPM_FHFHR_MULTICAST_SHIFT 1
+#define I40E_PRTPM_FHFHR_MULTICAST_MASK (0x1 << I40E_PRTPM_FHFHR_MULTICAST_SHIFT)
+#define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_SAH_MAX_INDEX 3
+#define I40E_PRTPM_SAH_PFPM_SAH_SHIFT 0
+#define I40E_PRTPM_SAH_PFPM_SAH_MASK (0xFFFF << I40E_PRTPM_SAH_PFPM_SAH_SHIFT)
+#define I40E_PRTPM_SAH_PF_NUM_SHIFT 26
+#define I40E_PRTPM_SAH_PF_NUM_MASK (0xF << I40E_PRTPM_SAH_PF_NUM_SHIFT)
+#define I40E_PRTPM_SAH_MC_MAG_EN_SHIFT 30
+#define I40E_PRTPM_SAH_MC_MAG_EN_MASK (0x1 << I40E_PRTPM_SAH_MC_MAG_EN_SHIFT)
+#define I40E_PRTPM_SAH_AV_SHIFT 31
+#define I40E_PRTPM_SAH_AV_MASK (0x1 << I40E_PRTPM_SAH_AV_SHIFT)
+#define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_SAL_MAX_INDEX 3
+#define I40E_PRTPM_SAL_PFPM_SAL_SHIFT 0
+#define I40E_PRTPM_SAL_PFPM_SAL_MASK (0xFFFFFFFF << I40E_PRTPM_SAL_PFPM_SAL_SHIFT)
+#define I40E_VF_ARQBAH1 0x00006000
+#define I40E_VF_ARQBAH1_ARQBAH_SHIFT 0
+#define I40E_VF_ARQBAH1_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH1_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL1 0x00006C00
+#define I40E_VF_ARQBAL1_ARQBAL_SHIFT 0
+#define I40E_VF_ARQBAL1_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL1_ARQBAL_SHIFT)
+#define I40E_VF_ARQH1 0x00007400
+#define I40E_VF_ARQH1_ARQH_SHIFT 0
+#define I40E_VF_ARQH1_ARQH_MASK (0x3FF << I40E_VF_ARQH1_ARQH_SHIFT)
+#define I40E_VF_ARQLEN1 0x00008000
+#define I40E_VF_ARQLEN1_ARQLEN_SHIFT 0
+#define I40E_VF_ARQLEN1_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN1_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN1_ARQVFE_SHIFT 28
+#define I40E_VF_ARQLEN1_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN1_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN1_ARQOVFL_SHIFT 29
+#define I40E_VF_ARQLEN1_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN1_ARQCRIT_SHIFT 30
+#define I40E_VF_ARQLEN1_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN1_ARQENABLE_SHIFT 31
+#define I40E_VF_ARQLEN1_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT1 0x00007000
+#define I40E_VF_ARQT1_ARQT_SHIFT 0
+#define I40E_VF_ARQT1_ARQT_MASK (0x3FF << I40E_VF_ARQT1_ARQT_SHIFT)
+#define I40E_VF_ATQBAH1 0x00007800
+#define I40E_VF_ATQBAH1_ATQBAH_SHIFT 0
+#define I40E_VF_ATQBAH1_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH1_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL1 0x00007C00
+#define I40E_VF_ATQBAL1_ATQBAL_SHIFT 0
+#define I40E_VF_ATQBAL1_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL1_ATQBAL_SHIFT)
+#define I40E_VF_ATQH1 0x00006400
+#define I40E_VF_ATQH1_ATQH_SHIFT 0
+#define I40E_VF_ATQH1_ATQH_MASK (0x3FF << I40E_VF_ATQH1_ATQH_SHIFT)
+#define I40E_VF_ATQLEN1 0x00006800
+#define I40E_VF_ATQLEN1_ATQLEN_SHIFT 0
+#define I40E_VF_ATQLEN1_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN1_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN1_ATQVFE_SHIFT 28
+#define I40E_VF_ATQLEN1_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN1_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN1_ATQOVFL_SHIFT 29
+#define I40E_VF_ATQLEN1_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN1_ATQCRIT_SHIFT 30
+#define I40E_VF_ATQLEN1_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN1_ATQENABLE_SHIFT 31
+#define I40E_VF_ATQLEN1_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT1 0x00008400
+#define I40E_VF_ATQT1_ATQT_SHIFT 0
+#define I40E_VF_ATQT1_ATQT_MASK (0x3FF << I40E_VF_ATQT1_ATQT_SHIFT)
+#define I40E_VFGEN_RSTAT 0x00008800
+#define I40E_VFGEN_RSTAT_VFR_STATE_SHIFT 0
+#define I40E_VFGEN_RSTAT_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
+#define I40E_VFINT_DYN_CTL01 0x00005C00
+#define I40E_VFINT_DYN_CTL01_INTENA_SHIFT 0
+#define I40E_VFINT_DYN_CTL01_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT 1
+#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT 2
+#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT 3
+#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT 5
+#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT 24
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT 25
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT 31
+#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4))
+#define I40E_VFINT_DYN_CTLN1_MAX_INDEX 15
+#define I40E_VFINT_DYN_CTLN1_INTENA_SHIFT 0
+#define I40E_VFINT_DYN_CTLN1_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT 1
+#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT 2
+#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT 3
+#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT 5
+#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT 24
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT 25
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT 31
+#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0_ENA1 0x00005000
+#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT 25
+#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT 30
+#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_RSVD_SHIFT 31
+#define I40E_VFINT_ICR0_ENA1_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
+#define I40E_VFINT_ICR01 0x00004800
+#define I40E_VFINT_ICR01_INTEVENT_SHIFT 0
+#define I40E_VFINT_ICR01_INTEVENT_MASK (0x1 << I40E_VFINT_ICR01_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_0_SHIFT 1
+#define I40E_VFINT_ICR01_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_1_SHIFT 2
+#define I40E_VFINT_ICR01_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_2_SHIFT 3
+#define I40E_VFINT_ICR01_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_3_SHIFT 4
+#define I40E_VFINT_ICR01_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT 25
+#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR01_ADMINQ_SHIFT 30
+#define I40E_VFINT_ICR01_ADMINQ_MASK (0x1 << I40E_VFINT_ICR01_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR01_SWINT_SHIFT 31
+#define I40E_VFINT_ICR01_SWINT_MASK (0x1 << I40E_VFINT_ICR01_SWINT_SHIFT)
+#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */
+#define I40E_VFINT_ITR01_MAX_INDEX 2
+#define I40E_VFINT_ITR01_INTERVAL_SHIFT 0
+#define I40E_VFINT_ITR01_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR01_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4))
+#define I40E_VFINT_ITRN1_MAX_INDEX 2
+#define I40E_VFINT_ITRN1_INTERVAL_SHIFT 0
+#define I40E_VFINT_ITRN1_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN1_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL01 0x00005400
+#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT 2
+#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
+#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_QRX_TAIL1_MAX_INDEX 15
+#define I40E_QRX_TAIL1_TAIL_SHIFT 0
+#define I40E_QRX_TAIL1_TAIL_MASK (0x1FFF << I40E_QRX_TAIL1_TAIL_SHIFT)
+#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_QTX_TAIL1_MAX_INDEX 15
+#define I40E_QTX_TAIL1_TAIL_SHIFT 0
+#define I40E_QTX_TAIL1_TAIL_MASK (0x1FFF << I40E_QTX_TAIL1_TAIL_SHIFT)
+#define I40E_VFMSIX_PBA 0x00002000
+#define I40E_VFMSIX_PBA_PENBIT_SHIFT 0
+#define I40E_VFMSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TADD_MAX_INDEX 16
+#define I40E_VFMSIX_TADD_MSIXTADD10_SHIFT 0
+#define I40E_VFMSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD_MSIXTADD_SHIFT 2
+#define I40E_VFMSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TMSG_MAX_INDEX 16
+#define I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT 0
+#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TUADD_MAX_INDEX 16
+#define I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT 0
+#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TVCTRL_MAX_INDEX 16
+#define I40E_VFMSIX_TVCTRL_MASK_SHIFT 0
+#define I40E_VFMSIX_TVCTRL_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFCM_PE_ERRDATA 0x0000DC00
+#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
+#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
+#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT 8
+#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO 0x0000D800
+#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
+#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
+#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
+#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
+#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
+#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_VFPE_AEQALLOC1 0x0000A400
+#define I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT 0
+#define I40E_VFPE_AEQALLOC1_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT)
+#define I40E_VFPE_CCQPHIGH1 0x00009800
+#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT 0
+#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT)
+#define I40E_VFPE_CCQPLOW1 0x0000AC00
+#define I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT 0
+#define I40E_VFPE_CCQPLOW1_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT)
+#define I40E_VFPE_CCQPSTATUS1 0x0000B800
+#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT 0
+#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT)
+#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT 31
+#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT)
+#define I40E_VFPE_CQACK1 0x0000B000
+#define I40E_VFPE_CQACK1_PECQID_SHIFT 0
+#define I40E_VFPE_CQACK1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK1_PECQID_SHIFT)
+#define I40E_VFPE_CQARM1 0x0000B400
+#define I40E_VFPE_CQARM1_PECQID_SHIFT 0
+#define I40E_VFPE_CQARM1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM1_PECQID_SHIFT)
+#define I40E_VFPE_CQPDB1 0x0000BC00
+#define I40E_VFPE_CQPDB1_WQHEAD_SHIFT 0
+#define I40E_VFPE_CQPDB1_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB1_WQHEAD_SHIFT)
+#define I40E_VFPE_CQPERRCODES1 0x00009C00
+#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT 0
+#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT)
+#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT 16
+#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT)
+#define I40E_VFPE_CQPTAIL1 0x0000A000
+#define I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT 0
+#define I40E_VFPE_CQPTAIL1_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT)
+#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT 31
+#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT)
+#define I40E_VFPE_IPCONFIG01 0x00008C00
+#define I40E_VFPE_IPCONFIG01_PEIPID_SHIFT 0
+#define I40E_VFPE_IPCONFIG01_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG01_PEIPID_SHIFT)
+#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT 16
+#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT)
+#define I40E_VFPE_MRTEIDXMASK1 0x00009000
+#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT 0
+#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT)
+#define I40E_VFPE_RCVUNEXPECTEDERROR1 0x00009400
+#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT 0
+#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT)
+#define I40E_VFPE_TCPNOWTIMER1 0x0000A800
+#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT 0
+#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT)
+#define I40E_VFPE_WQEALLOC1 0x0000C000
+#define I40E_VFPE_WQEALLOC1_PEQPID_SHIFT 0
+#define I40E_VFPE_WQEALLOC1_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC1_PEQPID_SHIFT)
+#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT 20
+#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT)
+#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */
+#define I40E_VFQF_HENA_MAX_INDEX 1
+#define I40E_VFQF_HENA_PTYPE_ENA_SHIFT 0
+#define I40E_VFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */
+#define I40E_VFQF_HKEY_MAX_INDEX 12
+#define I40E_VFQF_HKEY_KEY_0_SHIFT 0
+#define I40E_VFQF_HKEY_KEY_0_MASK (0xFF << I40E_VFQF_HKEY_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY_KEY_1_SHIFT 8
+#define I40E_VFQF_HKEY_KEY_1_MASK (0xFF << I40E_VFQF_HKEY_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY_KEY_2_SHIFT 16
+#define I40E_VFQF_HKEY_KEY_2_MASK (0xFF << I40E_VFQF_HKEY_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY_KEY_3_SHIFT 24
+#define I40E_VFQF_HKEY_KEY_3_MASK (0xFF << I40E_VFQF_HKEY_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_VFQF_HLUT_MAX_INDEX 15
+#define I40E_VFQF_HLUT_LUT0_SHIFT 0
+#define I40E_VFQF_HLUT_LUT0_MASK (0xF << I40E_VFQF_HLUT_LUT0_SHIFT)
+#define I40E_VFQF_HLUT_LUT1_SHIFT 8
+#define I40E_VFQF_HLUT_LUT1_MASK (0xF << I40E_VFQF_HLUT_LUT1_SHIFT)
+#define I40E_VFQF_HLUT_LUT2_SHIFT 16
+#define I40E_VFQF_HLUT_LUT2_MASK (0xF << I40E_VFQF_HLUT_LUT2_SHIFT)
+#define I40E_VFQF_HLUT_LUT3_SHIFT 24
+#define I40E_VFQF_HLUT_LUT3_MASK (0xF << I40E_VFQF_HLUT_LUT3_SHIFT)
+#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */
+#define I40E_VFQF_HREGION_MAX_INDEX 7
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION_REGION_0_SHIFT 1
+#define I40E_VFQF_HREGION_REGION_0_MASK (0x7 << I40E_VFQF_HREGION_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION_REGION_1_SHIFT 5
+#define I40E_VFQF_HREGION_REGION_1_MASK (0x7 << I40E_VFQF_HREGION_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION_REGION_2_SHIFT 9
+#define I40E_VFQF_HREGION_REGION_2_MASK (0x7 << I40E_VFQF_HREGION_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION_REGION_3_SHIFT 13
+#define I40E_VFQF_HREGION_REGION_3_MASK (0x7 << I40E_VFQF_HREGION_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION_REGION_4_SHIFT 17
+#define I40E_VFQF_HREGION_REGION_4_MASK (0x7 << I40E_VFQF_HREGION_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION_REGION_5_SHIFT 21
+#define I40E_VFQF_HREGION_REGION_5_MASK (0x7 << I40E_VFQF_HREGION_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION_REGION_6_SHIFT 25
+#define I40E_VFQF_HREGION_REGION_6_MASK (0x7 << I40E_VFQF_HREGION_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION_REGION_7_SHIFT 29
+#define I40E_VFQF_HREGION_REGION_7_MASK (0x7 << I40E_VFQF_HREGION_REGION_7_SHIFT)
+#define I40E_RCU_PST_FOC_ACCESS_STATUS 0x00270110
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT 0
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT)
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT 8
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT)
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT 16
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT)
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT 24
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_MASK (0x7 << I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT)
+#endif
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_status.h b/drivers/net/ethernet/intel/i40evf/i40e_status.h
new file mode 100644 (file)
index 0000000..7c08cc2
--- /dev/null
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_STATUS_H_
+#define _I40E_STATUS_H_
+
+/* Error Codes */
+enum i40e_status_code {
+       I40E_SUCCESS                            = 0,
+       I40E_ERR_NVM                            = -1,
+       I40E_ERR_NVM_CHECKSUM                   = -2,
+       I40E_ERR_PHY                            = -3,
+       I40E_ERR_CONFIG                         = -4,
+       I40E_ERR_PARAM                          = -5,
+       I40E_ERR_MAC_TYPE                       = -6,
+       I40E_ERR_UNKNOWN_PHY                    = -7,
+       I40E_ERR_LINK_SETUP                     = -8,
+       I40E_ERR_ADAPTER_STOPPED                = -9,
+       I40E_ERR_INVALID_MAC_ADDR               = -10,
+       I40E_ERR_DEVICE_NOT_SUPPORTED           = -11,
+       I40E_ERR_MASTER_REQUESTS_PENDING        = -12,
+       I40E_ERR_INVALID_LINK_SETTINGS          = -13,
+       I40E_ERR_AUTONEG_NOT_COMPLETE           = -14,
+       I40E_ERR_RESET_FAILED                   = -15,
+       I40E_ERR_SWFW_SYNC                      = -16,
+       I40E_ERR_NO_AVAILABLE_VSI               = -17,
+       I40E_ERR_NO_MEMORY                      = -18,
+       I40E_ERR_BAD_PTR                        = -19,
+       I40E_ERR_RING_FULL                      = -20,
+       I40E_ERR_INVALID_PD_ID                  = -21,
+       I40E_ERR_INVALID_QP_ID                  = -22,
+       I40E_ERR_INVALID_CQ_ID                  = -23,
+       I40E_ERR_INVALID_CEQ_ID                 = -24,
+       I40E_ERR_INVALID_AEQ_ID                 = -25,
+       I40E_ERR_INVALID_SIZE                   = -26,
+       I40E_ERR_INVALID_ARP_INDEX              = -27,
+       I40E_ERR_INVALID_FPM_FUNC_ID            = -28,
+       I40E_ERR_QP_INVALID_MSG_SIZE            = -29,
+       I40E_ERR_QP_TOOMANY_WRS_POSTED          = -30,
+       I40E_ERR_INVALID_FRAG_COUNT             = -31,
+       I40E_ERR_QUEUE_EMPTY                    = -32,
+       I40E_ERR_INVALID_ALIGNMENT              = -33,
+       I40E_ERR_FLUSHED_QUEUE                  = -34,
+       I40E_ERR_INVALID_PUSH_PAGE_INDEX        = -35,
+       I40E_ERR_INVALID_IMM_DATA_SIZE          = -36,
+       I40E_ERR_TIMEOUT                        = -37,
+       I40E_ERR_OPCODE_MISMATCH                = -38,
+       I40E_ERR_CQP_COMPL_ERROR                = -39,
+       I40E_ERR_INVALID_VF_ID                  = -40,
+       I40E_ERR_INVALID_HMCFN_ID               = -41,
+       I40E_ERR_BACKING_PAGE_ERROR             = -42,
+       I40E_ERR_NO_PBLCHUNKS_AVAILABLE         = -43,
+       I40E_ERR_INVALID_PBLE_INDEX             = -44,
+       I40E_ERR_INVALID_SD_INDEX               = -45,
+       I40E_ERR_INVALID_PAGE_DESC_INDEX        = -46,
+       I40E_ERR_INVALID_SD_TYPE                = -47,
+       I40E_ERR_MEMCPY_FAILED                  = -48,
+       I40E_ERR_INVALID_HMC_OBJ_INDEX          = -49,
+       I40E_ERR_INVALID_HMC_OBJ_COUNT          = -50,
+       I40E_ERR_INVALID_SRQ_ARM_LIMIT          = -51,
+       I40E_ERR_SRQ_ENABLED                    = -52,
+       I40E_ERR_ADMIN_QUEUE_ERROR              = -53,
+       I40E_ERR_ADMIN_QUEUE_TIMEOUT            = -54,
+       I40E_ERR_BUF_TOO_SHORT                  = -55,
+       I40E_ERR_ADMIN_QUEUE_FULL               = -56,
+       I40E_ERR_ADMIN_QUEUE_NO_WORK            = -57,
+       I40E_ERR_BAD_IWARP_CQE                  = -58,
+       I40E_ERR_NVM_BLANK_MODE                 = -59,
+       I40E_ERR_NOT_IMPLEMENTED                = -60,
+       I40E_ERR_PE_DOORBELL_NOT_ENABLED        = -61,
+       I40E_ERR_DIAG_TEST_FAILED               = -62,
+       I40E_ERR_NOT_READY                      = -63,
+       I40E_NOT_SUPPORTED                      = -64,
+       I40E_ERR_FIRMWARE_API_VERSION           = -65,
+};
+
+#endif /* _I40E_STATUS_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
new file mode 100644 (file)
index 0000000..ffdb01d
--- /dev/null
@@ -0,0 +1,1575 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#include <linux/prefetch.h>
+
+#include "i40evf.h"
+
+static inline __le64 build_ctob(u32 td_cmd, u32 td_offset, unsigned int size,
+                               u32 td_tag)
+{
+       return cpu_to_le64(I40E_TX_DESC_DTYPE_DATA |
+                          ((u64)td_cmd  << I40E_TXD_QW1_CMD_SHIFT) |
+                          ((u64)td_offset << I40E_TXD_QW1_OFFSET_SHIFT) |
+                          ((u64)size  << I40E_TXD_QW1_TX_BUF_SZ_SHIFT) |
+                          ((u64)td_tag  << I40E_TXD_QW1_L2TAG1_SHIFT));
+}
+
+#define I40E_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS)
+
+/**
+ * i40e_unmap_and_free_tx_resource - Release a Tx buffer
+ * @ring:      the ring that owns the buffer
+ * @tx_buffer: the buffer to free
+ **/
+static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring,
+                                           struct i40e_tx_buffer *tx_buffer)
+{
+       if (tx_buffer->skb) {
+               dev_kfree_skb_any(tx_buffer->skb);
+               if (dma_unmap_len(tx_buffer, len))
+                       dma_unmap_single(ring->dev,
+                                        dma_unmap_addr(tx_buffer, dma),
+                                        dma_unmap_len(tx_buffer, len),
+                                        DMA_TO_DEVICE);
+       } else if (dma_unmap_len(tx_buffer, len)) {
+               dma_unmap_page(ring->dev,
+                              dma_unmap_addr(tx_buffer, dma),
+                              dma_unmap_len(tx_buffer, len),
+                              DMA_TO_DEVICE);
+       }
+       tx_buffer->next_to_watch = NULL;
+       tx_buffer->skb = NULL;
+       dma_unmap_len_set(tx_buffer, len, 0);
+       /* tx_buffer must be completely set up in the transmit path */
+}
+
+/**
+ * i40evf_clean_tx_ring - Free any empty Tx buffers
+ * @tx_ring: ring to be cleaned
+ **/
+void i40evf_clean_tx_ring(struct i40e_ring *tx_ring)
+{
+       unsigned long bi_size;
+       u16 i;
+
+       /* ring already cleared, nothing to do */
+       if (!tx_ring->tx_bi)
+               return;
+
+       /* Free all the Tx ring sk_buffs */
+       for (i = 0; i < tx_ring->count; i++)
+               i40e_unmap_and_free_tx_resource(tx_ring, &tx_ring->tx_bi[i]);
+
+       bi_size = sizeof(struct i40e_tx_buffer) * tx_ring->count;
+       memset(tx_ring->tx_bi, 0, bi_size);
+
+       /* Zero out the descriptor ring */
+       memset(tx_ring->desc, 0, tx_ring->size);
+
+       tx_ring->next_to_use = 0;
+       tx_ring->next_to_clean = 0;
+
+       if (!tx_ring->netdev)
+               return;
+
+       /* cleanup Tx queue statistics */
+       netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
+                                                 tx_ring->queue_index));
+}
+
+/**
+ * i40evf_free_tx_resources - Free Tx resources per queue
+ * @tx_ring: Tx descriptor ring for a specific queue
+ *
+ * Free all transmit software resources
+ **/
+void i40evf_free_tx_resources(struct i40e_ring *tx_ring)
+{
+       i40evf_clean_tx_ring(tx_ring);
+       kfree(tx_ring->tx_bi);
+       tx_ring->tx_bi = NULL;
+
+       if (tx_ring->desc) {
+               dma_free_coherent(tx_ring->dev, tx_ring->size,
+                                 tx_ring->desc, tx_ring->dma);
+               tx_ring->desc = NULL;
+       }
+}
+
+/**
+ * i40e_get_tx_pending - how many tx descriptors not processed
+ * @tx_ring: the ring of descriptors
+ *
+ * Since there is no access to the ring head register
+ * in XL710, we need to use our local copies
+ **/
+static u32 i40e_get_tx_pending(struct i40e_ring *ring)
+{
+       u32 ntu = ((ring->next_to_clean <= ring->next_to_use)
+                       ? ring->next_to_use
+                       : ring->next_to_use + ring->count);
+       return ntu - ring->next_to_clean;
+}
+
+/**
+ * i40e_check_tx_hang - Is there a hang in the Tx queue
+ * @tx_ring: the ring of descriptors
+ **/
+static bool i40e_check_tx_hang(struct i40e_ring *tx_ring)
+{
+       u32 tx_pending = i40e_get_tx_pending(tx_ring);
+       bool ret = false;
+
+       clear_check_for_tx_hang(tx_ring);
+
+       /* Check for a hung queue, but be thorough. This verifies
+        * that a transmit has been completed since the previous
+        * check AND there is at least one packet pending. The
+        * ARMED bit is set to indicate a potential hang. The
+        * bit is cleared if a pause frame is received to remove
+        * false hang detection due to PFC or 802.3x frames. By
+        * requiring this to fail twice we avoid races with
+        * PFC clearing the ARMED bit and conditions where we
+        * run the check_tx_hang logic with a transmit completion
+        * pending but without time to complete it yet.
+        */
+       if ((tx_ring->tx_stats.tx_done_old == tx_ring->stats.packets) &&
+           tx_pending) {
+               /* make sure it is true for two checks in a row */
+               ret = test_and_set_bit(__I40E_HANG_CHECK_ARMED,
+                                      &tx_ring->state);
+       } else {
+               /* update completed stats and disarm the hang check */
+               tx_ring->tx_stats.tx_done_old = tx_ring->stats.packets;
+               clear_bit(__I40E_HANG_CHECK_ARMED, &tx_ring->state);
+       }
+
+       return ret;
+}
+
+/**
+ * i40e_clean_tx_irq - Reclaim resources after transmit completes
+ * @tx_ring:  tx ring to clean
+ * @budget:   how many cleans we're allowed
+ *
+ * Returns true if there's any budget left (e.g. the clean is finished)
+ **/
+static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
+{
+       u16 i = tx_ring->next_to_clean;
+       struct i40e_tx_buffer *tx_buf;
+       struct i40e_tx_desc *tx_desc;
+       unsigned int total_packets = 0;
+       unsigned int total_bytes = 0;
+
+       tx_buf = &tx_ring->tx_bi[i];
+       tx_desc = I40E_TX_DESC(tx_ring, i);
+       i -= tx_ring->count;
+
+       do {
+               struct i40e_tx_desc *eop_desc = tx_buf->next_to_watch;
+
+               /* if next_to_watch is not set then there is no work pending */
+               if (!eop_desc)
+                       break;
+
+               /* prevent any other reads prior to eop_desc */
+               read_barrier_depends();
+
+               /* if the descriptor isn't done, no work yet to do */
+               if (!(eop_desc->cmd_type_offset_bsz &
+                     cpu_to_le64(I40E_TX_DESC_DTYPE_DESC_DONE)))
+                       break;
+
+               /* clear next_to_watch to prevent false hangs */
+               tx_buf->next_to_watch = NULL;
+
+               /* update the statistics for this packet */
+               total_bytes += tx_buf->bytecount;
+               total_packets += tx_buf->gso_segs;
+
+               /* free the skb */
+               dev_kfree_skb_any(tx_buf->skb);
+
+               /* unmap skb header data */
+               dma_unmap_single(tx_ring->dev,
+                                dma_unmap_addr(tx_buf, dma),
+                                dma_unmap_len(tx_buf, len),
+                                DMA_TO_DEVICE);
+
+               /* clear tx_buffer data */
+               tx_buf->skb = NULL;
+               dma_unmap_len_set(tx_buf, len, 0);
+
+               /* unmap remaining buffers */
+               while (tx_desc != eop_desc) {
+
+                       tx_buf++;
+                       tx_desc++;
+                       i++;
+                       if (unlikely(!i)) {
+                               i -= tx_ring->count;
+                               tx_buf = tx_ring->tx_bi;
+                               tx_desc = I40E_TX_DESC(tx_ring, 0);
+                       }
+
+                       /* unmap any remaining paged data */
+                       if (dma_unmap_len(tx_buf, len)) {
+                               dma_unmap_page(tx_ring->dev,
+                                              dma_unmap_addr(tx_buf, dma),
+                                              dma_unmap_len(tx_buf, len),
+                                              DMA_TO_DEVICE);
+                               dma_unmap_len_set(tx_buf, len, 0);
+                       }
+               }
+
+               /* move us one more past the eop_desc for start of next pkt */
+               tx_buf++;
+               tx_desc++;
+               i++;
+               if (unlikely(!i)) {
+                       i -= tx_ring->count;
+                       tx_buf = tx_ring->tx_bi;
+                       tx_desc = I40E_TX_DESC(tx_ring, 0);
+               }
+
+               /* update budget accounting */
+               budget--;
+       } while (likely(budget));
+
+       i += tx_ring->count;
+       tx_ring->next_to_clean = i;
+       u64_stats_update_begin(&tx_ring->syncp);
+       tx_ring->stats.bytes += total_bytes;
+       tx_ring->stats.packets += total_packets;
+       u64_stats_update_end(&tx_ring->syncp);
+       tx_ring->q_vector->tx.total_bytes += total_bytes;
+       tx_ring->q_vector->tx.total_packets += total_packets;
+
+       if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) {
+               /* schedule immediate reset if we believe we hung */
+               dev_info(tx_ring->dev, "Detected Tx Unit Hang\n"
+                        "  VSI                  <%d>\n"
+                        "  Tx Queue             <%d>\n"
+                        "  next_to_use          <%x>\n"
+                        "  next_to_clean        <%x>\n",
+                        tx_ring->vsi->seid,
+                        tx_ring->queue_index,
+                        tx_ring->next_to_use, i);
+               dev_info(tx_ring->dev, "tx_bi[next_to_clean]\n"
+                        "  time_stamp           <%lx>\n"
+                        "  jiffies              <%lx>\n",
+                        tx_ring->tx_bi[i].time_stamp, jiffies);
+
+               netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+
+               dev_info(tx_ring->dev,
+                        "tx hang detected on queue %d, resetting adapter\n",
+                        tx_ring->queue_index);
+
+               tx_ring->netdev->netdev_ops->ndo_tx_timeout(tx_ring->netdev);
+
+               /* the adapter is about to reset, no point in enabling stuff */
+               return true;
+       }
+
+       netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev,
+                                                     tx_ring->queue_index),
+                                 total_packets, total_bytes);
+
+#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
+       if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) &&
+                    (I40E_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
+               /* Make sure that anybody stopping the queue after this
+                * sees the new next_to_clean.
+                */
+               smp_mb();
+               if (__netif_subqueue_stopped(tx_ring->netdev,
+                                            tx_ring->queue_index) &&
+                  !test_bit(__I40E_DOWN, &tx_ring->vsi->state)) {
+                       netif_wake_subqueue(tx_ring->netdev,
+                                           tx_ring->queue_index);
+                       ++tx_ring->tx_stats.restart_queue;
+               }
+       }
+
+       return budget > 0;
+}
+
+/**
+ * i40e_set_new_dynamic_itr - Find new ITR level
+ * @rc: structure containing ring performance data
+ *
+ * Stores a new ITR value based on packets and byte counts during
+ * the last interrupt.  The advantage of per interrupt computation
+ * is faster updates and more accurate ITR for the current traffic
+ * pattern.  Constants in this function were computed based on
+ * theoretical maximum wire speed and thresholds were set based on
+ * testing data as well as attempting to minimize response time
+ * while increasing bulk throughput.
+ **/
+static void i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
+{
+       enum i40e_latency_range new_latency_range = rc->latency_range;
+       u32 new_itr = rc->itr;
+       int bytes_per_int;
+
+       if (rc->total_packets == 0 || !rc->itr)
+               return;
+
+       /* simple throttlerate management
+        *   0-10MB/s   lowest (100000 ints/s)
+        *  10-20MB/s   low    (20000 ints/s)
+        *  20-1249MB/s bulk   (8000 ints/s)
+        */
+       bytes_per_int = rc->total_bytes / rc->itr;
+       switch (rc->itr) {
+       case I40E_LOWEST_LATENCY:
+               if (bytes_per_int > 10)
+                       new_latency_range = I40E_LOW_LATENCY;
+               break;
+       case I40E_LOW_LATENCY:
+               if (bytes_per_int > 20)
+                       new_latency_range = I40E_BULK_LATENCY;
+               else if (bytes_per_int <= 10)
+                       new_latency_range = I40E_LOWEST_LATENCY;
+               break;
+       case I40E_BULK_LATENCY:
+               if (bytes_per_int <= 20)
+                       rc->latency_range = I40E_LOW_LATENCY;
+               break;
+       }
+
+       switch (new_latency_range) {
+       case I40E_LOWEST_LATENCY:
+               new_itr = I40E_ITR_100K;
+               break;
+       case I40E_LOW_LATENCY:
+               new_itr = I40E_ITR_20K;
+               break;
+       case I40E_BULK_LATENCY:
+               new_itr = I40E_ITR_8K;
+               break;
+       default:
+               break;
+       }
+
+       if (new_itr != rc->itr) {
+               /* do an exponential smoothing */
+               new_itr = (10 * new_itr * rc->itr) /
+                         ((9 * new_itr) + rc->itr);
+               rc->itr = new_itr & I40E_MAX_ITR;
+       }
+
+       rc->total_bytes = 0;
+       rc->total_packets = 0;
+}
+
+/**
+ * i40e_update_dynamic_itr - Adjust ITR based on bytes per int
+ * @q_vector: the vector to adjust
+ **/
+static void i40e_update_dynamic_itr(struct i40e_q_vector *q_vector)
+{
+       u16 vector = q_vector->vsi->base_vector + q_vector->v_idx;
+       struct i40e_hw *hw = &q_vector->vsi->back->hw;
+       u32 reg_addr;
+       u16 old_itr;
+
+       reg_addr = I40E_VFINT_ITRN1(I40E_RX_ITR, vector - 1);
+       old_itr = q_vector->rx.itr;
+       i40e_set_new_dynamic_itr(&q_vector->rx);
+       if (old_itr != q_vector->rx.itr)
+               wr32(hw, reg_addr, q_vector->rx.itr);
+
+       reg_addr = I40E_VFINT_ITRN1(I40E_TX_ITR, vector - 1);
+       old_itr = q_vector->tx.itr;
+       i40e_set_new_dynamic_itr(&q_vector->tx);
+       if (old_itr != q_vector->tx.itr)
+               wr32(hw, reg_addr, q_vector->tx.itr);
+}
+
+/**
+ * i40evf_setup_tx_descriptors - Allocate the Tx descriptors
+ * @tx_ring: the tx ring to set up
+ *
+ * Return 0 on success, negative on error
+ **/
+int i40evf_setup_tx_descriptors(struct i40e_ring *tx_ring)
+{
+       struct device *dev = tx_ring->dev;
+       int bi_size;
+
+       if (!dev)
+               return -ENOMEM;
+
+       bi_size = sizeof(struct i40e_tx_buffer) * tx_ring->count;
+       tx_ring->tx_bi = kzalloc(bi_size, GFP_KERNEL);
+       if (!tx_ring->tx_bi)
+               goto err;
+
+       /* round up to nearest 4K */
+       tx_ring->size = tx_ring->count * sizeof(struct i40e_tx_desc);
+       tx_ring->size = ALIGN(tx_ring->size, 4096);
+       tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
+                                          &tx_ring->dma, GFP_KERNEL);
+       if (!tx_ring->desc) {
+               dev_info(dev, "Unable to allocate memory for the Tx descriptor ring, size=%d\n",
+                        tx_ring->size);
+               goto err;
+       }
+
+       tx_ring->next_to_use = 0;
+       tx_ring->next_to_clean = 0;
+       return 0;
+
+err:
+       kfree(tx_ring->tx_bi);
+       tx_ring->tx_bi = NULL;
+       return -ENOMEM;
+}
+
+/**
+ * i40evf_clean_rx_ring - Free Rx buffers
+ * @rx_ring: ring to be cleaned
+ **/
+void i40evf_clean_rx_ring(struct i40e_ring *rx_ring)
+{
+       struct device *dev = rx_ring->dev;
+       struct i40e_rx_buffer *rx_bi;
+       unsigned long bi_size;
+       u16 i;
+
+       /* ring already cleared, nothing to do */
+       if (!rx_ring->rx_bi)
+               return;
+
+       /* Free all the Rx ring sk_buffs */
+       for (i = 0; i < rx_ring->count; i++) {
+               rx_bi = &rx_ring->rx_bi[i];
+               if (rx_bi->dma) {
+                       dma_unmap_single(dev,
+                                        rx_bi->dma,
+                                        rx_ring->rx_buf_len,
+                                        DMA_FROM_DEVICE);
+                       rx_bi->dma = 0;
+               }
+               if (rx_bi->skb) {
+                       dev_kfree_skb(rx_bi->skb);
+                       rx_bi->skb = NULL;
+               }
+               if (rx_bi->page) {
+                       if (rx_bi->page_dma) {
+                               dma_unmap_page(dev,
+                                              rx_bi->page_dma,
+                                              PAGE_SIZE / 2,
+                                              DMA_FROM_DEVICE);
+                               rx_bi->page_dma = 0;
+                       }
+                       __free_page(rx_bi->page);
+                       rx_bi->page = NULL;
+                       rx_bi->page_offset = 0;
+               }
+       }
+
+       bi_size = sizeof(struct i40e_rx_buffer) * rx_ring->count;
+       memset(rx_ring->rx_bi, 0, bi_size);
+
+       /* Zero out the descriptor ring */
+       memset(rx_ring->desc, 0, rx_ring->size);
+
+       rx_ring->next_to_clean = 0;
+       rx_ring->next_to_use = 0;
+}
+
+/**
+ * i40evf_free_rx_resources - Free Rx resources
+ * @rx_ring: ring to clean the resources from
+ *
+ * Free all receive software resources
+ **/
+void i40evf_free_rx_resources(struct i40e_ring *rx_ring)
+{
+       i40evf_clean_rx_ring(rx_ring);
+       kfree(rx_ring->rx_bi);
+       rx_ring->rx_bi = NULL;
+
+       if (rx_ring->desc) {
+               dma_free_coherent(rx_ring->dev, rx_ring->size,
+                                 rx_ring->desc, rx_ring->dma);
+               rx_ring->desc = NULL;
+       }
+}
+
+/**
+ * i40evf_setup_rx_descriptors - Allocate Rx descriptors
+ * @rx_ring: Rx descriptor ring (for a specific queue) to setup
+ *
+ * Returns 0 on success, negative on failure
+ **/
+int i40evf_setup_rx_descriptors(struct i40e_ring *rx_ring)
+{
+       struct device *dev = rx_ring->dev;
+       int bi_size;
+
+       bi_size = sizeof(struct i40e_rx_buffer) * rx_ring->count;
+       rx_ring->rx_bi = kzalloc(bi_size, GFP_KERNEL);
+       if (!rx_ring->rx_bi)
+               goto err;
+
+       /* Round up to nearest 4K */
+       rx_ring->size = ring_is_16byte_desc_enabled(rx_ring)
+               ? rx_ring->count * sizeof(union i40e_16byte_rx_desc)
+               : rx_ring->count * sizeof(union i40e_32byte_rx_desc);
+       rx_ring->size = ALIGN(rx_ring->size, 4096);
+       rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
+                                          &rx_ring->dma, GFP_KERNEL);
+
+       if (!rx_ring->desc) {
+               dev_info(dev, "Unable to allocate memory for the Rx descriptor ring, size=%d\n",
+                        rx_ring->size);
+               goto err;
+       }
+
+       rx_ring->next_to_clean = 0;
+       rx_ring->next_to_use = 0;
+
+       return 0;
+err:
+       kfree(rx_ring->rx_bi);
+       rx_ring->rx_bi = NULL;
+       return -ENOMEM;
+}
+
+/**
+ * i40e_release_rx_desc - Store the new tail and head values
+ * @rx_ring: ring to bump
+ * @val: new head index
+ **/
+static inline void i40e_release_rx_desc(struct i40e_ring *rx_ring, u32 val)
+{
+       rx_ring->next_to_use = val;
+       /* Force memory writes to complete before letting h/w
+        * know there are new descriptors to fetch.  (Only
+        * applicable for weak-ordered memory model archs,
+        * such as IA-64).
+        */
+       wmb();
+       writel(val, rx_ring->tail);
+}
+
+/**
+ * i40evf_alloc_rx_buffers - Replace used receive buffers; packet split
+ * @rx_ring: ring to place buffers on
+ * @cleaned_count: number of buffers to replace
+ **/
+void i40evf_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
+{
+       u16 i = rx_ring->next_to_use;
+       union i40e_rx_desc *rx_desc;
+       struct i40e_rx_buffer *bi;
+       struct sk_buff *skb;
+
+       /* do nothing if no valid netdev defined */
+       if (!rx_ring->netdev || !cleaned_count)
+               return;
+
+       while (cleaned_count--) {
+               rx_desc = I40E_RX_DESC(rx_ring, i);
+               bi = &rx_ring->rx_bi[i];
+               skb = bi->skb;
+
+               if (!skb) {
+                       skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+                                                       rx_ring->rx_buf_len);
+                       if (!skb) {
+                               rx_ring->rx_stats.alloc_buff_failed++;
+                               goto no_buffers;
+                       }
+                       /* initialize queue mapping */
+                       skb_record_rx_queue(skb, rx_ring->queue_index);
+                       bi->skb = skb;
+               }
+
+               if (!bi->dma) {
+                       bi->dma = dma_map_single(rx_ring->dev,
+                                                skb->data,
+                                                rx_ring->rx_buf_len,
+                                                DMA_FROM_DEVICE);
+                       if (dma_mapping_error(rx_ring->dev, bi->dma)) {
+                               rx_ring->rx_stats.alloc_buff_failed++;
+                               bi->dma = 0;
+                               goto no_buffers;
+                       }
+               }
+
+               if (ring_is_ps_enabled(rx_ring)) {
+                       if (!bi->page) {
+                               bi->page = alloc_page(GFP_ATOMIC);
+                               if (!bi->page) {
+                                       rx_ring->rx_stats.alloc_page_failed++;
+                                       goto no_buffers;
+                               }
+                       }
+
+                       if (!bi->page_dma) {
+                               /* use a half page if we're re-using */
+                               bi->page_offset ^= PAGE_SIZE / 2;
+                               bi->page_dma = dma_map_page(rx_ring->dev,
+                                                           bi->page,
+                                                           bi->page_offset,
+                                                           PAGE_SIZE / 2,
+                                                           DMA_FROM_DEVICE);
+                               if (dma_mapping_error(rx_ring->dev,
+                                                     bi->page_dma)) {
+                                       rx_ring->rx_stats.alloc_page_failed++;
+                                       bi->page_dma = 0;
+                                       goto no_buffers;
+                               }
+                       }
+
+                       /* Refresh the desc even if buffer_addrs didn't change
+                        * because each write-back erases this info.
+                        */
+                       rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
+                       rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
+               } else {
+                       rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
+                       rx_desc->read.hdr_addr = 0;
+               }
+               i++;
+               if (i == rx_ring->count)
+                       i = 0;
+       }
+
+no_buffers:
+       if (rx_ring->next_to_use != i)
+               i40e_release_rx_desc(rx_ring, i);
+}
+
+/**
+ * i40e_receive_skb - Send a completed packet up the stack
+ * @rx_ring:  rx ring in play
+ * @skb: packet to send up
+ * @vlan_tag: vlan tag for packet
+ **/
+static void i40e_receive_skb(struct i40e_ring *rx_ring,
+                            struct sk_buff *skb, u16 vlan_tag)
+{
+       struct i40e_q_vector *q_vector = rx_ring->q_vector;
+       struct i40e_vsi *vsi = rx_ring->vsi;
+       u64 flags = vsi->back->flags;
+
+       if (vlan_tag & VLAN_VID_MASK)
+               __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
+
+       if (flags & I40E_FLAG_IN_NETPOLL)
+               netif_rx(skb);
+       else
+               napi_gro_receive(&q_vector->napi, skb);
+}
+
+/**
+ * i40e_rx_checksum - Indicate in skb if hw indicated a good cksum
+ * @vsi: the VSI we care about
+ * @skb: skb currently being received and modified
+ * @rx_status: status value of last descriptor in packet
+ * @rx_error: error value of last descriptor in packet
+ * @rx_ptype: ptype value of last descriptor in packet
+ **/
+static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
+                                   struct sk_buff *skb,
+                                   u32 rx_status,
+                                   u32 rx_error,
+                                   u16 rx_ptype)
+{
+       bool ipv4_tunnel, ipv6_tunnel;
+       __wsum rx_udp_csum;
+       __sum16 csum;
+       struct iphdr *iph;
+
+       ipv4_tunnel = (rx_ptype > I40E_RX_PTYPE_GRENAT4_MAC_PAY3) &&
+                     (rx_ptype < I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4);
+       ipv6_tunnel = (rx_ptype > I40E_RX_PTYPE_GRENAT6_MAC_PAY3) &&
+                     (rx_ptype < I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4);
+
+       skb->encapsulation = ipv4_tunnel || ipv6_tunnel;
+       skb->ip_summed = CHECKSUM_NONE;
+
+       /* Rx csum enabled and ip headers found? */
+       if (!(vsi->netdev->features & NETIF_F_RXCSUM &&
+             rx_status & (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT)))
+               return;
+
+       /* likely incorrect csum if alternate IP extention headers found */
+       if (rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
+               return;
+
+       /* IP or L4 or outmost IP checksum error */
+       if (rx_error & ((1 << I40E_RX_DESC_ERROR_IPE_SHIFT) |
+                       (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) |
+                       (1 << I40E_RX_DESC_ERROR_EIPE_SHIFT))) {
+               vsi->back->hw_csum_rx_error++;
+               return;
+       }
+
+       if (ipv4_tunnel &&
+           !(rx_status & (1 << I40E_RX_DESC_STATUS_UDP_0_SHIFT))) {
+               /* If VXLAN traffic has an outer UDPv4 checksum we need to check
+                * it in the driver, hardware does not do it for us.
+                * Since L3L4P bit was set we assume a valid IHL value (>=5)
+                * so the total length of IPv4 header is IHL*4 bytes
+                */
+               skb->transport_header = skb->mac_header +
+                                       sizeof(struct ethhdr) +
+                                       (ip_hdr(skb)->ihl * 4);
+
+               /* Add 4 bytes for VLAN tagged packets */
+               skb->transport_header += (skb->protocol == htons(ETH_P_8021Q) ||
+                                         skb->protocol == htons(ETH_P_8021AD))
+                                         ? VLAN_HLEN : 0;
+
+               rx_udp_csum = udp_csum(skb);
+               iph = ip_hdr(skb);
+               csum = csum_tcpudp_magic(
+                               iph->saddr, iph->daddr,
+                               (skb->len - skb_transport_offset(skb)),
+                               IPPROTO_UDP, rx_udp_csum);
+
+               if (udp_hdr(skb)->check != csum) {
+                       vsi->back->hw_csum_rx_error++;
+                       return;
+               }
+       }
+
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
+/**
+ * i40e_rx_hash - returns the hash value from the Rx descriptor
+ * @ring: descriptor ring
+ * @rx_desc: specific descriptor
+ **/
+static inline u32 i40e_rx_hash(struct i40e_ring *ring,
+                              union i40e_rx_desc *rx_desc)
+{
+       const __le64 rss_mask =
+               cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
+                           I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
+
+       if ((ring->netdev->features & NETIF_F_RXHASH) &&
+           (rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask)
+               return le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
+       else
+               return 0;
+}
+
+/**
+ * i40e_clean_rx_irq - Reclaim resources after receive completes
+ * @rx_ring:  rx ring to clean
+ * @budget:   how many cleans we're allowed
+ *
+ * Returns true if there's any budget left (e.g. the clean is finished)
+ **/
+static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
+{
+       unsigned int total_rx_bytes = 0, total_rx_packets = 0;
+       u16 rx_packet_len, rx_header_len, rx_sph, rx_hbo;
+       u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
+       const int current_node = numa_node_id();
+       struct i40e_vsi *vsi = rx_ring->vsi;
+       u16 i = rx_ring->next_to_clean;
+       union i40e_rx_desc *rx_desc;
+       u32 rx_error, rx_status;
+       u64 qword;
+       u16 rx_ptype;
+
+       rx_desc = I40E_RX_DESC(rx_ring, i);
+       qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+       rx_status = (qword & I40E_RXD_QW1_STATUS_MASK)
+                               >> I40E_RXD_QW1_STATUS_SHIFT;
+
+       while (rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) {
+               union i40e_rx_desc *next_rxd;
+               struct i40e_rx_buffer *rx_bi;
+               struct sk_buff *skb;
+               u16 vlan_tag;
+               rx_bi = &rx_ring->rx_bi[i];
+               skb = rx_bi->skb;
+               prefetch(skb->data);
+
+               rx_packet_len = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) >>
+                               I40E_RXD_QW1_LENGTH_PBUF_SHIFT;
+               rx_header_len = (qword & I40E_RXD_QW1_LENGTH_HBUF_MASK) >>
+                               I40E_RXD_QW1_LENGTH_HBUF_SHIFT;
+               rx_sph = (qword & I40E_RXD_QW1_LENGTH_SPH_MASK) >>
+                        I40E_RXD_QW1_LENGTH_SPH_SHIFT;
+
+               rx_error = (qword & I40E_RXD_QW1_ERROR_MASK) >>
+                          I40E_RXD_QW1_ERROR_SHIFT;
+               rx_hbo = rx_error & (1 << I40E_RX_DESC_ERROR_HBO_SHIFT);
+               rx_error &= ~(1 << I40E_RX_DESC_ERROR_HBO_SHIFT);
+
+               rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+                          I40E_RXD_QW1_PTYPE_SHIFT;
+               rx_bi->skb = NULL;
+
+               /* This memory barrier is needed to keep us from reading
+                * any other fields out of the rx_desc until we know the
+                * STATUS_DD bit is set
+                */
+               rmb();
+
+               /* Get the header and possibly the whole packet
+                * If this is an skb from previous receive dma will be 0
+                */
+               if (rx_bi->dma) {
+                       u16 len;
+
+                       if (rx_hbo)
+                               len = I40E_RX_HDR_SIZE;
+                       else if (rx_sph)
+                               len = rx_header_len;
+                       else if (rx_packet_len)
+                               len = rx_packet_len;   /* 1buf/no split found */
+                       else
+                               len = rx_header_len;   /* split always mode */
+
+                       skb_put(skb, len);
+                       dma_unmap_single(rx_ring->dev,
+                                        rx_bi->dma,
+                                        rx_ring->rx_buf_len,
+                                        DMA_FROM_DEVICE);
+                       rx_bi->dma = 0;
+               }
+
+               /* Get the rest of the data if this was a header split */
+               if (ring_is_ps_enabled(rx_ring) && rx_packet_len) {
+
+                       skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+                                          rx_bi->page,
+                                          rx_bi->page_offset,
+                                          rx_packet_len);
+
+                       skb->len += rx_packet_len;
+                       skb->data_len += rx_packet_len;
+                       skb->truesize += rx_packet_len;
+
+                       if ((page_count(rx_bi->page) == 1) &&
+                           (page_to_nid(rx_bi->page) == current_node))
+                               get_page(rx_bi->page);
+                       else
+                               rx_bi->page = NULL;
+
+                       dma_unmap_page(rx_ring->dev,
+                                      rx_bi->page_dma,
+                                      PAGE_SIZE / 2,
+                                      DMA_FROM_DEVICE);
+                       rx_bi->page_dma = 0;
+               }
+               I40E_RX_NEXT_DESC_PREFETCH(rx_ring, i, next_rxd);
+
+               if (unlikely(
+                   !(rx_status & (1 << I40E_RX_DESC_STATUS_EOF_SHIFT)))) {
+                       struct i40e_rx_buffer *next_buffer;
+
+                       next_buffer = &rx_ring->rx_bi[i];
+
+                       if (ring_is_ps_enabled(rx_ring)) {
+                               rx_bi->skb = next_buffer->skb;
+                               rx_bi->dma = next_buffer->dma;
+                               next_buffer->skb = skb;
+                               next_buffer->dma = 0;
+                       }
+                       rx_ring->rx_stats.non_eop_descs++;
+                       goto next_desc;
+               }
+
+               /* ERR_MASK will only have valid bits if EOP set */
+               if (unlikely(rx_error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) {
+                       dev_kfree_skb_any(skb);
+                       goto next_desc;
+               }
+
+               skb->rxhash = i40e_rx_hash(rx_ring, rx_desc);
+               /* probably a little skewed due to removing CRC */
+               total_rx_bytes += skb->len;
+               total_rx_packets++;
+
+               skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+
+               i40e_rx_checksum(vsi, skb, rx_status, rx_error, rx_ptype);
+
+               vlan_tag = rx_status & (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)
+                        ? le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1)
+                        : 0;
+               i40e_receive_skb(rx_ring, skb, vlan_tag);
+
+               rx_ring->netdev->last_rx = jiffies;
+               budget--;
+next_desc:
+               rx_desc->wb.qword1.status_error_len = 0;
+               if (!budget)
+                       break;
+
+               cleaned_count++;
+               /* return some buffers to hardware, one at a time is too slow */
+               if (cleaned_count >= I40E_RX_BUFFER_WRITE) {
+                       i40evf_alloc_rx_buffers(rx_ring, cleaned_count);
+                       cleaned_count = 0;
+               }
+
+               /* use prefetched values */
+               rx_desc = next_rxd;
+               qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+               rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
+                           I40E_RXD_QW1_STATUS_SHIFT;
+       }
+
+       rx_ring->next_to_clean = i;
+       u64_stats_update_begin(&rx_ring->syncp);
+       rx_ring->stats.packets += total_rx_packets;
+       rx_ring->stats.bytes += total_rx_bytes;
+       u64_stats_update_end(&rx_ring->syncp);
+       rx_ring->q_vector->rx.total_packets += total_rx_packets;
+       rx_ring->q_vector->rx.total_bytes += total_rx_bytes;
+
+       if (cleaned_count)
+               i40evf_alloc_rx_buffers(rx_ring, cleaned_count);
+
+       return budget > 0;
+}
+
+/**
+ * i40evf_napi_poll - NAPI polling Rx/Tx cleanup routine
+ * @napi: napi struct with our devices info in it
+ * @budget: amount of work driver is allowed to do this pass, in packets
+ *
+ * This function will clean all queues associated with a q_vector.
+ *
+ * Returns the amount of work done
+ **/
+int i40evf_napi_poll(struct napi_struct *napi, int budget)
+{
+       struct i40e_q_vector *q_vector =
+                              container_of(napi, struct i40e_q_vector, napi);
+       struct i40e_vsi *vsi = q_vector->vsi;
+       struct i40e_ring *ring;
+       bool clean_complete = true;
+       int budget_per_ring;
+
+       if (test_bit(__I40E_DOWN, &vsi->state)) {
+               napi_complete(napi);
+               return 0;
+       }
+
+       /* Since the actual Tx work is minimal, we can give the Tx a larger
+        * budget and be more aggressive about cleaning up the Tx descriptors.
+        */
+       i40e_for_each_ring(ring, q_vector->tx)
+               clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit);
+
+       /* We attempt to distribute budget to each Rx queue fairly, but don't
+        * allow the budget to go below 1 because that would exit polling early.
+        */
+       budget_per_ring = max(budget/q_vector->num_ringpairs, 1);
+
+       i40e_for_each_ring(ring, q_vector->rx)
+               clean_complete &= i40e_clean_rx_irq(ring, budget_per_ring);
+
+       /* If work not completed, return budget and polling will return */
+       if (!clean_complete)
+               return budget;
+
+       /* Work is done so exit the polling mode and re-enable the interrupt */
+       napi_complete(napi);
+       if (ITR_IS_DYNAMIC(vsi->rx_itr_setting) ||
+           ITR_IS_DYNAMIC(vsi->tx_itr_setting))
+               i40e_update_dynamic_itr(q_vector);
+
+       if (!test_bit(__I40E_DOWN, &vsi->state))
+               i40evf_irq_enable_queues(vsi->back, 1 << q_vector->v_idx);
+
+       return 0;
+}
+
+/**
+ * i40e_tx_prepare_vlan_flags - prepare generic TX VLAN tagging flags for HW
+ * @skb:     send buffer
+ * @tx_ring: ring to send buffer on
+ * @flags:   the tx flags to be set
+ *
+ * Checks the skb and set up correspondingly several generic transmit flags
+ * related to VLAN tagging for the HW, such as VLAN, DCB, etc.
+ *
+ * Returns error code indicate the frame should be dropped upon error and the
+ * otherwise  returns 0 to indicate the flags has been set properly.
+ **/
+static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
+                                     struct i40e_ring *tx_ring,
+                                     u32 *flags)
+{
+       __be16 protocol = skb->protocol;
+       u32  tx_flags = 0;
+
+       /* if we have a HW VLAN tag being added, default to the HW one */
+       if (vlan_tx_tag_present(skb)) {
+               tx_flags |= vlan_tx_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT;
+               tx_flags |= I40E_TX_FLAGS_HW_VLAN;
+       /* else if it is a SW VLAN, check the next protocol and store the tag */
+       } else if (protocol == htons(ETH_P_8021Q)) {
+               struct vlan_hdr *vhdr, _vhdr;
+               vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr);
+               if (!vhdr)
+                       return -EINVAL;
+
+               protocol = vhdr->h_vlan_encapsulated_proto;
+               tx_flags |= ntohs(vhdr->h_vlan_TCI) << I40E_TX_FLAGS_VLAN_SHIFT;
+               tx_flags |= I40E_TX_FLAGS_SW_VLAN;
+       }
+
+       *flags = tx_flags;
+       return 0;
+}
+
+/**
+ * i40e_tso - set up the tso context descriptor
+ * @tx_ring:  ptr to the ring to send
+ * @skb:      ptr to the skb we're sending
+ * @tx_flags: the collected send information
+ * @protocol: the send protocol
+ * @hdr_len:  ptr to the size of the packet header
+ * @cd_tunneling: ptr to context descriptor bits
+ *
+ * Returns 0 if no TSO can happen, 1 if tso is going, or error
+ **/
+static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
+                   u32 tx_flags, __be16 protocol, u8 *hdr_len,
+                   u64 *cd_type_cmd_tso_mss, u32 *cd_tunneling)
+{
+       u32 cd_cmd, cd_tso_len, cd_mss;
+       struct tcphdr *tcph;
+       struct iphdr *iph;
+       u32 l4len;
+       int err;
+       struct ipv6hdr *ipv6h;
+
+       if (!skb_is_gso(skb))
+               return 0;
+
+       if (skb_header_cloned(skb)) {
+               err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+               if (err)
+                       return err;
+       }
+
+       if (protocol == htons(ETH_P_IP)) {
+               iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb);
+               tcph = skb->encapsulation ? inner_tcp_hdr(skb) : tcp_hdr(skb);
+               iph->tot_len = 0;
+               iph->check = 0;
+               tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+                                                0, IPPROTO_TCP, 0);
+       } else if (skb_is_gso_v6(skb)) {
+
+               ipv6h = skb->encapsulation ? inner_ipv6_hdr(skb)
+                                          : ipv6_hdr(skb);
+               tcph = skb->encapsulation ? inner_tcp_hdr(skb) : tcp_hdr(skb);
+               ipv6h->payload_len = 0;
+               tcph->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
+                                              0, IPPROTO_TCP, 0);
+       }
+
+       l4len = skb->encapsulation ? inner_tcp_hdrlen(skb) : tcp_hdrlen(skb);
+       *hdr_len = (skb->encapsulation
+                   ? (skb_inner_transport_header(skb) - skb->data)
+                   : skb_transport_offset(skb)) + l4len;
+
+       /* find the field values */
+       cd_cmd = I40E_TX_CTX_DESC_TSO;
+       cd_tso_len = skb->len - *hdr_len;
+       cd_mss = skb_shinfo(skb)->gso_size;
+       *cd_type_cmd_tso_mss |= ((u64)cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |
+                               ((u64)cd_tso_len <<
+                                I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
+                               ((u64)cd_mss << I40E_TXD_CTX_QW1_MSS_SHIFT);
+       return 1;
+}
+
+/**
+ * i40e_tx_enable_csum - Enable Tx checksum offloads
+ * @skb: send buffer
+ * @tx_flags: Tx flags currently set
+ * @td_cmd: Tx descriptor command bits to set
+ * @td_offset: Tx descriptor header offsets to set
+ * @cd_tunneling: ptr to context desc bits
+ **/
+static void i40e_tx_enable_csum(struct sk_buff *skb, u32 tx_flags,
+                               u32 *td_cmd, u32 *td_offset,
+                               struct i40e_ring *tx_ring,
+                               u32 *cd_tunneling)
+{
+       struct ipv6hdr *this_ipv6_hdr;
+       unsigned int this_tcp_hdrlen;
+       struct iphdr *this_ip_hdr;
+       u32 network_hdr_len;
+       u8 l4_hdr = 0;
+
+       if (skb->encapsulation) {
+               network_hdr_len = skb_inner_network_header_len(skb);
+               this_ip_hdr = inner_ip_hdr(skb);
+               this_ipv6_hdr = inner_ipv6_hdr(skb);
+               this_tcp_hdrlen = inner_tcp_hdrlen(skb);
+
+               if (tx_flags & I40E_TX_FLAGS_IPV4) {
+
+                       if (tx_flags & I40E_TX_FLAGS_TSO) {
+                               *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV4;
+                               ip_hdr(skb)->check = 0;
+                       } else {
+                               *cd_tunneling |=
+                                        I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM;
+                       }
+               } else if (tx_flags & I40E_TX_FLAGS_IPV6) {
+                       if (tx_flags & I40E_TX_FLAGS_TSO) {
+                               *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6;
+                               ip_hdr(skb)->check = 0;
+                       } else {
+                               *cd_tunneling |=
+                                        I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM;
+                       }
+               }
+
+               /* Now set the ctx descriptor fields */
+               *cd_tunneling |= (skb_network_header_len(skb) >> 2) <<
+                                       I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT |
+                                  I40E_TXD_CTX_UDP_TUNNELING            |
+                                  ((skb_inner_network_offset(skb) -
+                                       skb_transport_offset(skb)) >> 1) <<
+                                  I40E_TXD_CTX_QW0_NATLEN_SHIFT;
+
+       } else {
+               network_hdr_len = skb_network_header_len(skb);
+               this_ip_hdr = ip_hdr(skb);
+               this_ipv6_hdr = ipv6_hdr(skb);
+               this_tcp_hdrlen = tcp_hdrlen(skb);
+       }
+
+       /* Enable IP checksum offloads */
+       if (tx_flags & I40E_TX_FLAGS_IPV4) {
+               l4_hdr = this_ip_hdr->protocol;
+               /* the stack computes the IP header already, the only time we
+                * need the hardware to recompute it is in the case of TSO.
+                */
+               if (tx_flags & I40E_TX_FLAGS_TSO) {
+                       *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4_CSUM;
+                       this_ip_hdr->check = 0;
+               } else {
+                       *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4;
+               }
+               /* Now set the td_offset for IP header length */
+               *td_offset = (network_hdr_len >> 2) <<
+                             I40E_TX_DESC_LENGTH_IPLEN_SHIFT;
+       } else if (tx_flags & I40E_TX_FLAGS_IPV6) {
+               l4_hdr = this_ipv6_hdr->nexthdr;
+               *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV6;
+               /* Now set the td_offset for IP header length */
+               *td_offset = (network_hdr_len >> 2) <<
+                             I40E_TX_DESC_LENGTH_IPLEN_SHIFT;
+       }
+       /* words in MACLEN + dwords in IPLEN + dwords in L4Len */
+       *td_offset |= (skb_network_offset(skb) >> 1) <<
+                      I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
+
+       /* Enable L4 checksum offloads */
+       switch (l4_hdr) {
+       case IPPROTO_TCP:
+               /* enable checksum offloads */
+               *td_cmd |= I40E_TX_DESC_CMD_L4T_EOFT_TCP;
+               *td_offset |= (this_tcp_hdrlen >> 2) <<
+                              I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
+               break;
+       case IPPROTO_SCTP:
+               /* enable SCTP checksum offload */
+               *td_cmd |= I40E_TX_DESC_CMD_L4T_EOFT_SCTP;
+               *td_offset |= (sizeof(struct sctphdr) >> 2) <<
+                              I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
+               break;
+       case IPPROTO_UDP:
+               /* enable UDP checksum offload */
+               *td_cmd |= I40E_TX_DESC_CMD_L4T_EOFT_UDP;
+               *td_offset |= (sizeof(struct udphdr) >> 2) <<
+                              I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
+               break;
+       default:
+               break;
+       }
+}
+
+/**
+ * i40e_create_tx_ctx Build the Tx context descriptor
+ * @tx_ring:  ring to create the descriptor on
+ * @cd_type_cmd_tso_mss: Quad Word 1
+ * @cd_tunneling: Quad Word 0 - bits 0-31
+ * @cd_l2tag2: Quad Word 0 - bits 32-63
+ **/
+static void i40e_create_tx_ctx(struct i40e_ring *tx_ring,
+                              const u64 cd_type_cmd_tso_mss,
+                              const u32 cd_tunneling, const u32 cd_l2tag2)
+{
+       struct i40e_tx_context_desc *context_desc;
+       int i = tx_ring->next_to_use;
+
+       if (!cd_type_cmd_tso_mss && !cd_tunneling && !cd_l2tag2)
+               return;
+
+       /* grab the next descriptor */
+       context_desc = I40E_TX_CTXTDESC(tx_ring, i);
+
+       i++;
+       tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
+
+       /* cpu_to_le32 and assign to struct fields */
+       context_desc->tunneling_params = cpu_to_le32(cd_tunneling);
+       context_desc->l2tag2 = cpu_to_le16(cd_l2tag2);
+       context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
+}
+
+/**
+ * i40e_tx_map - Build the Tx descriptor
+ * @tx_ring:  ring to send buffer on
+ * @skb:      send buffer
+ * @first:    first buffer info buffer to use
+ * @tx_flags: collected send information
+ * @hdr_len:  size of the packet header
+ * @td_cmd:   the command field in the descriptor
+ * @td_offset: offset for checksum or crc
+ **/
+static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
+                       struct i40e_tx_buffer *first, u32 tx_flags,
+                       const u8 hdr_len, u32 td_cmd, u32 td_offset)
+{
+       unsigned int data_len = skb->data_len;
+       unsigned int size = skb_headlen(skb);
+       struct skb_frag_struct *frag;
+       struct i40e_tx_buffer *tx_bi;
+       struct i40e_tx_desc *tx_desc;
+       u16 i = tx_ring->next_to_use;
+       u32 td_tag = 0;
+       dma_addr_t dma;
+       u16 gso_segs;
+
+       if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
+               td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
+               td_tag = (tx_flags & I40E_TX_FLAGS_VLAN_MASK) >>
+                        I40E_TX_FLAGS_VLAN_SHIFT;
+       }
+
+       if (tx_flags & (I40E_TX_FLAGS_TSO | I40E_TX_FLAGS_FSO))
+               gso_segs = skb_shinfo(skb)->gso_segs;
+       else
+               gso_segs = 1;
+
+       /* multiply data chunks by size of headers */
+       first->bytecount = skb->len - hdr_len + (gso_segs * hdr_len);
+       first->gso_segs = gso_segs;
+       first->skb = skb;
+       first->tx_flags = tx_flags;
+
+       dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
+
+       tx_desc = I40E_TX_DESC(tx_ring, i);
+       tx_bi = first;
+
+       for (frag = &skb_shinfo(skb)->frags[0];; frag++) {
+               if (dma_mapping_error(tx_ring->dev, dma))
+                       goto dma_error;
+
+               /* record length, and DMA address */
+               dma_unmap_len_set(tx_bi, len, size);
+               dma_unmap_addr_set(tx_bi, dma, dma);
+
+               tx_desc->buffer_addr = cpu_to_le64(dma);
+
+               while (unlikely(size > I40E_MAX_DATA_PER_TXD)) {
+                       tx_desc->cmd_type_offset_bsz =
+                               build_ctob(td_cmd, td_offset,
+                                          I40E_MAX_DATA_PER_TXD, td_tag);
+
+                       tx_desc++;
+                       i++;
+                       if (i == tx_ring->count) {
+                               tx_desc = I40E_TX_DESC(tx_ring, 0);
+                               i = 0;
+                       }
+
+                       dma += I40E_MAX_DATA_PER_TXD;
+                       size -= I40E_MAX_DATA_PER_TXD;
+
+                       tx_desc->buffer_addr = cpu_to_le64(dma);
+               }
+
+               if (likely(!data_len))
+                       break;
+
+               tx_desc->cmd_type_offset_bsz = build_ctob(td_cmd, td_offset,
+                                                         size, td_tag);
+
+               tx_desc++;
+               i++;
+               if (i == tx_ring->count) {
+                       tx_desc = I40E_TX_DESC(tx_ring, 0);
+                       i = 0;
+               }
+
+               size = skb_frag_size(frag);
+               data_len -= size;
+
+               dma = skb_frag_dma_map(tx_ring->dev, frag, 0, size,
+                                      DMA_TO_DEVICE);
+
+               tx_bi = &tx_ring->tx_bi[i];
+       }
+
+       tx_desc->cmd_type_offset_bsz =
+               build_ctob(td_cmd, td_offset, size, td_tag) |
+               cpu_to_le64((u64)I40E_TXD_CMD << I40E_TXD_QW1_CMD_SHIFT);
+
+       netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev,
+                                                tx_ring->queue_index),
+                            first->bytecount);
+
+       /* set the timestamp */
+       first->time_stamp = jiffies;
+
+       /* Force memory writes to complete before letting h/w
+        * know there are new descriptors to fetch.  (Only
+        * applicable for weak-ordered memory model archs,
+        * such as IA-64).
+        */
+       wmb();
+
+       /* set next_to_watch value indicating a packet is present */
+       first->next_to_watch = tx_desc;
+
+       i++;
+       if (i == tx_ring->count)
+               i = 0;
+
+       tx_ring->next_to_use = i;
+
+       /* notify HW of packet */
+       writel(i, tx_ring->tail);
+
+       return;
+
+dma_error:
+       dev_info(tx_ring->dev, "TX DMA map failed\n");
+
+       /* clear dma mappings for failed tx_bi map */
+       for (;;) {
+               tx_bi = &tx_ring->tx_bi[i];
+               i40e_unmap_and_free_tx_resource(tx_ring, tx_bi);
+               if (tx_bi == first)
+                       break;
+               if (i == 0)
+                       i = tx_ring->count;
+               i--;
+       }
+
+       tx_ring->next_to_use = i;
+}
+
+/**
+ * __i40e_maybe_stop_tx - 2nd level check for tx stop conditions
+ * @tx_ring: the ring to be checked
+ * @size:    the size buffer we want to assure is available
+ *
+ * Returns -EBUSY if a stop is needed, else 0
+ **/
+static inline int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+{
+       netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+       /* Memory barrier before checking head and tail */
+       smp_mb();
+
+       /* Check again in a case another CPU has just made room available. */
+       if (likely(I40E_DESC_UNUSED(tx_ring) < size))
+               return -EBUSY;
+
+       /* A reprieve! - use start_queue because it doesn't call schedule */
+       netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
+       ++tx_ring->tx_stats.restart_queue;
+       return 0;
+}
+
+/**
+ * i40e_maybe_stop_tx - 1st level check for tx stop conditions
+ * @tx_ring: the ring to be checked
+ * @size:    the size buffer we want to assure is available
+ *
+ * Returns 0 if stop is not needed
+ **/
+static int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+{
+       if (likely(I40E_DESC_UNUSED(tx_ring) >= size))
+               return 0;
+       return __i40e_maybe_stop_tx(tx_ring, size);
+}
+
+/**
+ * i40e_xmit_descriptor_count - calculate number of tx descriptors needed
+ * @skb:     send buffer
+ * @tx_ring: ring to send buffer on
+ *
+ * Returns number of data descriptors needed for this skb. Returns 0 to indicate
+ * there is not enough descriptors available in this ring since we need at least
+ * one descriptor.
+ **/
+static int i40e_xmit_descriptor_count(struct sk_buff *skb,
+                                     struct i40e_ring *tx_ring)
+{
+#if PAGE_SIZE > I40E_MAX_DATA_PER_TXD
+       unsigned int f;
+#endif
+       int count = 0;
+
+       /* need: 1 descriptor per page * PAGE_SIZE/I40E_MAX_DATA_PER_TXD,
+        *       + 1 desc for skb_head_len/I40E_MAX_DATA_PER_TXD,
+        *       + 2 desc gap to keep tail from touching head,
+        *       + 1 desc for context descriptor,
+        * otherwise try next time
+        */
+#if PAGE_SIZE > I40E_MAX_DATA_PER_TXD
+       for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
+               count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
+#else
+       count += skb_shinfo(skb)->nr_frags;
+#endif
+       count += TXD_USE_COUNT(skb_headlen(skb));
+       if (i40e_maybe_stop_tx(tx_ring, count + 3)) {
+               tx_ring->tx_stats.tx_busy++;
+               return 0;
+       }
+       return count;
+}
+
+/**
+ * i40e_xmit_frame_ring - Sends buffer on Tx ring
+ * @skb:     send buffer
+ * @tx_ring: ring to send buffer on
+ *
+ * Returns NETDEV_TX_OK if sent, else an error code
+ **/
+static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
+                                       struct i40e_ring *tx_ring)
+{
+       u64 cd_type_cmd_tso_mss = I40E_TX_DESC_DTYPE_CONTEXT;
+       u32 cd_tunneling = 0, cd_l2tag2 = 0;
+       struct i40e_tx_buffer *first;
+       u32 td_offset = 0;
+       u32 tx_flags = 0;
+       __be16 protocol;
+       u32 td_cmd = 0;
+       u8 hdr_len = 0;
+       int tso;
+       if (0 == i40e_xmit_descriptor_count(skb, tx_ring))
+               return NETDEV_TX_BUSY;
+
+       /* prepare the xmit flags */
+       if (i40e_tx_prepare_vlan_flags(skb, tx_ring, &tx_flags))
+               goto out_drop;
+
+       /* obtain protocol of skb */
+       protocol = skb->protocol;
+
+       /* record the location of the first descriptor for this packet */
+       first = &tx_ring->tx_bi[tx_ring->next_to_use];
+
+       /* setup IPv4/IPv6 offloads */
+       if (protocol == htons(ETH_P_IP))
+               tx_flags |= I40E_TX_FLAGS_IPV4;
+       else if (protocol == htons(ETH_P_IPV6))
+               tx_flags |= I40E_TX_FLAGS_IPV6;
+
+       tso = i40e_tso(tx_ring, skb, tx_flags, protocol, &hdr_len,
+                      &cd_type_cmd_tso_mss, &cd_tunneling);
+
+       if (tso < 0)
+               goto out_drop;
+       else if (tso)
+               tx_flags |= I40E_TX_FLAGS_TSO;
+
+       skb_tx_timestamp(skb);
+
+       /* always enable CRC insertion offload */
+       td_cmd |= I40E_TX_DESC_CMD_ICRC;
+
+       /* Always offload the checksum, since it's in the data descriptor */
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
+               tx_flags |= I40E_TX_FLAGS_CSUM;
+
+               i40e_tx_enable_csum(skb, tx_flags, &td_cmd, &td_offset,
+                                   tx_ring, &cd_tunneling);
+       }
+
+       i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss,
+                          cd_tunneling, cd_l2tag2);
+
+       i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
+                   td_cmd, td_offset);
+
+       i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
+
+       return NETDEV_TX_OK;
+
+out_drop:
+       dev_kfree_skb_any(skb);
+       return NETDEV_TX_OK;
+}
+
+/**
+ * i40evf_xmit_frame - Selects the correct VSI and Tx queue to send buffer
+ * @skb:    send buffer
+ * @netdev: network interface device structure
+ *
+ * Returns NETDEV_TX_OK if sent, else an error code
+ **/
+netdev_tx_t i40evf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       struct i40e_ring *tx_ring = adapter->tx_rings[skb->queue_mapping];
+
+       /* hardware can't handle really short frames, hardware padding works
+        * beyond this point
+        */
+       if (unlikely(skb->len < I40E_MIN_TX_LEN)) {
+               if (skb_pad(skb, I40E_MIN_TX_LEN - skb->len))
+                       return NETDEV_TX_OK;
+               skb->len = I40E_MIN_TX_LEN;
+               skb_set_tail_pointer(skb, I40E_MIN_TX_LEN);
+       }
+
+       return i40e_xmit_frame_ring(skb, tx_ring);
+}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
new file mode 100644 (file)
index 0000000..10bf49e
--- /dev/null
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_TXRX_H_
+#define _I40E_TXRX_H_
+
+/* Interrupt Throttling and Rate Limiting (storm control) Goodies */
+
+#define I40E_MAX_ITR               0x0FF0  /* reg uses 2 usec resolution */
+#define I40E_MIN_ITR               0x0004  /* reg uses 2 usec resolution */
+#define I40E_MAX_IRATE             0x03F
+#define I40E_MIN_IRATE             0x001
+#define I40E_IRATE_USEC_RESOLUTION 4
+#define I40E_ITR_100K              0x0005
+#define I40E_ITR_20K               0x0019
+#define I40E_ITR_8K                0x003E
+#define I40E_ITR_4K                0x007A
+#define I40E_ITR_RX_DEF            I40E_ITR_8K
+#define I40E_ITR_TX_DEF            I40E_ITR_4K
+#define I40E_ITR_DYNAMIC           0x8000  /* use top bit as a flag */
+#define I40E_MIN_INT_RATE          250     /* ~= 1000000 / (I40E_MAX_ITR * 2) */
+#define I40E_MAX_INT_RATE          500000  /* == 1000000 / (I40E_MIN_ITR * 2) */
+#define I40E_DEFAULT_IRQ_WORK      256
+#define ITR_TO_REG(setting) ((setting & ~I40E_ITR_DYNAMIC) >> 1)
+#define ITR_IS_DYNAMIC(setting) (!!(setting & I40E_ITR_DYNAMIC))
+#define ITR_REG_TO_USEC(itr_reg) (itr_reg << 1)
+
+#define I40E_QUEUE_END_OF_LIST 0x7FF
+
+/* this enum matches hardware bits and is meant to be used by DYN_CTLN
+ * registers and QINT registers or more generally anywhere in the manual
+ * mentioning ITR_INDX, ITR_NONE cannot be used as an index 'n' into any
+ * register but instead is a special value meaning "don't update" ITR0/1/2.
+ */
+enum i40e_dyn_idx_t {
+       I40E_IDX_ITR0 = 0,
+       I40E_IDX_ITR1 = 1,
+       I40E_IDX_ITR2 = 2,
+       I40E_ITR_NONE = 3       /* ITR_NONE must not be used as an index */
+};
+
+/* these are indexes into ITRN registers */
+#define I40E_RX_ITR    I40E_IDX_ITR0
+#define I40E_TX_ITR    I40E_IDX_ITR1
+#define I40E_PE_ITR    I40E_IDX_ITR2
+
+/* Supported RSS offloads */
+#define I40E_DEFAULT_RSS_HENA ( \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) | \
+       ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD))
+
+/* Supported Rx Buffer Sizes */
+#define I40E_RXBUFFER_512   512    /* Used for packet split */
+#define I40E_RXBUFFER_2048  2048
+#define I40E_RXBUFFER_3072  3072   /* For FCoE MTU of 2158 */
+#define I40E_RXBUFFER_4096  4096
+#define I40E_RXBUFFER_8192  8192
+#define I40E_MAX_RXBUFFER   9728  /* largest size for single descriptor */
+
+/* NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN means we
+ * reserve 2 more, and skb_shared_info adds an additional 384 bytes more,
+ * this adds up to 512 bytes of extra data meaning the smallest allocation
+ * we could have is 1K.
+ * i.e. RXBUFFER_512 --> size-1024 slab
+ */
+#define I40E_RX_HDR_SIZE  I40E_RXBUFFER_512
+
+/* How many Rx Buffers do we bundle into one write to the hardware ? */
+#define I40E_RX_BUFFER_WRITE   16      /* Must be power of 2 */
+#define I40E_RX_NEXT_DESC(r, i, n)             \
+       do {                                    \
+               (i)++;                          \
+               if ((i) == (r)->count)          \
+                       i = 0;                  \
+               (n) = I40E_RX_DESC((r), (i));   \
+       } while (0)
+
+#define I40E_RX_NEXT_DESC_PREFETCH(r, i, n)            \
+       do {                                            \
+               I40E_RX_NEXT_DESC((r), (i), (n));       \
+               prefetch((n));                          \
+       } while (0)
+
+#define i40e_rx_desc i40e_32byte_rx_desc
+
+#define I40E_MIN_TX_LEN                17
+#define I40E_MAX_DATA_PER_TXD  16383   /* aka 16kB - 1 */
+
+/* Tx Descriptors needed, worst case */
+#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), I40E_MAX_DATA_PER_TXD)
+#define DESC_NEEDED ((MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE)) + 4)
+
+#define I40E_TX_FLAGS_CSUM             (u32)(1)
+#define I40E_TX_FLAGS_HW_VLAN          (u32)(1 << 1)
+#define I40E_TX_FLAGS_SW_VLAN          (u32)(1 << 2)
+#define I40E_TX_FLAGS_TSO              (u32)(1 << 3)
+#define I40E_TX_FLAGS_IPV4             (u32)(1 << 4)
+#define I40E_TX_FLAGS_IPV6             (u32)(1 << 5)
+#define I40E_TX_FLAGS_FCCRC            (u32)(1 << 6)
+#define I40E_TX_FLAGS_FSO              (u32)(1 << 7)
+#define I40E_TX_FLAGS_VLAN_MASK                0xffff0000
+#define I40E_TX_FLAGS_VLAN_PRIO_MASK   0xe0000000
+#define I40E_TX_FLAGS_VLAN_PRIO_SHIFT  29
+#define I40E_TX_FLAGS_VLAN_SHIFT       16
+
+struct i40e_tx_buffer {
+       struct i40e_tx_desc *next_to_watch;
+       unsigned long time_stamp;
+       struct sk_buff *skb;
+       unsigned int bytecount;
+       unsigned short gso_segs;
+       DEFINE_DMA_UNMAP_ADDR(dma);
+       DEFINE_DMA_UNMAP_LEN(len);
+       u32 tx_flags;
+};
+
+struct i40e_rx_buffer {
+       struct sk_buff *skb;
+       dma_addr_t dma;
+       struct page *page;
+       dma_addr_t page_dma;
+       unsigned int page_offset;
+};
+
+struct i40e_queue_stats {
+       u64 packets;
+       u64 bytes;
+};
+
+struct i40e_tx_queue_stats {
+       u64 restart_queue;
+       u64 tx_busy;
+       u64 tx_done_old;
+};
+
+struct i40e_rx_queue_stats {
+       u64 non_eop_descs;
+       u64 alloc_page_failed;
+       u64 alloc_buff_failed;
+};
+
+enum i40e_ring_state_t {
+       __I40E_TX_FDIR_INIT_DONE,
+       __I40E_TX_XPS_INIT_DONE,
+       __I40E_TX_DETECT_HANG,
+       __I40E_HANG_CHECK_ARMED,
+       __I40E_RX_PS_ENABLED,
+       __I40E_RX_LRO_ENABLED,
+       __I40E_RX_16BYTE_DESC_ENABLED,
+};
+
+#define ring_is_ps_enabled(ring) \
+       test_bit(__I40E_RX_PS_ENABLED, &(ring)->state)
+#define set_ring_ps_enabled(ring) \
+       set_bit(__I40E_RX_PS_ENABLED, &(ring)->state)
+#define clear_ring_ps_enabled(ring) \
+       clear_bit(__I40E_RX_PS_ENABLED, &(ring)->state)
+#define check_for_tx_hang(ring) \
+       test_bit(__I40E_TX_DETECT_HANG, &(ring)->state)
+#define set_check_for_tx_hang(ring) \
+       set_bit(__I40E_TX_DETECT_HANG, &(ring)->state)
+#define clear_check_for_tx_hang(ring) \
+       clear_bit(__I40E_TX_DETECT_HANG, &(ring)->state)
+#define ring_is_lro_enabled(ring) \
+       test_bit(__I40E_RX_LRO_ENABLED, &(ring)->state)
+#define set_ring_lro_enabled(ring) \
+       set_bit(__I40E_RX_LRO_ENABLED, &(ring)->state)
+#define clear_ring_lro_enabled(ring) \
+       clear_bit(__I40E_RX_LRO_ENABLED, &(ring)->state)
+#define ring_is_16byte_desc_enabled(ring) \
+       test_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state)
+#define set_ring_16byte_desc_enabled(ring) \
+       set_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state)
+#define clear_ring_16byte_desc_enabled(ring) \
+       clear_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state)
+
+/* struct that defines a descriptor ring, associated with a VSI */
+struct i40e_ring {
+       struct i40e_ring *next;         /* pointer to next ring in q_vector */
+       void *desc;                     /* Descriptor ring memory */
+       struct device *dev;             /* Used for DMA mapping */
+       struct net_device *netdev;      /* netdev ring maps to */
+       union {
+               struct i40e_tx_buffer *tx_bi;
+               struct i40e_rx_buffer *rx_bi;
+       };
+       unsigned long state;
+       u16 queue_index;                /* Queue number of ring */
+       u8 dcb_tc;                      /* Traffic class of ring */
+       u8 __iomem *tail;
+
+       u16 count;                      /* Number of descriptors */
+       u16 reg_idx;                    /* HW register index of the ring */
+       u16 rx_hdr_len;
+       u16 rx_buf_len;
+       u8  dtype;
+#define I40E_RX_DTYPE_NO_SPLIT      0
+#define I40E_RX_DTYPE_SPLIT_ALWAYS  1
+#define I40E_RX_DTYPE_HEADER_SPLIT  2
+       u8  hsplit;
+#define I40E_RX_SPLIT_L2      0x1
+#define I40E_RX_SPLIT_IP      0x2
+#define I40E_RX_SPLIT_TCP_UDP 0x4
+#define I40E_RX_SPLIT_SCTP    0x8
+
+       /* used in interrupt processing */
+       u16 next_to_use;
+       u16 next_to_clean;
+
+       u8 atr_sample_rate;
+       u8 atr_count;
+
+       bool ring_active;               /* is ring online or not */
+
+       /* stats structs */
+       struct i40e_queue_stats stats;
+       struct u64_stats_sync syncp;
+       union {
+               struct i40e_tx_queue_stats tx_stats;
+               struct i40e_rx_queue_stats rx_stats;
+       };
+
+       unsigned int size;              /* length of descriptor ring in bytes */
+       dma_addr_t dma;                 /* physical address of ring */
+
+       struct i40e_vsi *vsi;           /* Backreference to associated VSI */
+       struct i40e_q_vector *q_vector; /* Backreference to associated vector */
+
+       struct rcu_head rcu;            /* to avoid race on free */
+} ____cacheline_internodealigned_in_smp;
+
+enum i40e_latency_range {
+       I40E_LOWEST_LATENCY = 0,
+       I40E_LOW_LATENCY = 1,
+       I40E_BULK_LATENCY = 2,
+};
+
+struct i40e_ring_container {
+       /* array of pointers to rings */
+       struct i40e_ring *ring;
+       unsigned int total_bytes;       /* total bytes processed this int */
+       unsigned int total_packets;     /* total packets processed this int */
+       u16 count;
+       enum i40e_latency_range latency_range;
+       u16 itr;
+};
+
+/* iterator for handling rings in ring container */
+#define i40e_for_each_ring(pos, head) \
+       for (pos = (head).ring; pos != NULL; pos = pos->next)
+
+void i40evf_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count);
+netdev_tx_t i40evf_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+void i40evf_clean_tx_ring(struct i40e_ring *tx_ring);
+void i40evf_clean_rx_ring(struct i40e_ring *rx_ring);
+int i40evf_setup_tx_descriptors(struct i40e_ring *tx_ring);
+int i40evf_setup_rx_descriptors(struct i40e_ring *rx_ring);
+void i40evf_free_tx_resources(struct i40e_ring *tx_ring);
+void i40evf_free_rx_resources(struct i40e_ring *rx_ring);
+int i40evf_napi_poll(struct napi_struct *napi, int budget);
+#endif /* _I40E_TXRX_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
new file mode 100644 (file)
index 0000000..beb3fa7
--- /dev/null
@@ -0,0 +1,1152 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_TYPE_H_
+#define _I40E_TYPE_H_
+
+#include "i40e_status.h"
+#include "i40e_osdep.h"
+#include "i40e_register.h"
+#include "i40e_adminq.h"
+#include "i40e_hmc.h"
+#include "i40e_lan_hmc.h"
+
+/* Device IDs */
+#define I40E_SFP_XL710_DEVICE_ID       0x1572
+#define I40E_SFP_X710_DEVICE_ID                0x1573
+#define I40E_QEMU_DEVICE_ID            0x1574
+#define I40E_KX_A_DEVICE_ID            0x157F
+#define I40E_KX_B_DEVICE_ID            0x1580
+#define I40E_KX_C_DEVICE_ID            0x1581
+#define I40E_KX_D_DEVICE_ID            0x1582
+#define I40E_QSFP_A_DEVICE_ID          0x1583
+#define I40E_QSFP_B_DEVICE_ID          0x1584
+#define I40E_QSFP_C_DEVICE_ID          0x1585
+#define I40E_VF_DEVICE_ID              0x154C
+#define I40E_VF_HV_DEVICE_ID           0x1571
+
+#define i40e_is_40G_device(d)          ((d) == I40E_QSFP_A_DEVICE_ID  || \
+                                        (d) == I40E_QSFP_B_DEVICE_ID  || \
+                                        (d) == I40E_QSFP_C_DEVICE_ID)
+
+#define I40E_MAX_VSI_QP                        16
+#define I40E_MAX_VF_VSI                        3
+#define I40E_MAX_CHAINED_RX_BUFFERS    5
+#define I40E_MAX_PF_UDP_OFFLOAD_PORTS  16
+
+/* Max default timeout in ms, */
+#define I40E_MAX_NVM_TIMEOUT           18000
+
+/* Switch from mc to the 2usec global time (this is the GTIME resolution) */
+#define I40E_MS_TO_GTIME(time)         (((time) * 1000) / 2)
+
+/* forward declaration */
+struct i40e_hw;
+typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *);
+
+#define ETH_ALEN       6
+
+/* Data type manipulation macros. */
+
+#define I40E_DESC_UNUSED(R)    \
+       ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
+       (R)->next_to_clean - (R)->next_to_use - 1)
+
+/* bitfields for Tx queue mapping in QTX_CTL */
+#define I40E_QTX_CTL_VF_QUEUE  0x0
+#define I40E_QTX_CTL_VM_QUEUE  0x1
+#define I40E_QTX_CTL_PF_QUEUE  0x2
+
+/* debug masks - set these bits in hw->debug_mask to control output */
+enum i40e_debug_mask {
+       I40E_DEBUG_INIT                 = 0x00000001,
+       I40E_DEBUG_RELEASE              = 0x00000002,
+
+       I40E_DEBUG_LINK                 = 0x00000010,
+       I40E_DEBUG_PHY                  = 0x00000020,
+       I40E_DEBUG_HMC                  = 0x00000040,
+       I40E_DEBUG_NVM                  = 0x00000080,
+       I40E_DEBUG_LAN                  = 0x00000100,
+       I40E_DEBUG_FLOW                 = 0x00000200,
+       I40E_DEBUG_DCB                  = 0x00000400,
+       I40E_DEBUG_DIAG                 = 0x00000800,
+
+       I40E_DEBUG_AQ_MESSAGE           = 0x01000000,
+       I40E_DEBUG_AQ_DESCRIPTOR        = 0x02000000,
+       I40E_DEBUG_AQ_DESC_BUFFER       = 0x04000000,
+       I40E_DEBUG_AQ_COMMAND           = 0x06000000,
+       I40E_DEBUG_AQ                   = 0x0F000000,
+
+       I40E_DEBUG_USER                 = 0xF0000000,
+
+       I40E_DEBUG_ALL                  = 0xFFFFFFFF
+};
+
+/* PCI Bus Info */
+#define I40E_PCI_LINK_WIDTH_1          0x10
+#define I40E_PCI_LINK_WIDTH_2          0x20
+#define I40E_PCI_LINK_WIDTH_4          0x40
+#define I40E_PCI_LINK_WIDTH_8          0x80
+#define I40E_PCI_LINK_SPEED_2500       0x1
+#define I40E_PCI_LINK_SPEED_5000       0x2
+#define I40E_PCI_LINK_SPEED_8000       0x3
+
+/* These are structs for managing the hardware information and the operations.
+ * The structures of function pointers are filled out at init time when we
+ * know for sure exactly which hardware we're working with.  This gives us the
+ * flexibility of using the same main driver code but adapting to slightly
+ * different hardware needs as new parts are developed.  For this architecture,
+ * the Firmware and AdminQ are intended to insulate the driver from most of the
+ * future changes, but these structures will also do part of the job.
+ */
+enum i40e_mac_type {
+       I40E_MAC_UNKNOWN = 0,
+       I40E_MAC_X710,
+       I40E_MAC_XL710,
+       I40E_MAC_VF,
+       I40E_MAC_GENERIC,
+};
+
+enum i40e_media_type {
+       I40E_MEDIA_TYPE_UNKNOWN = 0,
+       I40E_MEDIA_TYPE_FIBER,
+       I40E_MEDIA_TYPE_BASET,
+       I40E_MEDIA_TYPE_BACKPLANE,
+       I40E_MEDIA_TYPE_CX4,
+       I40E_MEDIA_TYPE_DA,
+       I40E_MEDIA_TYPE_VIRTUAL
+};
+
+enum i40e_fc_mode {
+       I40E_FC_NONE = 0,
+       I40E_FC_RX_PAUSE,
+       I40E_FC_TX_PAUSE,
+       I40E_FC_FULL,
+       I40E_FC_PFC,
+       I40E_FC_DEFAULT
+};
+
+enum i40e_vsi_type {
+       I40E_VSI_MAIN = 0,
+       I40E_VSI_VMDQ1,
+       I40E_VSI_VMDQ2,
+       I40E_VSI_CTRL,
+       I40E_VSI_FCOE,
+       I40E_VSI_MIRROR,
+       I40E_VSI_SRIOV,
+       I40E_VSI_FDIR,
+       I40E_VSI_TYPE_UNKNOWN
+};
+
+enum i40e_queue_type {
+       I40E_QUEUE_TYPE_RX = 0,
+       I40E_QUEUE_TYPE_TX,
+       I40E_QUEUE_TYPE_PE_CEQ,
+       I40E_QUEUE_TYPE_UNKNOWN
+};
+
+struct i40e_link_status {
+       enum i40e_aq_phy_type phy_type;
+       enum i40e_aq_link_speed link_speed;
+       u8 link_info;
+       u8 an_info;
+       u8 ext_info;
+       u8 loopback;
+       /* is Link Status Event notification to SW enabled */
+       bool lse_enable;
+};
+
+struct i40e_phy_info {
+       struct i40e_link_status link_info;
+       struct i40e_link_status link_info_old;
+       u32 autoneg_advertised;
+       u32 phy_id;
+       u32 module_type;
+       bool get_link_info;
+       enum i40e_media_type media_type;
+};
+
+#define I40E_HW_CAP_MAX_GPIO                   30
+/* Capabilities of a PF or a VF or the whole device */
+struct i40e_hw_capabilities {
+       u32  switch_mode;
+#define I40E_NVM_IMAGE_TYPE_EVB                0x0
+#define I40E_NVM_IMAGE_TYPE_CLOUD      0x2
+#define I40E_NVM_IMAGE_TYPE_UDP_CLOUD  0x3
+
+       u32  management_mode;
+       u32  npar_enable;
+       u32  os2bmc;
+       u32  valid_functions;
+       bool sr_iov_1_1;
+       bool vmdq;
+       bool evb_802_1_qbg; /* Edge Virtual Bridging */
+       bool evb_802_1_qbh; /* Bridge Port Extension */
+       bool dcb;
+       bool fcoe;
+       bool mfp_mode_1;
+       bool mgmt_cem;
+       bool ieee_1588;
+       bool iwarp;
+       bool fd;
+       u32 fd_filters_guaranteed;
+       u32 fd_filters_best_effort;
+       bool rss;
+       u32 rss_table_size;
+       u32 rss_table_entry_width;
+       bool led[I40E_HW_CAP_MAX_GPIO];
+       bool sdp[I40E_HW_CAP_MAX_GPIO];
+       u32 nvm_image_type;
+       u32 num_flow_director_filters;
+       u32 num_vfs;
+       u32 vf_base_id;
+       u32 num_vsis;
+       u32 num_rx_qp;
+       u32 num_tx_qp;
+       u32 base_queue;
+       u32 num_msix_vectors;
+       u32 num_msix_vectors_vf;
+       u32 led_pin_num;
+       u32 sdp_pin_num;
+       u32 mdio_port_num;
+       u32 mdio_port_mode;
+       u8 rx_buf_chain_len;
+       u32 enabled_tcmap;
+       u32 maxtc;
+};
+
+struct i40e_mac_info {
+       enum i40e_mac_type type;
+       u8 addr[ETH_ALEN];
+       u8 perm_addr[ETH_ALEN];
+       u8 san_addr[ETH_ALEN];
+       u16 max_fcoeq;
+};
+
+enum i40e_aq_resources_ids {
+       I40E_NVM_RESOURCE_ID = 1
+};
+
+enum i40e_aq_resource_access_type {
+       I40E_RESOURCE_READ = 1,
+       I40E_RESOURCE_WRITE
+};
+
+struct i40e_nvm_info {
+       u64 hw_semaphore_timeout; /* 2usec global time (GTIME resolution) */
+       u64 hw_semaphore_wait;    /* - || - */
+       u32 timeout;              /* [ms] */
+       u16 sr_size;              /* Shadow RAM size in words */
+       bool blank_nvm_mode;      /* is NVM empty (no FW present)*/
+       u16 version;              /* NVM package version */
+       u32 eetrack;              /* NVM data version */
+};
+
+/* PCI bus types */
+enum i40e_bus_type {
+       i40e_bus_type_unknown = 0,
+       i40e_bus_type_pci,
+       i40e_bus_type_pcix,
+       i40e_bus_type_pci_express,
+       i40e_bus_type_reserved
+};
+
+/* PCI bus speeds */
+enum i40e_bus_speed {
+       i40e_bus_speed_unknown  = 0,
+       i40e_bus_speed_33       = 33,
+       i40e_bus_speed_66       = 66,
+       i40e_bus_speed_100      = 100,
+       i40e_bus_speed_120      = 120,
+       i40e_bus_speed_133      = 133,
+       i40e_bus_speed_2500     = 2500,
+       i40e_bus_speed_5000     = 5000,
+       i40e_bus_speed_8000     = 8000,
+       i40e_bus_speed_reserved
+};
+
+/* PCI bus widths */
+enum i40e_bus_width {
+       i40e_bus_width_unknown  = 0,
+       i40e_bus_width_pcie_x1  = 1,
+       i40e_bus_width_pcie_x2  = 2,
+       i40e_bus_width_pcie_x4  = 4,
+       i40e_bus_width_pcie_x8  = 8,
+       i40e_bus_width_32       = 32,
+       i40e_bus_width_64       = 64,
+       i40e_bus_width_reserved
+};
+
+/* Bus parameters */
+struct i40e_bus_info {
+       enum i40e_bus_speed speed;
+       enum i40e_bus_width width;
+       enum i40e_bus_type type;
+
+       u16 func;
+       u16 device;
+       u16 lan_id;
+};
+
+/* Flow control (FC) parameters */
+struct i40e_fc_info {
+       enum i40e_fc_mode current_mode; /* FC mode in effect */
+       enum i40e_fc_mode requested_mode; /* FC mode requested by caller */
+};
+
+#define I40E_MAX_TRAFFIC_CLASS         8
+#define I40E_MAX_USER_PRIORITY         8
+#define I40E_DCBX_MAX_APPS             32
+#define I40E_LLDPDU_SIZE               1500
+
+/* IEEE 802.1Qaz ETS Configuration data */
+struct i40e_ieee_ets_config {
+       u8 willing;
+       u8 cbs;
+       u8 maxtcs;
+       u8 prioritytable[I40E_MAX_TRAFFIC_CLASS];
+       u8 tcbwtable[I40E_MAX_TRAFFIC_CLASS];
+       u8 tsatable[I40E_MAX_TRAFFIC_CLASS];
+};
+
+/* IEEE 802.1Qaz ETS Recommendation data */
+struct i40e_ieee_ets_recommend {
+       u8 prioritytable[I40E_MAX_TRAFFIC_CLASS];
+       u8 tcbwtable[I40E_MAX_TRAFFIC_CLASS];
+       u8 tsatable[I40E_MAX_TRAFFIC_CLASS];
+};
+
+/* IEEE 802.1Qaz PFC Configuration data */
+struct i40e_ieee_pfc_config {
+       u8 willing;
+       u8 mbc;
+       u8 pfccap;
+       u8 pfcenable;
+};
+
+/* IEEE 802.1Qaz Application Priority data */
+struct i40e_ieee_app_priority_table {
+       u8  priority;
+       u8  selector;
+       u16 protocolid;
+};
+
+struct i40e_dcbx_config {
+       u32 numapps;
+       struct i40e_ieee_ets_config etscfg;
+       struct i40e_ieee_ets_recommend etsrec;
+       struct i40e_ieee_pfc_config pfc;
+       struct i40e_ieee_app_priority_table app[I40E_DCBX_MAX_APPS];
+};
+
+/* Port hardware description */
+struct i40e_hw {
+       u8 __iomem *hw_addr;
+       void *back;
+
+       /* function pointer structs */
+       struct i40e_phy_info phy;
+       struct i40e_mac_info mac;
+       struct i40e_bus_info bus;
+       struct i40e_nvm_info nvm;
+       struct i40e_fc_info fc;
+
+       /* pci info */
+       u16 device_id;
+       u16 vendor_id;
+       u16 subsystem_device_id;
+       u16 subsystem_vendor_id;
+       u8 revision_id;
+       u8 port;
+       bool adapter_stopped;
+
+       /* capabilities for entire device and PCI func */
+       struct i40e_hw_capabilities dev_caps;
+       struct i40e_hw_capabilities func_caps;
+
+       /* Flow Director shared filter space */
+       u16 fdir_shared_filter_count;
+
+       /* device profile info */
+       u8  pf_id;
+       u16 main_vsi_seid;
+
+       /* Closest numa node to the device */
+       u16 numa_node;
+
+       /* Admin Queue info */
+       struct i40e_adminq_info aq;
+
+       /* HMC info */
+       struct i40e_hmc_info hmc; /* HMC info struct */
+
+       /* LLDP/DCBX Status */
+       u16 dcbx_status;
+
+       /* DCBX info */
+       struct i40e_dcbx_config local_dcbx_config;
+       struct i40e_dcbx_config remote_dcbx_config;
+
+       /* debug mask */
+       u32 debug_mask;
+};
+
+struct i40e_driver_version {
+       u8 major_version;
+       u8 minor_version;
+       u8 build_version;
+       u8 subbuild_version;
+};
+
+/* RX Descriptors */
+union i40e_16byte_rx_desc {
+       struct {
+               __le64 pkt_addr; /* Packet buffer address */
+               __le64 hdr_addr; /* Header buffer address */
+       } read;
+       struct {
+               struct {
+                       struct {
+                               union {
+                                       __le16 mirroring_status;
+                                       __le16 fcoe_ctx_id;
+                               } mirr_fcoe;
+                               __le16 l2tag1;
+                       } lo_dword;
+                       union {
+                               __le32 rss; /* RSS Hash */
+                               __le32 fd_id; /* Flow director filter id */
+                               __le32 fcoe_param; /* FCoE DDP Context id */
+                       } hi_dword;
+               } qword0;
+               struct {
+                       /* ext status/error/pktype/length */
+                       __le64 status_error_len;
+               } qword1;
+       } wb;  /* writeback */
+};
+
+union i40e_32byte_rx_desc {
+       struct {
+               __le64  pkt_addr; /* Packet buffer address */
+               __le64  hdr_addr; /* Header buffer address */
+                       /* bit 0 of hdr_buffer_addr is DD bit */
+               __le64  rsvd1;
+               __le64  rsvd2;
+       } read;
+       struct {
+               struct {
+                       struct {
+                               union {
+                                       __le16 mirroring_status;
+                                       __le16 fcoe_ctx_id;
+                               } mirr_fcoe;
+                               __le16 l2tag1;
+                       } lo_dword;
+                       union {
+                               __le32 rss; /* RSS Hash */
+                               __le32 fcoe_param; /* FCoE DDP Context id */
+                       } hi_dword;
+               } qword0;
+               struct {
+                       /* status/error/pktype/length */
+                       __le64 status_error_len;
+               } qword1;
+               struct {
+                       __le16 ext_status; /* extended status */
+                       __le16 rsvd;
+                       __le16 l2tag2_1;
+                       __le16 l2tag2_2;
+               } qword2;
+               struct {
+                       union {
+                               __le32 flex_bytes_lo;
+                               __le32 pe_status;
+                       } lo_dword;
+                       union {
+                               __le32 flex_bytes_hi;
+                               __le32 fd_id;
+                       } hi_dword;
+               } qword3;
+       } wb;  /* writeback */
+};
+
+#define I40E_RXD_QW1_STATUS_SHIFT      0
+#define I40E_RXD_QW1_STATUS_MASK       (0x7FFFUL << I40E_RXD_QW1_STATUS_SHIFT)
+
+enum i40e_rx_desc_status_bits {
+       /* Note: These are predefined bit offsets */
+       I40E_RX_DESC_STATUS_DD_SHIFT            = 0,
+       I40E_RX_DESC_STATUS_EOF_SHIFT           = 1,
+       I40E_RX_DESC_STATUS_L2TAG1P_SHIFT       = 2,
+       I40E_RX_DESC_STATUS_L3L4P_SHIFT         = 3,
+       I40E_RX_DESC_STATUS_CRCP_SHIFT          = 4,
+       I40E_RX_DESC_STATUS_TSYNINDX_SHIFT      = 5, /* 2 BITS */
+       I40E_RX_DESC_STATUS_TSYNVALID_SHIFT     = 7,
+       I40E_RX_DESC_STATUS_PIF_SHIFT           = 8,
+       I40E_RX_DESC_STATUS_UMBCAST_SHIFT       = 9, /* 2 BITS */
+       I40E_RX_DESC_STATUS_FLM_SHIFT           = 11,
+       I40E_RX_DESC_STATUS_FLTSTAT_SHIFT       = 12, /* 2 BITS */
+       I40E_RX_DESC_STATUS_LPBK_SHIFT          = 14,
+       I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT     = 15,
+       I40E_RX_DESC_STATUS_RESERVED_SHIFT      = 16, /* 2 BITS */
+       I40E_RX_DESC_STATUS_UDP_0_SHIFT         = 18
+};
+
+#define I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT   I40E_RX_DESC_STATUS_TSYNINDX_SHIFT
+#define I40E_RXD_QW1_STATUS_TSYNINDX_MASK      (0x3UL << \
+                                            I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT)
+
+#define I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT  I40E_RX_DESC_STATUS_TSYNVALID_SHIFT
+#define I40E_RXD_QW1_STATUS_TSYNVALID_MASK     (0x1UL << \
+                                        I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT)
+
+enum i40e_rx_desc_fltstat_values {
+       I40E_RX_DESC_FLTSTAT_NO_DATA    = 0,
+       I40E_RX_DESC_FLTSTAT_RSV_FD_ID  = 1, /* 16byte desc? FD_ID : RSV */
+       I40E_RX_DESC_FLTSTAT_RSV        = 2,
+       I40E_RX_DESC_FLTSTAT_RSS_HASH   = 3,
+};
+
+#define I40E_RXD_QW1_ERROR_SHIFT       19
+#define I40E_RXD_QW1_ERROR_MASK                (0xFFUL << I40E_RXD_QW1_ERROR_SHIFT)
+
+enum i40e_rx_desc_error_bits {
+       /* Note: These are predefined bit offsets */
+       I40E_RX_DESC_ERROR_RXE_SHIFT            = 0,
+       I40E_RX_DESC_ERROR_RECIPE_SHIFT         = 1,
+       I40E_RX_DESC_ERROR_HBO_SHIFT            = 2,
+       I40E_RX_DESC_ERROR_L3L4E_SHIFT          = 3, /* 3 BITS */
+       I40E_RX_DESC_ERROR_IPE_SHIFT            = 3,
+       I40E_RX_DESC_ERROR_L4E_SHIFT            = 4,
+       I40E_RX_DESC_ERROR_EIPE_SHIFT           = 5,
+       I40E_RX_DESC_ERROR_OVERSIZE_SHIFT       = 6
+};
+
+enum i40e_rx_desc_error_l3l4e_fcoe_masks {
+       I40E_RX_DESC_ERROR_L3L4E_NONE           = 0,
+       I40E_RX_DESC_ERROR_L3L4E_PROT           = 1,
+       I40E_RX_DESC_ERROR_L3L4E_FC             = 2,
+       I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR       = 3,
+       I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN      = 4
+};
+
+#define I40E_RXD_QW1_PTYPE_SHIFT       30
+#define I40E_RXD_QW1_PTYPE_MASK                (0xFFULL << I40E_RXD_QW1_PTYPE_SHIFT)
+
+/* Packet type non-ip values */
+enum i40e_rx_l2_ptype {
+       I40E_RX_PTYPE_L2_RESERVED                       = 0,
+       I40E_RX_PTYPE_L2_MAC_PAY2                       = 1,
+       I40E_RX_PTYPE_L2_TIMESYNC_PAY2                  = 2,
+       I40E_RX_PTYPE_L2_FIP_PAY2                       = 3,
+       I40E_RX_PTYPE_L2_OUI_PAY2                       = 4,
+       I40E_RX_PTYPE_L2_MACCNTRL_PAY2                  = 5,
+       I40E_RX_PTYPE_L2_LLDP_PAY2                      = 6,
+       I40E_RX_PTYPE_L2_ECP_PAY2                       = 7,
+       I40E_RX_PTYPE_L2_EVB_PAY2                       = 8,
+       I40E_RX_PTYPE_L2_QCN_PAY2                       = 9,
+       I40E_RX_PTYPE_L2_EAPOL_PAY2                     = 10,
+       I40E_RX_PTYPE_L2_ARP                            = 11,
+       I40E_RX_PTYPE_L2_FCOE_PAY3                      = 12,
+       I40E_RX_PTYPE_L2_FCOE_FCDATA_PAY3               = 13,
+       I40E_RX_PTYPE_L2_FCOE_FCRDY_PAY3                = 14,
+       I40E_RX_PTYPE_L2_FCOE_FCRSP_PAY3                = 15,
+       I40E_RX_PTYPE_L2_FCOE_FCOTHER_PA                = 16,
+       I40E_RX_PTYPE_L2_FCOE_VFT_PAY3                  = 17,
+       I40E_RX_PTYPE_L2_FCOE_VFT_FCDATA                = 18,
+       I40E_RX_PTYPE_L2_FCOE_VFT_FCRDY                 = 19,
+       I40E_RX_PTYPE_L2_FCOE_VFT_FCRSP                 = 20,
+       I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER               = 21,
+       I40E_RX_PTYPE_GRENAT4_MAC_PAY3                  = 58,
+       I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4    = 87,
+       I40E_RX_PTYPE_GRENAT6_MAC_PAY3                  = 124,
+       I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4    = 153
+};
+
+struct i40e_rx_ptype_decoded {
+       u32 ptype:8;
+       u32 known:1;
+       u32 outer_ip:1;
+       u32 outer_ip_ver:1;
+       u32 outer_frag:1;
+       u32 tunnel_type:3;
+       u32 tunnel_end_prot:2;
+       u32 tunnel_end_frag:1;
+       u32 inner_prot:4;
+       u32 payload_layer:3;
+};
+
+enum i40e_rx_ptype_outer_ip {
+       I40E_RX_PTYPE_OUTER_L2  = 0,
+       I40E_RX_PTYPE_OUTER_IP  = 1
+};
+
+enum i40e_rx_ptype_outer_ip_ver {
+       I40E_RX_PTYPE_OUTER_NONE        = 0,
+       I40E_RX_PTYPE_OUTER_IPV4        = 0,
+       I40E_RX_PTYPE_OUTER_IPV6        = 1
+};
+
+enum i40e_rx_ptype_outer_fragmented {
+       I40E_RX_PTYPE_NOT_FRAG  = 0,
+       I40E_RX_PTYPE_FRAG      = 1
+};
+
+enum i40e_rx_ptype_tunnel_type {
+       I40E_RX_PTYPE_TUNNEL_NONE               = 0,
+       I40E_RX_PTYPE_TUNNEL_IP_IP              = 1,
+       I40E_RX_PTYPE_TUNNEL_IP_GRENAT          = 2,
+       I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC      = 3,
+       I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4,
+};
+
+enum i40e_rx_ptype_tunnel_end_prot {
+       I40E_RX_PTYPE_TUNNEL_END_NONE   = 0,
+       I40E_RX_PTYPE_TUNNEL_END_IPV4   = 1,
+       I40E_RX_PTYPE_TUNNEL_END_IPV6   = 2,
+};
+
+enum i40e_rx_ptype_inner_prot {
+       I40E_RX_PTYPE_INNER_PROT_NONE           = 0,
+       I40E_RX_PTYPE_INNER_PROT_UDP            = 1,
+       I40E_RX_PTYPE_INNER_PROT_TCP            = 2,
+       I40E_RX_PTYPE_INNER_PROT_SCTP           = 3,
+       I40E_RX_PTYPE_INNER_PROT_ICMP           = 4,
+       I40E_RX_PTYPE_INNER_PROT_TIMESYNC       = 5
+};
+
+enum i40e_rx_ptype_payload_layer {
+       I40E_RX_PTYPE_PAYLOAD_LAYER_NONE        = 0,
+       I40E_RX_PTYPE_PAYLOAD_LAYER_PAY2        = 1,
+       I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3        = 2,
+       I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4        = 3,
+};
+
+#define I40E_RXD_QW1_LENGTH_PBUF_SHIFT 38
+#define I40E_RXD_QW1_LENGTH_PBUF_MASK  (0x3FFFULL << \
+                                        I40E_RXD_QW1_LENGTH_PBUF_SHIFT)
+
+#define I40E_RXD_QW1_LENGTH_HBUF_SHIFT 52
+#define I40E_RXD_QW1_LENGTH_HBUF_MASK  (0x7FFULL << \
+                                        I40E_RXD_QW1_LENGTH_HBUF_SHIFT)
+
+#define I40E_RXD_QW1_LENGTH_SPH_SHIFT  63
+#define I40E_RXD_QW1_LENGTH_SPH_MASK   (0x1ULL << \
+                                        I40E_RXD_QW1_LENGTH_SPH_SHIFT)
+
+enum i40e_rx_desc_ext_status_bits {
+       /* Note: These are predefined bit offsets */
+       I40E_RX_DESC_EXT_STATUS_L2TAG2P_SHIFT   = 0,
+       I40E_RX_DESC_EXT_STATUS_L2TAG3P_SHIFT   = 1,
+       I40E_RX_DESC_EXT_STATUS_FLEXBL_SHIFT    = 2, /* 2 BITS */
+       I40E_RX_DESC_EXT_STATUS_FLEXBH_SHIFT    = 4, /* 2 BITS */
+       I40E_RX_DESC_EXT_STATUS_FTYPE_SHIFT     = 6, /* 3 BITS */
+       I40E_RX_DESC_EXT_STATUS_FDLONGB_SHIFT   = 9,
+       I40E_RX_DESC_EXT_STATUS_FCOELONGB_SHIFT = 10,
+       I40E_RX_DESC_EXT_STATUS_PELONGB_SHIFT   = 11,
+};
+
+enum i40e_rx_desc_pe_status_bits {
+       /* Note: These are predefined bit offsets */
+       I40E_RX_DESC_PE_STATUS_QPID_SHIFT       = 0, /* 18 BITS */
+       I40E_RX_DESC_PE_STATUS_L4PORT_SHIFT     = 0, /* 16 BITS */
+       I40E_RX_DESC_PE_STATUS_IPINDEX_SHIFT    = 16, /* 8 BITS */
+       I40E_RX_DESC_PE_STATUS_QPIDHIT_SHIFT    = 24,
+       I40E_RX_DESC_PE_STATUS_APBVTHIT_SHIFT   = 25,
+       I40E_RX_DESC_PE_STATUS_PORTV_SHIFT      = 26,
+       I40E_RX_DESC_PE_STATUS_URG_SHIFT        = 27,
+       I40E_RX_DESC_PE_STATUS_IPFRAG_SHIFT     = 28,
+       I40E_RX_DESC_PE_STATUS_IPOPT_SHIFT      = 29
+};
+
+#define I40E_RX_PROG_STATUS_DESC_LENGTH_SHIFT          38
+#define I40E_RX_PROG_STATUS_DESC_LENGTH                        0x2000000
+
+#define I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT      2
+#define I40E_RX_PROG_STATUS_DESC_QW1_PROGID_MASK       (0x7UL << \
+                               I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT)
+
+#define I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT       19
+#define I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK                (0x3FUL << \
+                               I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT)
+
+enum i40e_rx_prog_status_desc_status_bits {
+       /* Note: These are predefined bit offsets */
+       I40E_RX_PROG_STATUS_DESC_DD_SHIFT       = 0,
+       I40E_RX_PROG_STATUS_DESC_PROG_ID_SHIFT  = 2 /* 3 BITS */
+};
+
+enum i40e_rx_prog_status_desc_prog_id_masks {
+       I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS       = 1,
+       I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS  = 2,
+       I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS  = 4,
+};
+
+enum i40e_rx_prog_status_desc_error_bits {
+       /* Note: These are predefined bit offsets */
+       I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT      = 0,
+       I40E_RX_PROG_STATUS_DESC_NO_FD_QUOTA_SHIFT      = 1,
+       I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT    = 2,
+       I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT    = 3
+};
+
+/* TX Descriptor */
+struct i40e_tx_desc {
+       __le64 buffer_addr; /* Address of descriptor's data buf */
+       __le64 cmd_type_offset_bsz;
+};
+
+#define I40E_TXD_QW1_DTYPE_SHIFT       0
+#define I40E_TXD_QW1_DTYPE_MASK                (0xFUL << I40E_TXD_QW1_DTYPE_SHIFT)
+
+enum i40e_tx_desc_dtype_value {
+       I40E_TX_DESC_DTYPE_DATA         = 0x0,
+       I40E_TX_DESC_DTYPE_NOP          = 0x1, /* same as Context desc */
+       I40E_TX_DESC_DTYPE_CONTEXT      = 0x1,
+       I40E_TX_DESC_DTYPE_FCOE_CTX     = 0x2,
+       I40E_TX_DESC_DTYPE_FILTER_PROG  = 0x8,
+       I40E_TX_DESC_DTYPE_DDP_CTX      = 0x9,
+       I40E_TX_DESC_DTYPE_FLEX_DATA    = 0xB,
+       I40E_TX_DESC_DTYPE_FLEX_CTX_1   = 0xC,
+       I40E_TX_DESC_DTYPE_FLEX_CTX_2   = 0xD,
+       I40E_TX_DESC_DTYPE_DESC_DONE    = 0xF
+};
+
+#define I40E_TXD_QW1_CMD_SHIFT 4
+#define I40E_TXD_QW1_CMD_MASK  (0x3FFUL << I40E_TXD_QW1_CMD_SHIFT)
+
+enum i40e_tx_desc_cmd_bits {
+       I40E_TX_DESC_CMD_EOP                    = 0x0001,
+       I40E_TX_DESC_CMD_RS                     = 0x0002,
+       I40E_TX_DESC_CMD_ICRC                   = 0x0004,
+       I40E_TX_DESC_CMD_IL2TAG1                = 0x0008,
+       I40E_TX_DESC_CMD_DUMMY                  = 0x0010,
+       I40E_TX_DESC_CMD_IIPT_NONIP             = 0x0000, /* 2 BITS */
+       I40E_TX_DESC_CMD_IIPT_IPV6              = 0x0020, /* 2 BITS */
+       I40E_TX_DESC_CMD_IIPT_IPV4              = 0x0040, /* 2 BITS */
+       I40E_TX_DESC_CMD_IIPT_IPV4_CSUM         = 0x0060, /* 2 BITS */
+       I40E_TX_DESC_CMD_FCOET                  = 0x0080,
+       I40E_TX_DESC_CMD_L4T_EOFT_UNK           = 0x0000, /* 2 BITS */
+       I40E_TX_DESC_CMD_L4T_EOFT_TCP           = 0x0100, /* 2 BITS */
+       I40E_TX_DESC_CMD_L4T_EOFT_SCTP          = 0x0200, /* 2 BITS */
+       I40E_TX_DESC_CMD_L4T_EOFT_UDP           = 0x0300, /* 2 BITS */
+       I40E_TX_DESC_CMD_L4T_EOFT_EOF_N         = 0x0000, /* 2 BITS */
+       I40E_TX_DESC_CMD_L4T_EOFT_EOF_T         = 0x0100, /* 2 BITS */
+       I40E_TX_DESC_CMD_L4T_EOFT_EOF_NI        = 0x0200, /* 2 BITS */
+       I40E_TX_DESC_CMD_L4T_EOFT_EOF_A         = 0x0300, /* 2 BITS */
+};
+
+#define I40E_TXD_QW1_OFFSET_SHIFT      16
+#define I40E_TXD_QW1_OFFSET_MASK       (0x3FFFFULL << \
+                                        I40E_TXD_QW1_OFFSET_SHIFT)
+
+enum i40e_tx_desc_length_fields {
+       /* Note: These are predefined bit offsets */
+       I40E_TX_DESC_LENGTH_MACLEN_SHIFT        = 0, /* 7 BITS */
+       I40E_TX_DESC_LENGTH_IPLEN_SHIFT         = 7, /* 7 BITS */
+       I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT     = 14 /* 4 BITS */
+};
+
+#define I40E_TXD_QW1_TX_BUF_SZ_SHIFT   34
+#define I40E_TXD_QW1_TX_BUF_SZ_MASK    (0x3FFFULL << \
+                                        I40E_TXD_QW1_TX_BUF_SZ_SHIFT)
+
+#define I40E_TXD_QW1_L2TAG1_SHIFT      48
+#define I40E_TXD_QW1_L2TAG1_MASK       (0xFFFFULL << I40E_TXD_QW1_L2TAG1_SHIFT)
+
+/* Context descriptors */
+struct i40e_tx_context_desc {
+       __le32 tunneling_params;
+       __le16 l2tag2;
+       __le16 rsvd;
+       __le64 type_cmd_tso_mss;
+};
+
+#define I40E_TXD_CTX_QW1_DTYPE_SHIFT   0
+#define I40E_TXD_CTX_QW1_DTYPE_MASK    (0xFUL << I40E_TXD_CTX_QW1_DTYPE_SHIFT)
+
+#define I40E_TXD_CTX_QW1_CMD_SHIFT     4
+#define I40E_TXD_CTX_QW1_CMD_MASK      (0xFFFFUL << I40E_TXD_CTX_QW1_CMD_SHIFT)
+
+enum i40e_tx_ctx_desc_cmd_bits {
+       I40E_TX_CTX_DESC_TSO            = 0x01,
+       I40E_TX_CTX_DESC_TSYN           = 0x02,
+       I40E_TX_CTX_DESC_IL2TAG2        = 0x04,
+       I40E_TX_CTX_DESC_IL2TAG2_IL2H   = 0x08,
+       I40E_TX_CTX_DESC_SWTCH_NOTAG    = 0x00,
+       I40E_TX_CTX_DESC_SWTCH_UPLINK   = 0x10,
+       I40E_TX_CTX_DESC_SWTCH_LOCAL    = 0x20,
+       I40E_TX_CTX_DESC_SWTCH_VSI      = 0x30,
+       I40E_TX_CTX_DESC_SWPE           = 0x40
+};
+
+#define I40E_TXD_CTX_QW1_TSO_LEN_SHIFT 30
+#define I40E_TXD_CTX_QW1_TSO_LEN_MASK  (0x3FFFFULL << \
+                                        I40E_TXD_CTX_QW1_TSO_LEN_SHIFT)
+
+#define I40E_TXD_CTX_QW1_MSS_SHIFT     50
+#define I40E_TXD_CTX_QW1_MSS_MASK      (0x3FFFULL << \
+                                        I40E_TXD_CTX_QW1_MSS_SHIFT)
+
+#define I40E_TXD_CTX_QW1_VSI_SHIFT     50
+#define I40E_TXD_CTX_QW1_VSI_MASK      (0x1FFULL << I40E_TXD_CTX_QW1_VSI_SHIFT)
+
+#define I40E_TXD_CTX_QW0_EXT_IP_SHIFT  0
+#define I40E_TXD_CTX_QW0_EXT_IP_MASK   (0x3ULL << \
+                                        I40E_TXD_CTX_QW0_EXT_IP_SHIFT)
+
+enum i40e_tx_ctx_desc_eipt_offload {
+       I40E_TX_CTX_EXT_IP_NONE         = 0x0,
+       I40E_TX_CTX_EXT_IP_IPV6         = 0x1,
+       I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM = 0x2,
+       I40E_TX_CTX_EXT_IP_IPV4         = 0x3
+};
+
+#define I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT       2
+#define I40E_TXD_CTX_QW0_EXT_IPLEN_MASK        (0x3FULL << \
+                                        I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT)
+
+#define I40E_TXD_CTX_QW0_NATT_SHIFT    9
+#define I40E_TXD_CTX_QW0_NATT_MASK     (0x3ULL << I40E_TXD_CTX_QW0_NATT_SHIFT)
+
+#define I40E_TXD_CTX_UDP_TUNNELING     (0x1ULL << I40E_TXD_CTX_QW0_NATT_SHIFT)
+#define I40E_TXD_CTX_GRE_TUNNELING     (0x2ULL << I40E_TXD_CTX_QW0_NATT_SHIFT)
+
+#define I40E_TXD_CTX_QW0_EIP_NOINC_SHIFT       11
+#define I40E_TXD_CTX_QW0_EIP_NOINC_MASK        (0x1ULL << \
+                                        I40E_TXD_CTX_QW0_EIP_NOINC_SHIFT)
+
+#define I40E_TXD_CTX_EIP_NOINC_IPID_CONST      I40E_TXD_CTX_QW0_EIP_NOINC_MASK
+
+#define I40E_TXD_CTX_QW0_NATLEN_SHIFT  12
+#define I40E_TXD_CTX_QW0_NATLEN_MASK   (0X7FULL << \
+                                        I40E_TXD_CTX_QW0_NATLEN_SHIFT)
+
+#define I40E_TXD_CTX_QW0_DECTTL_SHIFT  19
+#define I40E_TXD_CTX_QW0_DECTTL_MASK   (0xFULL << \
+                                        I40E_TXD_CTX_QW0_DECTTL_SHIFT)
+
+struct i40e_filter_program_desc {
+       __le32 qindex_flex_ptype_vsi;
+       __le32 rsvd;
+       __le32 dtype_cmd_cntindex;
+       __le32 fd_id;
+};
+#define I40E_TXD_FLTR_QW0_QINDEX_SHIFT 0
+#define I40E_TXD_FLTR_QW0_QINDEX_MASK  (0x7FFUL << \
+                                        I40E_TXD_FLTR_QW0_QINDEX_SHIFT)
+#define I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT        11
+#define I40E_TXD_FLTR_QW0_FLEXOFF_MASK (0x7UL << \
+                                        I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT)
+#define I40E_TXD_FLTR_QW0_PCTYPE_SHIFT 17
+#define I40E_TXD_FLTR_QW0_PCTYPE_MASK  (0x3FUL << \
+                                        I40E_TXD_FLTR_QW0_PCTYPE_SHIFT)
+
+/* Packet Classifier Types for filters */
+enum i40e_filter_pctype {
+       /* Note: Values 0-28 are reserved for future use */
+       I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP        = 29,
+       I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP      = 30,
+       I40E_FILTER_PCTYPE_NONF_IPV4_UDP                = 31,
+       I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN            = 32,
+       I40E_FILTER_PCTYPE_NONF_IPV4_TCP                = 33,
+       I40E_FILTER_PCTYPE_NONF_IPV4_SCTP               = 34,
+       I40E_FILTER_PCTYPE_NONF_IPV4_OTHER              = 35,
+       I40E_FILTER_PCTYPE_FRAG_IPV4                    = 36,
+       /* Note: Values 37-38 are reserved for future use */
+       I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP        = 39,
+       I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP      = 40,
+       I40E_FILTER_PCTYPE_NONF_IPV6_UDP                = 41,
+       I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN            = 42,
+       I40E_FILTER_PCTYPE_NONF_IPV6_TCP                = 43,
+       I40E_FILTER_PCTYPE_NONF_IPV6_SCTP               = 44,
+       I40E_FILTER_PCTYPE_NONF_IPV6_OTHER              = 45,
+       I40E_FILTER_PCTYPE_FRAG_IPV6                    = 46,
+       /* Note: Value 47 is reserved for future use */
+       I40E_FILTER_PCTYPE_FCOE_OX                      = 48,
+       I40E_FILTER_PCTYPE_FCOE_RX                      = 49,
+       I40E_FILTER_PCTYPE_FCOE_OTHER                   = 50,
+       /* Note: Values 51-62 are reserved for future use */
+       I40E_FILTER_PCTYPE_L2_PAYLOAD                   = 63,
+};
+
+enum i40e_filter_program_desc_dest {
+       I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET               = 0x0,
+       I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX      = 0x1,
+       I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER       = 0x2,
+};
+
+enum i40e_filter_program_desc_fd_status {
+       I40E_FILTER_PROGRAM_DESC_FD_STATUS_NONE                 = 0x0,
+       I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID                = 0x1,
+       I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID_4FLEX_BYTES    = 0x2,
+       I40E_FILTER_PROGRAM_DESC_FD_STATUS_8FLEX_BYTES          = 0x3,
+};
+
+#define I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT       23
+#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK        (0x1FFUL << \
+                                        I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT)
+
+#define I40E_TXD_FLTR_QW1_CMD_SHIFT    4
+#define I40E_TXD_FLTR_QW1_CMD_MASK     (0xFFFFULL << \
+                                        I40E_TXD_FLTR_QW1_CMD_SHIFT)
+
+#define I40E_TXD_FLTR_QW1_PCMD_SHIFT   (0x0ULL + I40E_TXD_FLTR_QW1_CMD_SHIFT)
+#define I40E_TXD_FLTR_QW1_PCMD_MASK    (0x7ULL << I40E_TXD_FLTR_QW1_PCMD_SHIFT)
+
+enum i40e_filter_program_desc_pcmd {
+       I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE        = 0x1,
+       I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE            = 0x2,
+};
+
+#define I40E_TXD_FLTR_QW1_DEST_SHIFT   (0x3ULL + I40E_TXD_FLTR_QW1_CMD_SHIFT)
+#define I40E_TXD_FLTR_QW1_DEST_MASK    (0x3ULL << I40E_TXD_FLTR_QW1_DEST_SHIFT)
+
+#define I40E_TXD_FLTR_QW1_CNT_ENA_SHIFT        (0x7ULL + I40E_TXD_FLTR_QW1_CMD_SHIFT)
+#define I40E_TXD_FLTR_QW1_CNT_ENA_MASK (0x1ULL << \
+                                        I40E_TXD_FLTR_QW1_CNT_ENA_SHIFT)
+
+#define I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT      (0x9ULL + \
+                                                I40E_TXD_FLTR_QW1_CMD_SHIFT)
+#define I40E_TXD_FLTR_QW1_FD_STATUS_MASK (0x3ULL << \
+                                         I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT)
+
+#define I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT 20
+#define I40E_TXD_FLTR_QW1_CNTINDEX_MASK        (0x1FFUL << \
+                                        I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT)
+
+enum i40e_filter_type {
+       I40E_FLOW_DIRECTOR_FLTR = 0,
+       I40E_PE_QUAD_HASH_FLTR = 1,
+       I40E_ETHERTYPE_FLTR,
+       I40E_FCOE_CTX_FLTR,
+       I40E_MAC_VLAN_FLTR,
+       I40E_HASH_FLTR
+};
+
+struct i40e_vsi_context {
+       u16 seid;
+       u16 uplink_seid;
+       u16 vsi_number;
+       u16 vsis_allocated;
+       u16 vsis_unallocated;
+       u16 flags;
+       u8 pf_num;
+       u8 vf_num;
+       u8 connection_type;
+       struct i40e_aqc_vsi_properties_data info;
+};
+
+/* Statistics collected by each port, VSI, VEB, and S-channel */
+struct i40e_eth_stats {
+       u64 rx_bytes;                   /* gorc */
+       u64 rx_unicast;                 /* uprc */
+       u64 rx_multicast;               /* mprc */
+       u64 rx_broadcast;               /* bprc */
+       u64 rx_discards;                /* rdpc */
+       u64 rx_errors;                  /* repc */
+       u64 rx_missed;                  /* rmpc */
+       u64 rx_unknown_protocol;        /* rupp */
+       u64 tx_bytes;                   /* gotc */
+       u64 tx_unicast;                 /* uptc */
+       u64 tx_multicast;               /* mptc */
+       u64 tx_broadcast;               /* bptc */
+       u64 tx_discards;                /* tdpc */
+       u64 tx_errors;                  /* tepc */
+};
+
+/* Statistics collected by the MAC */
+struct i40e_hw_port_stats {
+       /* eth stats collected by the port */
+       struct i40e_eth_stats eth;
+
+       /* additional port specific stats */
+       u64 tx_dropped_link_down;       /* tdold */
+       u64 crc_errors;                 /* crcerrs */
+       u64 illegal_bytes;              /* illerrc */
+       u64 error_bytes;                /* errbc */
+       u64 mac_local_faults;           /* mlfc */
+       u64 mac_remote_faults;          /* mrfc */
+       u64 rx_length_errors;           /* rlec */
+       u64 link_xon_rx;                /* lxonrxc */
+       u64 link_xoff_rx;               /* lxoffrxc */
+       u64 priority_xon_rx[8];         /* pxonrxc[8] */
+       u64 priority_xoff_rx[8];        /* pxoffrxc[8] */
+       u64 link_xon_tx;                /* lxontxc */
+       u64 link_xoff_tx;               /* lxofftxc */
+       u64 priority_xon_tx[8];         /* pxontxc[8] */
+       u64 priority_xoff_tx[8];        /* pxofftxc[8] */
+       u64 priority_xon_2_xoff[8];     /* pxon2offc[8] */
+       u64 rx_size_64;                 /* prc64 */
+       u64 rx_size_127;                /* prc127 */
+       u64 rx_size_255;                /* prc255 */
+       u64 rx_size_511;                /* prc511 */
+       u64 rx_size_1023;               /* prc1023 */
+       u64 rx_size_1522;               /* prc1522 */
+       u64 rx_size_big;                /* prc9522 */
+       u64 rx_undersize;               /* ruc */
+       u64 rx_fragments;               /* rfc */
+       u64 rx_oversize;                /* roc */
+       u64 rx_jabber;                  /* rjc */
+       u64 tx_size_64;                 /* ptc64 */
+       u64 tx_size_127;                /* ptc127 */
+       u64 tx_size_255;                /* ptc255 */
+       u64 tx_size_511;                /* ptc511 */
+       u64 tx_size_1023;               /* ptc1023 */
+       u64 tx_size_1522;               /* ptc1522 */
+       u64 tx_size_big;                /* ptc9522 */
+       u64 mac_short_packet_dropped;   /* mspdc */
+       u64 checksum_error;             /* xec */
+};
+
+/* Checksum and Shadow RAM pointers */
+#define I40E_SR_NVM_CONTROL_WORD               0x00
+#define I40E_SR_EMP_MODULE_PTR                 0x0F
+#define I40E_SR_NVM_IMAGE_VERSION              0x18
+#define I40E_SR_NVM_WAKE_ON_LAN                        0x19
+#define I40E_SR_ALTERNATE_SAN_MAC_ADDRESS_PTR  0x27
+#define I40E_SR_NVM_EETRACK_LO                 0x2D
+#define I40E_SR_NVM_EETRACK_HI                 0x2E
+#define I40E_SR_VPD_PTR                                0x2F
+#define I40E_SR_PCIE_ALT_AUTO_LOAD_PTR         0x3E
+#define I40E_SR_SW_CHECKSUM_WORD               0x3F
+
+/* Auxiliary field, mask and shift definition for Shadow RAM and NVM Flash */
+#define I40E_SR_VPD_MODULE_MAX_SIZE            1024
+#define I40E_SR_PCIE_ALT_MODULE_MAX_SIZE       1024
+#define I40E_SR_CONTROL_WORD_1_SHIFT           0x06
+#define I40E_SR_CONTROL_WORD_1_MASK    (0x03 << I40E_SR_CONTROL_WORD_1_SHIFT)
+
+/* Shadow RAM related */
+#define I40E_SR_SECTOR_SIZE_IN_WORDS   0x800
+#define I40E_SR_WORDS_IN_1KB           512
+/* Checksum should be calculated such that after adding all the words,
+ * including the checksum word itself, the sum should be 0xBABA.
+ */
+#define I40E_SR_SW_CHECKSUM_BASE       0xBABA
+
+#define I40E_SRRD_SRCTL_ATTEMPTS       100000
+
+enum i40e_switch_element_types {
+       I40E_SWITCH_ELEMENT_TYPE_MAC    = 1,
+       I40E_SWITCH_ELEMENT_TYPE_PF     = 2,
+       I40E_SWITCH_ELEMENT_TYPE_VF     = 3,
+       I40E_SWITCH_ELEMENT_TYPE_EMP    = 4,
+       I40E_SWITCH_ELEMENT_TYPE_BMC    = 6,
+       I40E_SWITCH_ELEMENT_TYPE_PE     = 16,
+       I40E_SWITCH_ELEMENT_TYPE_VEB    = 17,
+       I40E_SWITCH_ELEMENT_TYPE_PA     = 18,
+       I40E_SWITCH_ELEMENT_TYPE_VSI    = 19,
+};
+
+/* Supported EtherType filters */
+enum i40e_ether_type_index {
+       I40E_ETHER_TYPE_1588            = 0,
+       I40E_ETHER_TYPE_FIP             = 1,
+       I40E_ETHER_TYPE_OUI_EXTENDED    = 2,
+       I40E_ETHER_TYPE_MAC_CONTROL     = 3,
+       I40E_ETHER_TYPE_LLDP            = 4,
+       I40E_ETHER_TYPE_EVB_PROTOCOL1   = 5,
+       I40E_ETHER_TYPE_EVB_PROTOCOL2   = 6,
+       I40E_ETHER_TYPE_QCN_CNM         = 7,
+       I40E_ETHER_TYPE_8021X           = 8,
+       I40E_ETHER_TYPE_ARP             = 9,
+       I40E_ETHER_TYPE_RSV1            = 10,
+       I40E_ETHER_TYPE_RSV2            = 11,
+};
+
+/* Filter context base size is 1K */
+#define I40E_HASH_FILTER_BASE_SIZE     1024
+/* Supported Hash filter values */
+enum i40e_hash_filter_size {
+       I40E_HASH_FILTER_SIZE_1K        = 0,
+       I40E_HASH_FILTER_SIZE_2K        = 1,
+       I40E_HASH_FILTER_SIZE_4K        = 2,
+       I40E_HASH_FILTER_SIZE_8K        = 3,
+       I40E_HASH_FILTER_SIZE_16K       = 4,
+       I40E_HASH_FILTER_SIZE_32K       = 5,
+       I40E_HASH_FILTER_SIZE_64K       = 6,
+       I40E_HASH_FILTER_SIZE_128K      = 7,
+       I40E_HASH_FILTER_SIZE_256K      = 8,
+       I40E_HASH_FILTER_SIZE_512K      = 9,
+       I40E_HASH_FILTER_SIZE_1M        = 10,
+};
+
+/* DMA context base size is 0.5K */
+#define I40E_DMA_CNTX_BASE_SIZE                512
+/* Supported DMA context values */
+enum i40e_dma_cntx_size {
+       I40E_DMA_CNTX_SIZE_512          = 0,
+       I40E_DMA_CNTX_SIZE_1K           = 1,
+       I40E_DMA_CNTX_SIZE_2K           = 2,
+       I40E_DMA_CNTX_SIZE_4K           = 3,
+       I40E_DMA_CNTX_SIZE_8K           = 4,
+       I40E_DMA_CNTX_SIZE_16K          = 5,
+       I40E_DMA_CNTX_SIZE_32K          = 6,
+       I40E_DMA_CNTX_SIZE_64K          = 7,
+       I40E_DMA_CNTX_SIZE_128K         = 8,
+       I40E_DMA_CNTX_SIZE_256K         = 9,
+};
+
+/* Supported Hash look up table (LUT) sizes */
+enum i40e_hash_lut_size {
+       I40E_HASH_LUT_SIZE_128          = 0,
+       I40E_HASH_LUT_SIZE_512          = 1,
+};
+
+/* Structure to hold a per PF filter control settings */
+struct i40e_filter_control_settings {
+       /* number of PE Quad Hash filter buckets */
+       enum i40e_hash_filter_size pe_filt_num;
+       /* number of PE Quad Hash contexts */
+       enum i40e_dma_cntx_size pe_cntx_num;
+       /* number of FCoE filter buckets */
+       enum i40e_hash_filter_size fcoe_filt_num;
+       /* number of FCoE DDP contexts */
+       enum i40e_dma_cntx_size fcoe_cntx_num;
+       /* size of the Hash LUT */
+       enum i40e_hash_lut_size hash_lut_size;
+       /* enable FDIR filters for PF and its VFs */
+       bool enable_fdir;
+       /* enable Ethertype filters for PF and its VFs */
+       bool enable_ethtype;
+       /* enable MAC/VLAN filters for PF and its VFs */
+       bool enable_macvlan;
+};
+
+/* Structure to hold device level control filter counts */
+struct i40e_control_filter_stats {
+       u16 mac_etype_used;   /* Used perfect match MAC/EtherType filters */
+       u16 etype_used;       /* Used perfect EtherType filters */
+       u16 mac_etype_free;   /* Un-used perfect match MAC/EtherType filters */
+       u16 etype_free;       /* Un-used perfect EtherType filters */
+};
+
+enum i40e_reset_type {
+       I40E_RESET_POR          = 0,
+       I40E_RESET_CORER        = 1,
+       I40E_RESET_GLOBR        = 2,
+       I40E_RESET_EMPR         = 3,
+};
+#endif /* _I40E_TYPE_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
new file mode 100644 (file)
index 0000000..ccf45d0
--- /dev/null
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_VIRTCHNL_H_
+#define _I40E_VIRTCHNL_H_
+
+#include "i40e_type.h"
+
+/* Description:
+ * This header file describes the VF-PF communication protocol used
+ * by the various i40e drivers.
+ *
+ * Admin queue buffer usage:
+ * desc->opcode is always i40e_aqc_opc_send_msg_to_pf
+ * flags, retval, datalen, and data addr are all used normally.
+ * Firmware copies the cookie fields when sending messages between the PF and
+ * VF, but uses all other fields internally. Due to this limitation, we
+ * must send all messages as "indirect", i.e. using an external buffer.
+ *
+ * All the vsi indexes are relative to the VF. Each VF can have maximum of
+ * three VSIs. All the queue indexes are relative to the VSI.  Each VF can
+ * have a maximum of sixteen queues for all of its VSIs.
+ *
+ * The PF is required to return a status code in v_retval for all messages
+ * except RESET_VF, which does not require any response. The return value is of
+ * i40e_status_code type, defined in the i40e_type.h.
+ *
+ * In general, VF driver initialization should roughly follow the order of these
+ * opcodes. The VF driver must first validate the API version of the PF driver,
+ * then request a reset, then get resources, then configure queues and
+ * interrupts. After these operations are complete, the VF driver may start
+ * its queues, optionally add MAC and VLAN filters, and process traffic.
+ */
+
+/* Opcodes for VF-PF communication. These are placed in the v_opcode field
+ * of the virtchnl_msg structure.
+ */
+enum i40e_virtchnl_ops {
+/* VF sends req. to pf for the following
+ * ops.
+ */
+       I40E_VIRTCHNL_OP_UNKNOWN = 0,
+       I40E_VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */
+       I40E_VIRTCHNL_OP_RESET_VF,
+       I40E_VIRTCHNL_OP_GET_VF_RESOURCES,
+       I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE,
+       I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE,
+       I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+       I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
+       I40E_VIRTCHNL_OP_ENABLE_QUEUES,
+       I40E_VIRTCHNL_OP_DISABLE_QUEUES,
+       I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
+       I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
+       I40E_VIRTCHNL_OP_ADD_VLAN,
+       I40E_VIRTCHNL_OP_DEL_VLAN,
+       I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
+       I40E_VIRTCHNL_OP_GET_STATS,
+       I40E_VIRTCHNL_OP_FCOE,
+/* PF sends status change events to vfs using
+ * the following op.
+ */
+       I40E_VIRTCHNL_OP_EVENT,
+};
+
+/* Virtual channel message descriptor. This overlays the admin queue
+ * descriptor. All other data is passed in external buffers.
+ */
+
+struct i40e_virtchnl_msg {
+       u8 pad[8];                       /* AQ flags/opcode/len/retval fields */
+       enum i40e_virtchnl_ops v_opcode; /* avoid confusion with desc->opcode */
+       i40e_status v_retval;  /* ditto for desc->retval */
+       u32 vfid;                        /* used by PF when sending to VF */
+};
+
+/* Message descriptions and data structures.*/
+
+/* I40E_VIRTCHNL_OP_VERSION
+ * VF posts its version number to the PF. PF responds with its version number
+ * in the same format, along with a return code.
+ * Reply from PF has its major/minor versions also in param0 and param1.
+ * If there is a major version mismatch, then the VF cannot operate.
+ * If there is a minor version mismatch, then the VF can operate but should
+ * add a warning to the system log.
+ *
+ * This enum element MUST always be specified as == 1, regardless of other
+ * changes in the API. The PF must always respond to this message without
+ * error regardless of version mismatch.
+ */
+#define I40E_VIRTCHNL_VERSION_MAJOR            1
+#define I40E_VIRTCHNL_VERSION_MINOR            0
+struct i40e_virtchnl_version_info {
+       u32 major;
+       u32 minor;
+};
+
+/* I40E_VIRTCHNL_OP_RESET_VF
+ * VF sends this request to PF with no parameters
+ * PF does NOT respond! VF driver must delay then poll VFGEN_RSTAT register
+ * until reset completion is indicated. The admin queue must be reinitialized
+ * after this operation.
+ *
+ * When reset is complete, PF must ensure that all queues in all VSIs associated
+ * with the VF are stopped, all queue configurations in the HMC are set to 0,
+ * and all MAC and VLAN filters (except the default MAC address) on all VSIs
+ * are cleared.
+ */
+
+/* I40E_VIRTCHNL_OP_GET_VF_RESOURCES
+ * VF sends this request to PF with no parameters
+ * PF responds with an indirect message containing
+ * i40e_virtchnl_vf_resource and one or more
+ * i40e_virtchnl_vsi_resource structures.
+ */
+
+struct i40e_virtchnl_vsi_resource {
+       u16 vsi_id;
+       u16 num_queue_pairs;
+       enum i40e_vsi_type vsi_type;
+       u16 qset_handle;
+       u8 default_mac_addr[ETH_ALEN];
+};
+/* VF offload flags */
+#define I40E_VIRTCHNL_VF_OFFLOAD_L2    0x00000001
+#define I40E_VIRTCHNL_VF_OFFLOAD_FCOE  0x00000004
+#define I40E_VIRTCHNL_VF_OFFLOAD_VLAN  0x00010000
+
+struct i40e_virtchnl_vf_resource {
+       u16 num_vsis;
+       u16 num_queue_pairs;
+       u16 max_vectors;
+       u16 max_mtu;
+
+       u32 vf_offload_flags;
+       u32 max_fcoe_contexts;
+       u32 max_fcoe_filters;
+
+       struct i40e_virtchnl_vsi_resource vsi_res[1];
+};
+
+/* I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE
+ * VF sends this message to set up parameters for one TX queue.
+ * External data buffer contains one instance of i40e_virtchnl_txq_info.
+ * PF configures requested queue and returns a status code.
+ */
+
+/* Tx queue config info */
+struct i40e_virtchnl_txq_info {
+       u16 vsi_id;
+       u16 queue_id;
+       u16 ring_len;           /* number of descriptors, multiple of 8 */
+       u16 headwb_enabled;
+       u64 dma_ring_addr;
+       u64 dma_headwb_addr;
+};
+
+/* I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE
+ * VF sends this message to set up parameters for one RX queue.
+ * External data buffer contains one instance of i40e_virtchnl_rxq_info.
+ * PF configures requested queue and returns a status code.
+ */
+
+/* Rx queue config info */
+struct i40e_virtchnl_rxq_info {
+       u16 vsi_id;
+       u16 queue_id;
+       u32 ring_len;           /* number of descriptors, multiple of 32 */
+       u16 hdr_size;
+       u16 splithdr_enabled;
+       u32 databuffer_size;
+       u32 max_pkt_size;
+       u64 dma_ring_addr;
+       enum i40e_hmc_obj_rx_hsplit_0 rx_split_pos;
+};
+
+/* I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES
+ * VF sends this message to set parameters for all active TX and RX queues
+ * associated with the specified VSI.
+ * PF configures queues and returns status.
+ * If the number of queues specified is greater than the number of queues
+ * associated with the VSI, an error is returned and no queues are configured.
+ */
+struct i40e_virtchnl_queue_pair_info {
+       /* NOTE: vsi_id and queue_id should be identical for both queues. */
+       struct i40e_virtchnl_txq_info txq;
+       struct i40e_virtchnl_rxq_info rxq;
+};
+
+struct i40e_virtchnl_vsi_queue_config_info {
+       u16 vsi_id;
+       u16 num_queue_pairs;
+       struct i40e_virtchnl_queue_pair_info qpair[1];
+};
+
+/* I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP
+ * VF uses this message to map vectors to queues.
+ * The rxq_map and txq_map fields are bitmaps used to indicate which queues
+ * are to be associated with the specified vector.
+ * The "other" causes are always mapped to vector 0.
+ * PF configures interrupt mapping and returns status.
+ */
+struct i40e_virtchnl_vector_map {
+       u16 vsi_id;
+       u16 vector_id;
+       u16 rxq_map;
+       u16 txq_map;
+       u16 rxitr_idx;
+       u16 txitr_idx;
+};
+
+struct i40e_virtchnl_irq_map_info {
+       u16 num_vectors;
+       struct i40e_virtchnl_vector_map vecmap[1];
+};
+
+/* I40E_VIRTCHNL_OP_ENABLE_QUEUES
+ * I40E_VIRTCHNL_OP_DISABLE_QUEUES
+ * VF sends these message to enable or disable TX/RX queue pairs.
+ * The queues fields are bitmaps indicating which queues to act upon.
+ * (Currently, we only support 16 queues per VF, but we make the field
+ * u32 to allow for expansion.)
+ * PF performs requested action and returns status.
+ */
+struct i40e_virtchnl_queue_select {
+       u16 vsi_id;
+       u16 pad;
+       u32 rx_queues;
+       u32 tx_queues;
+};
+
+/* I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS
+ * VF sends this message in order to add one or more unicast or multicast
+ * address filters for the specified VSI.
+ * PF adds the filters and returns status.
+ */
+
+/* I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS
+ * VF sends this message in order to remove one or more unicast or multicast
+ * filters for the specified VSI.
+ * PF removes the filters and returns status.
+ */
+
+struct i40e_virtchnl_ether_addr {
+       u8 addr[ETH_ALEN];
+       u8 pad[2];
+};
+
+struct i40e_virtchnl_ether_addr_list {
+       u16 vsi_id;
+       u16 num_elements;
+       struct i40e_virtchnl_ether_addr list[1];
+};
+
+/* I40E_VIRTCHNL_OP_ADD_VLAN
+ * VF sends this message to add one or more VLAN tag filters for receives.
+ * PF adds the filters and returns status.
+ * If a port VLAN is configured by the PF, this operation will return an
+ * error to the VF.
+ */
+
+/* I40E_VIRTCHNL_OP_DEL_VLAN
+ * VF sends this message to remove one or more VLAN tag filters for receives.
+ * PF removes the filters and returns status.
+ * If a port VLAN is configured by the PF, this operation will return an
+ * error to the VF.
+ */
+
+struct i40e_virtchnl_vlan_filter_list {
+       u16 vsi_id;
+       u16 num_elements;
+       u16 vlan_id[1];
+};
+
+/* I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE
+ * VF sends VSI id and flags.
+ * PF returns status code in retval.
+ * Note: we assume that broadcast accept mode is always enabled.
+ */
+struct i40e_virtchnl_promisc_info {
+       u16 vsi_id;
+       u16 flags;
+};
+
+#define I40E_FLAG_VF_UNICAST_PROMISC   0x00000001
+#define I40E_FLAG_VF_MULTICAST_PROMISC 0x00000002
+
+/* I40E_VIRTCHNL_OP_GET_STATS
+ * VF sends this message to request stats for the selected VSI. VF uses
+ * the i40e_virtchnl_queue_select struct to specify the VSI. The queue_id
+ * field is ignored by the PF.
+ *
+ * PF replies with struct i40e_eth_stats in an external buffer.
+ */
+
+/* I40E_VIRTCHNL_OP_EVENT
+ * PF sends this message to inform the VF driver of events that may affect it.
+ * No direct response is expected from the VF, though it may generate other
+ * messages in response to this one.
+ */
+enum i40e_virtchnl_event_codes {
+       I40E_VIRTCHNL_EVENT_UNKNOWN = 0,
+       I40E_VIRTCHNL_EVENT_LINK_CHANGE,
+       I40E_VIRTCHNL_EVENT_RESET_IMPENDING,
+       I40E_VIRTCHNL_EVENT_PF_DRIVER_CLOSE,
+};
+#define I40E_PF_EVENT_SEVERITY_INFO            0
+#define I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM    255
+
+struct i40e_virtchnl_pf_event {
+       enum i40e_virtchnl_event_codes event;
+       union {
+               struct {
+                       enum i40e_aq_link_speed link_speed;
+                       bool link_status;
+               } link_event;
+       } event_data;
+
+       int severity;
+};
+
+/* The following are TBD, not necessary for LAN functionality.
+ * I40E_VIRTCHNL_OP_FCOE
+ */
+
+/* VF reset states - these are written into the RSTAT register:
+ * I40E_VFGEN_RSTAT1 on the PF
+ * I40E_VFGEN_RSTAT on the VF
+ * When the PF initiates a reset, it writes 0
+ * When the reset is complete, it writes 1
+ * When the PF detects that the VF has recovered, it writes 2
+ * VF checks this register periodically to determine if a reset has occurred,
+ * then polls it to know when the reset is complete.
+ * If either the PF or VF reads the register while the hardware
+ * is in a reset state, it will return DEADBEEF, which, when masked
+ * will result in 3.
+ */
+enum i40e_vfr_states {
+       I40E_VFR_INPROGRESS = 0,
+       I40E_VFR_COMPLETED,
+       I40E_VFR_VFACTIVE,
+       I40E_VFR_UNKNOWN,
+};
+
+#endif /* _I40E_VIRTCHNL_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
new file mode 100644 (file)
index 0000000..ff6529b
--- /dev/null
@@ -0,0 +1,321 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40EVF_H_
+#define _I40EVF_H_
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/sctp.h>
+#include <linux/ipv6.h>
+#include <net/ip6_checksum.h>
+#include <net/udp.h>
+#include <linux/sctp.h>
+
+
+#include "i40e_type.h"
+#include "i40e_virtchnl.h"
+#include "i40e_txrx.h"
+
+#define DEFAULT_DEBUG_LEVEL_SHIFT 3
+#define PFX "i40evf: "
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+       ((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
+       printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
+               __func__ , ## args)))
+
+/* dummy struct to make common code less painful */
+struct i40e_vsi {
+       struct i40evf_adapter *back;
+       struct net_device *netdev;
+       unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+       u16 seid;
+       u16 id;
+       unsigned long state;
+       int base_vector;
+       u16 work_limit;
+       /* high bit set means dynamic, use accessor routines to read/write.
+        * hardware only supports 2us resolution for the ITR registers.
+        * these values always store the USER setting, and must be converted
+        * before programming to a register.
+        */
+       u16 rx_itr_setting;
+       u16 tx_itr_setting;
+};
+
+/* How many Rx Buffers do we bundle into one write to the hardware ? */
+#define I40EVF_RX_BUFFER_WRITE 16      /* Must be power of 2 */
+#define I40EVF_DEFAULT_TXD   512
+#define I40EVF_DEFAULT_RXD   512
+#define I40EVF_MAX_TXD       4096
+#define I40EVF_MIN_TXD       64
+#define I40EVF_MAX_RXD       4096
+#define I40EVF_MIN_RXD       64
+#define I40EVF_REQ_DESCRIPTOR_MULTIPLE  8
+
+/* Supported Rx Buffer Sizes */
+#define I40EVF_RXBUFFER_64    64     /* Used for packet split */
+#define I40EVF_RXBUFFER_128   128    /* Used for packet split */
+#define I40EVF_RXBUFFER_256   256    /* Used for packet split */
+#define I40EVF_RXBUFFER_2048  2048
+#define I40EVF_MAX_RXBUFFER   16384  /* largest size for single descriptor */
+#define I40EVF_MAX_AQ_BUF_SIZE    4096
+#define I40EVF_AQ_LEN             32
+#define I40EVF_AQ_MAX_ERR         10 /* times to try before resetting AQ */
+
+#define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
+
+#define I40E_RX_DESC(R, i) (&(((union i40e_32byte_rx_desc *)((R)->desc))[i]))
+#define I40E_TX_DESC(R, i) (&(((struct i40e_tx_desc *)((R)->desc))[i]))
+#define I40E_TX_CTXTDESC(R, i) \
+       (&(((struct i40e_tx_context_desc *)((R)->desc))[i]))
+#define MAX_RX_QUEUES 8
+#define MAX_TX_QUEUES MAX_RX_QUEUES
+
+/* MAX_MSIX_Q_VECTORS of these are allocated,
+ * but we only use one per queue-specific vector.
+ */
+struct i40e_q_vector {
+       struct i40evf_adapter *adapter;
+       struct i40e_vsi *vsi;
+       struct napi_struct napi;
+       unsigned long reg_idx;
+       struct i40e_ring_container rx;
+       struct i40e_ring_container tx;
+       u32 ring_mask;
+       u8 num_ringpairs;       /* total number of ring pairs in vector */
+       int v_idx;        /* vector index in list */
+       char name[IFNAMSIZ + 9];
+       cpumask_var_t affinity_mask;
+};
+
+/* Helper macros to switch between ints/sec and what the register uses.
+ * And yes, it's the same math going both ways.  The lowest value
+ * supported by all of the i40e hardware is 8.
+ */
+#define EITR_INTS_PER_SEC_TO_REG(_eitr) \
+       ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8)
+#define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG
+
+#define I40EVF_DESC_UNUSED(R) \
+       ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
+       (R)->next_to_clean - (R)->next_to_use - 1)
+
+#define I40EVF_RX_DESC_ADV(R, i)           \
+       (&(((union i40e_adv_rx_desc *)((R).desc))[i]))
+#define I40EVF_TX_DESC_ADV(R, i)           \
+       (&(((union i40e_adv_tx_desc *)((R).desc))[i]))
+#define I40EVF_TX_CTXTDESC_ADV(R, i)       \
+       (&(((struct i40e_adv_tx_context_desc *)((R).desc))[i]))
+
+#define OTHER_VECTOR 1
+#define NONQ_VECS (OTHER_VECTOR)
+
+#define MAX_MSIX_Q_VECTORS 4
+#define MAX_MSIX_COUNT 5
+
+#define MIN_MSIX_Q_VECTORS 1
+#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NONQ_VECS)
+
+#define I40EVF_QUEUE_END_OF_LIST 0x7FF
+#define I40EVF_FREE_VECTOR 0x7FFF
+struct i40evf_mac_filter {
+       struct list_head list;
+       u8 macaddr[ETH_ALEN];
+       bool remove;            /* filter needs to be removed */
+       bool add;               /* filter needs to be added */
+};
+
+struct i40evf_vlan_filter {
+       struct list_head list;
+       u16 vlan;
+       bool remove;            /* filter needs to be removed */
+       bool add;               /* filter needs to be added */
+};
+
+/* Driver state. The order of these is important! */
+enum i40evf_state_t {
+       __I40EVF_STARTUP,               /* driver loaded, probe complete */
+       __I40EVF_FAILED,                /* PF communication failed. Fatal. */
+       __I40EVF_REMOVE,                /* driver is being unloaded */
+       __I40EVF_INIT_VERSION_CHECK,    /* aq msg sent, awaiting reply */
+       __I40EVF_INIT_GET_RESOURCES,    /* aq msg sent, awaiting reply */
+       __I40EVF_INIT_SW,               /* got resources, setting up structs */
+       /* Below here, watchdog is running */
+       __I40EVF_DOWN,                  /* ready, can be opened */
+       __I40EVF_TESTING,               /* in ethtool self-test */
+       __I40EVF_RESETTING,             /* in reset */
+       __I40EVF_RUNNING,               /* opened, working */
+};
+
+enum i40evf_critical_section_t {
+       __I40EVF_IN_CRITICAL_TASK,      /* cannot be interrupted */
+};
+/* make common code happy */
+#define __I40E_DOWN __I40EVF_DOWN
+
+/* board specific private data structure */
+struct i40evf_adapter {
+       struct timer_list watchdog_timer;
+       struct vlan_group *vlgrp;
+       struct work_struct reset_task;
+       struct work_struct adminq_task;
+       struct delayed_work init_task;
+       struct i40e_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
+       struct list_head vlan_filter_list;
+       char name[MAX_MSIX_COUNT][IFNAMSIZ + 9];
+
+       /* Interrupt Throttle Rate */
+       u32 itr_setting;
+       u16 eitr_low;
+       u16 eitr_high;
+
+       /* TX */
+       struct i40e_ring *tx_rings[I40E_MAX_VSI_QP];
+       u64 restart_queue;
+       u64 hw_csum_tx_good;
+       u64 lsc_int;
+       u64 hw_tso_ctxt;
+       u64 hw_tso6_ctxt;
+       u32 tx_timeout_count;
+       struct list_head mac_filter_list;
+#ifdef DEBUG
+       bool detect_tx_hung;
+#endif /* DEBUG */
+
+       /* RX */
+       struct i40e_ring *rx_rings[I40E_MAX_VSI_QP];
+       int txd_count;
+       int rxd_count;
+       u64 hw_csum_rx_error;
+       u64 hw_rx_no_dma_resources;
+       u64 hw_csum_rx_good;
+       u64 non_eop_descs;
+       int num_msix_vectors;
+       struct msix_entry *msix_entries;
+
+       u64 rx_hdr_split;
+
+       u32 init_state;
+       volatile unsigned long flags;
+#define I40EVF_FLAG_RX_CSUM_ENABLED              (u32)(1)
+#define I40EVF_FLAG_RX_1BUF_CAPABLE              (u32)(1 << 1)
+#define I40EVF_FLAG_RX_PS_CAPABLE                (u32)(1 << 2)
+#define I40EVF_FLAG_RX_PS_ENABLED                (u32)(1 << 3)
+#define I40EVF_FLAG_IN_NETPOLL                   (u32)(1 << 4)
+#define I40EVF_FLAG_IMIR_ENABLED                 (u32)(1 << 5)
+#define I40EVF_FLAG_MQ_CAPABLE                   (u32)(1 << 6)
+#define I40EVF_FLAG_NEED_LINK_UPDATE             (u32)(1 << 7)
+/* duplcates for common code */
+#define I40E_FLAG_FDIR_ATR_ENABLED              0
+#define I40E_FLAG_DCB_ENABLED                   0
+#define I40E_FLAG_IN_NETPOLL                    I40EVF_FLAG_IN_NETPOLL
+#define I40E_FLAG_RX_CSUM_ENABLED                I40EVF_FLAG_RX_CSUM_ENABLED
+       /* flags for admin queue service task */
+       u32 aq_required;
+       u32 aq_pending;
+#define I40EVF_FLAG_AQ_ENABLE_QUEUES           (u32)(1)
+#define I40EVF_FLAG_AQ_DISABLE_QUEUES          (u32)(1 << 1)
+#define I40EVF_FLAG_AQ_ADD_MAC_FILTER          (u32)(1 << 2)
+#define I40EVF_FLAG_AQ_ADD_VLAN_FILTER         (u32)(1 << 3)
+#define I40EVF_FLAG_AQ_DEL_MAC_FILTER          (u32)(1 << 4)
+#define I40EVF_FLAG_AQ_DEL_VLAN_FILTER         (u32)(1 << 5)
+#define I40EVF_FLAG_AQ_CONFIGURE_QUEUES                (u32)(1 << 6)
+#define I40EVF_FLAG_AQ_MAP_VECTORS             (u32)(1 << 7)
+#define I40EVF_FLAG_AQ_HANDLE_RESET            (u32)(1 << 8)
+       /* OS defined structs */
+       struct net_device *netdev;
+       struct pci_dev *pdev;
+       struct net_device_stats net_stats;
+
+       /* structs defined in i40e_vf.h */
+       struct i40e_hw hw;
+
+       enum i40evf_state_t state;
+       volatile unsigned long crit_section;
+       u64 tx_busy;
+
+       struct work_struct watchdog_task;
+       bool netdev_registered;
+       bool dev_closed;
+       bool link_up;
+       enum i40e_virtchnl_ops current_op;
+       struct i40e_virtchnl_vf_resource *vf_res; /* incl. all VSIs */
+       struct i40e_virtchnl_vsi_resource *vsi_res; /* our LAN VSI */
+       u16 msg_enable;
+       struct i40e_eth_stats current_stats;
+       struct i40e_vsi vsi;
+       u32 aq_wait_count;
+};
+
+struct i40evf_info {
+       enum i40e_mac_type      mac;
+       unsigned int            flags;
+};
+
+
+/* needed by i40evf_ethtool.c */
+extern char i40evf_driver_name[];
+extern const char i40evf_driver_version[];
+
+int i40evf_up(struct i40evf_adapter *adapter);
+void i40evf_down(struct i40evf_adapter *adapter);
+void i40evf_reinit_locked(struct i40evf_adapter *adapter);
+void i40evf_reset(struct i40evf_adapter *adapter);
+void i40evf_set_ethtool_ops(struct net_device *netdev);
+void i40evf_update_stats(struct i40evf_adapter *adapter);
+void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter);
+int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter);
+void i40evf_irq_enable_queues(struct i40evf_adapter *adapter, u32 mask);
+
+void i40e_napi_add_all(struct i40evf_adapter *adapter);
+void i40e_napi_del_all(struct i40evf_adapter *adapter);
+
+int i40evf_send_api_ver(struct i40evf_adapter *adapter);
+int i40evf_verify_api_ver(struct i40evf_adapter *adapter);
+int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter);
+int i40evf_get_vf_config(struct i40evf_adapter *adapter);
+void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush);
+void i40evf_configure_queues(struct i40evf_adapter *adapter);
+void i40evf_deconfigure_queues(struct i40evf_adapter *adapter);
+void i40evf_enable_queues(struct i40evf_adapter *adapter);
+void i40evf_disable_queues(struct i40evf_adapter *adapter);
+void i40evf_map_queues(struct i40evf_adapter *adapter);
+void i40evf_add_ether_addrs(struct i40evf_adapter *adapter);
+void i40evf_del_ether_addrs(struct i40evf_adapter *adapter);
+void i40evf_add_vlans(struct i40evf_adapter *adapter);
+void i40evf_del_vlans(struct i40evf_adapter *adapter);
+void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags);
+void i40evf_request_stats(struct i40evf_adapter *adapter);
+void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
+                               enum i40e_virtchnl_ops v_opcode,
+                               i40e_status v_retval, u8 *msg, u16 msglen);
+#endif /* _I40EVF_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
new file mode 100644 (file)
index 0000000..b0b1f4b
--- /dev/null
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+/* ethtool support for i40evf */
+#include "i40evf.h"
+
+#include <linux/uaccess.h>
+
+
+struct i40evf_stats {
+       char stat_string[ETH_GSTRING_LEN];
+       int stat_offset;
+};
+
+#define I40EVF_STAT(_name, _stat) { \
+       .stat_string = _name, \
+       .stat_offset = offsetof(struct i40evf_adapter, _stat) \
+}
+
+/* All stats are u64, so we don't need to track the size of the field. */
+static const struct i40evf_stats i40evf_gstrings_stats[] = {
+       I40EVF_STAT("rx_bytes", current_stats.rx_bytes),
+       I40EVF_STAT("rx_unicast", current_stats.rx_unicast),
+       I40EVF_STAT("rx_multicast", current_stats.rx_multicast),
+       I40EVF_STAT("rx_broadcast", current_stats.rx_broadcast),
+       I40EVF_STAT("rx_discards", current_stats.rx_discards),
+       I40EVF_STAT("rx_errors", current_stats.rx_errors),
+       I40EVF_STAT("rx_missed", current_stats.rx_missed),
+       I40EVF_STAT("rx_unknown_protocol", current_stats.rx_unknown_protocol),
+       I40EVF_STAT("tx_bytes", current_stats.tx_bytes),
+       I40EVF_STAT("tx_unicast", current_stats.tx_unicast),
+       I40EVF_STAT("tx_multicast", current_stats.tx_multicast),
+       I40EVF_STAT("tx_broadcast", current_stats.tx_broadcast),
+       I40EVF_STAT("tx_discards", current_stats.tx_discards),
+       I40EVF_STAT("tx_errors", current_stats.tx_errors),
+};
+
+#define I40EVF_GLOBAL_STATS_LEN ARRAY_SIZE(i40evf_gstrings_stats)
+#define I40EVF_QUEUE_STATS_LEN \
+       (((struct i40evf_adapter *) \
+               netdev_priv(netdev))->vsi_res->num_queue_pairs * 4)
+#define I40EVF_STATS_LEN (I40EVF_GLOBAL_STATS_LEN + I40EVF_QUEUE_STATS_LEN)
+
+/**
+ * i40evf_get_settings - Get Link Speed and Duplex settings
+ * @netdev: network interface device structure
+ * @ecmd: ethtool command
+ *
+ * Reports speed/duplex settings. Because this is a VF, we don't know what
+ * kind of link we really have, so we fake it.
+ **/
+static int i40evf_get_settings(struct net_device *netdev,
+                              struct ethtool_cmd *ecmd)
+{
+       /* In the future the VF will be able to query the PF for
+        * some information - for now use a dummy value
+        */
+       ecmd->supported = SUPPORTED_10000baseT_Full;
+       ecmd->autoneg = AUTONEG_DISABLE;
+       ecmd->transceiver = XCVR_DUMMY1;
+       ecmd->port = PORT_NONE;
+
+       return 0;
+}
+
+/**
+ * i40evf_get_sset_count - Get length of string set
+ * @netdev: network interface device structure
+ * @sset: id of string set
+ *
+ * Reports size of string table. This driver only supports
+ * strings for statistics.
+ **/
+static int i40evf_get_sset_count(struct net_device *netdev, int sset)
+{
+       if (sset == ETH_SS_STATS)
+               return I40EVF_STATS_LEN;
+       else
+               return -ENOTSUPP;
+}
+
+/**
+ * i40evf_get_ethtool_stats - report device statistics
+ * @netdev: network interface device structure
+ * @stats: ethtool statistics structure
+ * @data: pointer to data buffer
+ *
+ * All statistics are added to the data buffer as an array of u64.
+ **/
+static void i40evf_get_ethtool_stats(struct net_device *netdev,
+                                    struct ethtool_stats *stats, u64 *data)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       int i, j;
+       char *p;
+
+       for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
+               p = (char *)adapter + i40evf_gstrings_stats[i].stat_offset;
+               data[i] =  *(u64 *)p;
+       }
+       for (j = 0; j < adapter->vsi_res->num_queue_pairs; j++) {
+               data[i++] = adapter->tx_rings[j]->stats.packets;
+               data[i++] = adapter->tx_rings[j]->stats.bytes;
+       }
+       for (j = 0; j < adapter->vsi_res->num_queue_pairs; j++) {
+               data[i++] = adapter->rx_rings[j]->stats.packets;
+               data[i++] = adapter->rx_rings[j]->stats.bytes;
+       }
+}
+
+/**
+ * i40evf_get_strings - Get string set
+ * @netdev: network interface device structure
+ * @sset: id of string set
+ * @data: buffer for string data
+ *
+ * Builds stats string table.
+ **/
+static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       u8 *p = data;
+       int i;
+
+       if (sset == ETH_SS_STATS) {
+               for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
+                       memcpy(p, i40evf_gstrings_stats[i].stat_string,
+                              ETH_GSTRING_LEN);
+                       p += ETH_GSTRING_LEN;
+               }
+               for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) {
+                       snprintf(p, ETH_GSTRING_LEN, "tx-%u.packets", i);
+                       p += ETH_GSTRING_LEN;
+                       snprintf(p, ETH_GSTRING_LEN, "tx-%u.bytes", i);
+                       p += ETH_GSTRING_LEN;
+               }
+               for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) {
+                       snprintf(p, ETH_GSTRING_LEN, "rx-%u.packets", i);
+                       p += ETH_GSTRING_LEN;
+                       snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i);
+                       p += ETH_GSTRING_LEN;
+               }
+       }
+}
+
+/**
+ * i40evf_get_msglevel - Get debug message level
+ * @netdev: network interface device structure
+ *
+ * Returns current debug message level.
+ **/
+static u32 i40evf_get_msglevel(struct net_device *netdev)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       return adapter->msg_enable;
+}
+
+/**
+ * i40evf_get_msglevel - Set debug message level
+ * @netdev: network interface device structure
+ * @data: message level
+ *
+ * Set current debug message level. Higher values cause the driver to
+ * be noisier.
+ **/
+static void i40evf_set_msglevel(struct net_device *netdev, u32 data)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       adapter->msg_enable = data;
+}
+
+/**
+ * i40evf_get_drvinto - Get driver info
+ * @netdev: network interface device structure
+ * @drvinfo: ethool driver info structure
+ *
+ * Returns information about the driver and device for display to the user.
+ **/
+static void i40evf_get_drvinfo(struct net_device *netdev,
+                              struct ethtool_drvinfo *drvinfo)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+       strlcpy(drvinfo->driver, i40evf_driver_name, 32);
+       strlcpy(drvinfo->version, i40evf_driver_version, 32);
+
+       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+}
+
+/**
+ * i40evf_get_ringparam - Get ring parameters
+ * @netdev: network interface device structure
+ * @ring: ethtool ringparam structure
+ *
+ * Returns current ring parameters. TX and RX rings are reported separately,
+ * but the number of rings is not reported.
+ **/
+static void i40evf_get_ringparam(struct net_device *netdev,
+                                 struct ethtool_ringparam *ring)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       struct i40e_ring *tx_ring = adapter->tx_rings[0];
+       struct i40e_ring *rx_ring = adapter->rx_rings[0];
+
+       ring->rx_max_pending = I40EVF_MAX_RXD;
+       ring->tx_max_pending = I40EVF_MAX_TXD;
+       ring->rx_pending = rx_ring->count;
+       ring->tx_pending = tx_ring->count;
+}
+
+/**
+ * i40evf_set_ringparam - Set ring parameters
+ * @netdev: network interface device structure
+ * @ring: ethtool ringparam structure
+ *
+ * Sets ring parameters. TX and RX rings are controlled separately, but the
+ * number of rings is not specified, so all rings get the same settings.
+ **/
+static int i40evf_set_ringparam(struct net_device *netdev,
+                               struct ethtool_ringparam *ring)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       u32 new_rx_count, new_tx_count;
+
+       if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+               return -EINVAL;
+
+       new_tx_count = clamp_t(u32, ring->tx_pending,
+                              I40EVF_MIN_TXD,
+                              I40EVF_MAX_TXD);
+       new_tx_count = ALIGN(new_tx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
+
+       new_rx_count = clamp_t(u32, ring->rx_pending,
+                              I40EVF_MIN_RXD,
+                              I40EVF_MAX_RXD);
+       new_rx_count = ALIGN(new_rx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
+
+       /* if nothing to do return success */
+       if ((new_tx_count == adapter->txd_count) &&
+           (new_rx_count == adapter->rxd_count))
+               return 0;
+
+       adapter->txd_count = new_tx_count;
+       adapter->rxd_count = new_rx_count;
+
+       if (netif_running(netdev))
+               i40evf_reinit_locked(adapter);
+       return 0;
+}
+
+/**
+ * i40evf_get_coalesce - Get interrupt coalescing settings
+ * @netdev: network interface device structure
+ * @ec: ethtool coalesce structure
+ *
+ * Returns current coalescing settings. This is referred to elsewhere in the
+ * driver as Interrupt Throttle Rate, as this is how the hardware describes
+ * this functionality.
+ **/
+static int i40evf_get_coalesce(struct net_device *netdev,
+                            struct ethtool_coalesce *ec)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       struct i40e_vsi *vsi = &adapter->vsi;
+
+       ec->tx_max_coalesced_frames = vsi->work_limit;
+       ec->rx_max_coalesced_frames = vsi->work_limit;
+
+       if (ITR_IS_DYNAMIC(vsi->rx_itr_setting))
+               ec->rx_coalesce_usecs = 1;
+       else
+               ec->rx_coalesce_usecs = vsi->rx_itr_setting;
+
+       if (ITR_IS_DYNAMIC(vsi->tx_itr_setting))
+               ec->tx_coalesce_usecs = 1;
+       else
+               ec->tx_coalesce_usecs = vsi->tx_itr_setting;
+
+       return 0;
+}
+
+/**
+ * i40evf_set_coalesce - Set interrupt coalescing settings
+ * @netdev: network interface device structure
+ * @ec: ethtool coalesce structure
+ *
+ * Change current coalescing settings.
+ **/
+static int i40evf_set_coalesce(struct net_device *netdev,
+                            struct ethtool_coalesce *ec)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       struct i40e_hw *hw = &adapter->hw;
+       struct i40e_vsi *vsi = &adapter->vsi;
+       struct i40e_q_vector *q_vector;
+       int i;
+
+       if (ec->tx_max_coalesced_frames || ec->rx_max_coalesced_frames)
+               vsi->work_limit = ec->tx_max_coalesced_frames;
+
+       switch (ec->rx_coalesce_usecs) {
+       case 0:
+               vsi->rx_itr_setting = 0;
+               break;
+       case 1:
+               vsi->rx_itr_setting = (I40E_ITR_DYNAMIC
+                                      | ITR_REG_TO_USEC(I40E_ITR_RX_DEF));
+               break;
+       default:
+               if ((ec->rx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
+                   (ec->rx_coalesce_usecs > (I40E_MAX_ITR << 1)))
+                       return -EINVAL;
+               vsi->rx_itr_setting = ec->rx_coalesce_usecs;
+               break;
+       }
+
+       switch (ec->tx_coalesce_usecs) {
+       case 0:
+               vsi->tx_itr_setting = 0;
+               break;
+       case 1:
+               vsi->tx_itr_setting = (I40E_ITR_DYNAMIC
+                                      | ITR_REG_TO_USEC(I40E_ITR_TX_DEF));
+               break;
+       default:
+               if ((ec->tx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
+                   (ec->tx_coalesce_usecs > (I40E_MAX_ITR << 1)))
+                       return -EINVAL;
+               vsi->tx_itr_setting = ec->tx_coalesce_usecs;
+               break;
+       }
+
+       for (i = 0; i < adapter->num_msix_vectors - NONQ_VECS; i++) {
+               q_vector = adapter->q_vector[i];
+               q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
+               wr32(hw, I40E_VFINT_ITRN1(0, i), q_vector->rx.itr);
+               q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting);
+               wr32(hw, I40E_VFINT_ITRN1(1, i), q_vector->tx.itr);
+               i40e_flush(hw);
+       }
+
+       return 0;
+}
+
+static struct ethtool_ops i40evf_ethtool_ops = {
+       .get_settings           = i40evf_get_settings,
+       .get_drvinfo            = i40evf_get_drvinfo,
+       .get_link               = ethtool_op_get_link,
+       .get_ringparam          = i40evf_get_ringparam,
+       .set_ringparam          = i40evf_set_ringparam,
+       .get_strings            = i40evf_get_strings,
+       .get_ethtool_stats      = i40evf_get_ethtool_stats,
+       .get_sset_count         = i40evf_get_sset_count,
+       .get_msglevel           = i40evf_get_msglevel,
+       .set_msglevel           = i40evf_set_msglevel,
+       .get_coalesce           = i40evf_get_coalesce,
+       .set_coalesce           = i40evf_set_coalesce,
+};
+
+/**
+ * i40evf_set_ethtool_ops - Initialize ethtool ops struct
+ * @netdev: network interface device structure
+ *
+ * Sets ethtool ops struct in our netdev so that ethtool can call
+ * our functions.
+ **/
+void i40evf_set_ethtool_ops(struct net_device *netdev)
+{
+       SET_ETHTOOL_OPS(netdev, &i40evf_ethtool_ops);
+}
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
new file mode 100644 (file)
index 0000000..06bf825
--- /dev/null
@@ -0,0 +1,2353 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#include "i40evf.h"
+#include "i40e_prototype.h"
+static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter);
+static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter);
+static int i40evf_close(struct net_device *netdev);
+
+char i40evf_driver_name[] = "i40evf";
+static const char i40evf_driver_string[] =
+       "Intel(R) XL710 X710 Virtual Function Network Driver";
+
+#define DRV_VERSION "0.9.11"
+const char i40evf_driver_version[] = DRV_VERSION;
+static const char i40evf_copyright[] =
+       "Copyright (c) 2013 Intel Corporation.";
+
+/* i40evf_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ *   Class, Class Mask, private data (not used) }
+ */
+static DEFINE_PCI_DEVICE_TABLE(i40evf_pci_tbl) = {
+       {PCI_VDEVICE(INTEL, I40E_VF_DEVICE_ID), 0},
+       /* required last entry */
+       {0, }
+};
+
+MODULE_DEVICE_TABLE(pci, i40evf_pci_tbl);
+
+MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
+MODULE_DESCRIPTION("Intel(R) XL710 X710 Virtual Function Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+/**
+ * i40evf_allocate_dma_mem_d - OS specific memory alloc for shared code
+ * @hw:   pointer to the HW structure
+ * @mem:  ptr to mem struct to fill out
+ * @size: size of memory requested
+ * @alignment: what to align the allocation to
+ **/
+i40e_status i40evf_allocate_dma_mem_d(struct i40e_hw *hw,
+                                     struct i40e_dma_mem *mem,
+                                     u64 size, u32 alignment)
+{
+       struct i40evf_adapter *adapter = (struct i40evf_adapter *)hw->back;
+
+       if (!mem)
+               return I40E_ERR_PARAM;
+
+       mem->size = ALIGN(size, alignment);
+       mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size,
+                                    (dma_addr_t *)&mem->pa, GFP_KERNEL);
+       if (mem->va)
+               return 0;
+       else
+               return I40E_ERR_NO_MEMORY;
+}
+
+/**
+ * i40evf_free_dma_mem_d - OS specific memory free for shared code
+ * @hw:   pointer to the HW structure
+ * @mem:  ptr to mem struct to free
+ **/
+i40e_status i40evf_free_dma_mem_d(struct i40e_hw *hw, struct i40e_dma_mem *mem)
+{
+       struct i40evf_adapter *adapter = (struct i40evf_adapter *)hw->back;
+
+       if (!mem || !mem->va)
+               return I40E_ERR_PARAM;
+       dma_free_coherent(&adapter->pdev->dev, mem->size,
+                         mem->va, (dma_addr_t)mem->pa);
+       return 0;
+}
+
+/**
+ * i40evf_allocate_virt_mem_d - OS specific memory alloc for shared code
+ * @hw:   pointer to the HW structure
+ * @mem:  ptr to mem struct to fill out
+ * @size: size of memory requested
+ **/
+i40e_status i40evf_allocate_virt_mem_d(struct i40e_hw *hw,
+                                      struct i40e_virt_mem *mem, u32 size)
+{
+       if (!mem)
+               return I40E_ERR_PARAM;
+
+       mem->size = size;
+       mem->va = kzalloc(size, GFP_KERNEL);
+
+       if (mem->va)
+               return 0;
+       else
+               return I40E_ERR_NO_MEMORY;
+}
+
+/**
+ * i40evf_free_virt_mem_d - OS specific memory free for shared code
+ * @hw:   pointer to the HW structure
+ * @mem:  ptr to mem struct to free
+ **/
+i40e_status i40evf_free_virt_mem_d(struct i40e_hw *hw,
+                                  struct i40e_virt_mem *mem)
+{
+       if (!mem)
+               return I40E_ERR_PARAM;
+
+       /* it's ok to kfree a NULL pointer */
+       kfree(mem->va);
+
+       return 0;
+}
+
+/**
+ * i40evf_debug_d - OS dependent version of debug printing
+ * @hw:  pointer to the HW structure
+ * @mask: debug level mask
+ * @fmt_str: printf-type format description
+ **/
+void i40evf_debug_d(void *hw, u32 mask, char *fmt_str, ...)
+{
+       char buf[512];
+       va_list argptr;
+
+       if (!(mask & ((struct i40e_hw *)hw)->debug_mask))
+               return;
+
+       va_start(argptr, fmt_str);
+       vsnprintf(buf, sizeof(buf), fmt_str, argptr);
+       va_end(argptr);
+
+       /* the debug string is already formatted with a newline */
+       pr_info("%s", buf);
+}
+
+/**
+ * i40evf_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ **/
+static void i40evf_tx_timeout(struct net_device *netdev)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+       adapter->tx_timeout_count++;
+
+       /* Do the reset outside of interrupt context */
+       schedule_work(&adapter->reset_task);
+}
+
+/**
+ * i40evf_misc_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+static void i40evf_misc_irq_disable(struct i40evf_adapter *adapter)
+{
+       struct i40e_hw *hw = &adapter->hw;
+       wr32(hw, I40E_VFINT_DYN_CTL01, 0);
+
+       /* read flush */
+       rd32(hw, I40E_VFGEN_RSTAT);
+
+       synchronize_irq(adapter->msix_entries[0].vector);
+}
+
+/**
+ * i40evf_misc_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+static void i40evf_misc_irq_enable(struct i40evf_adapter *adapter)
+{
+       struct i40e_hw *hw = &adapter->hw;
+       wr32(hw, I40E_VFINT_DYN_CTL01, I40E_VFINT_DYN_CTL01_INTENA_MASK |
+                                      I40E_VFINT_DYN_CTL01_ITR_INDX_MASK);
+       wr32(hw, I40E_VFINT_ICR0_ENA1, I40E_VFINT_ICR0_ENA_ADMINQ_MASK);
+
+       /* read flush */
+       rd32(hw, I40E_VFGEN_RSTAT);
+}
+
+/**
+ * i40evf_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+static void i40evf_irq_disable(struct i40evf_adapter *adapter)
+{
+       int i;
+       struct i40e_hw *hw = &adapter->hw;
+
+       for (i = 1; i < adapter->num_msix_vectors; i++) {
+               wr32(hw, I40E_VFINT_DYN_CTLN1(i - 1), 0);
+               synchronize_irq(adapter->msix_entries[i].vector);
+       }
+       /* read flush */
+       rd32(hw, I40E_VFGEN_RSTAT);
+
+}
+
+/**
+ * i40evf_irq_enable_queues - Enable interrupt for specified queues
+ * @adapter: board private structure
+ * @mask: bitmap of queues to enable
+ **/
+void i40evf_irq_enable_queues(struct i40evf_adapter *adapter, u32 mask)
+{
+       struct i40e_hw *hw = &adapter->hw;
+       int i;
+
+       for (i = 1; i < adapter->num_msix_vectors; i++) {
+               if (mask & (1 << (i - 1))) {
+                       wr32(hw, I40E_VFINT_DYN_CTLN1(i - 1),
+                            I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+                            I40E_VFINT_DYN_CTLN_CLEARPBA_MASK);
+               }
+       }
+}
+
+/**
+ * i40evf_fire_sw_int - Generate SW interrupt for specified vectors
+ * @adapter: board private structure
+ * @mask: bitmap of vectors to trigger
+ **/
+static void i40evf_fire_sw_int(struct i40evf_adapter *adapter,
+                                           u32 mask)
+{
+       struct i40e_hw *hw = &adapter->hw;
+       int i;
+       uint32_t dyn_ctl;
+
+       for (i = 1; i < adapter->num_msix_vectors; i++) {
+               if (mask & (1 << i)) {
+                       dyn_ctl = rd32(hw, I40E_VFINT_DYN_CTLN1(i - 1));
+                       dyn_ctl |= I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK |
+                                  I40E_VFINT_DYN_CTLN_CLEARPBA_MASK;
+                       wr32(hw, I40E_VFINT_DYN_CTLN1(i - 1), dyn_ctl);
+               }
+       }
+}
+
+/**
+ * i40evf_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush)
+{
+       struct i40e_hw *hw = &adapter->hw;
+
+       i40evf_irq_enable_queues(adapter, ~0);
+
+       if (flush)
+               rd32(hw, I40E_VFGEN_RSTAT);
+}
+
+/**
+ * i40evf_msix_aq - Interrupt handler for vector 0
+ * @irq: interrupt number
+ * @data: pointer to netdev
+ **/
+static irqreturn_t i40evf_msix_aq(int irq, void *data)
+{
+       struct net_device *netdev = data;
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       struct i40e_hw *hw = &adapter->hw;
+       u32 val;
+       u32 ena_mask;
+
+       /* handle non-queue interrupts */
+       val = rd32(hw, I40E_VFINT_ICR01);
+       ena_mask = rd32(hw, I40E_VFINT_ICR0_ENA1);
+
+
+       val = rd32(hw, I40E_VFINT_DYN_CTL01);
+       val = val | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK;
+       wr32(hw, I40E_VFINT_DYN_CTL01, val);
+
+       /* re-enable interrupt causes */
+       wr32(hw, I40E_VFINT_ICR0_ENA1, ena_mask);
+       wr32(hw, I40E_VFINT_DYN_CTL01, I40E_VFINT_DYN_CTL01_INTENA_MASK);
+
+       /* schedule work on the private workqueue */
+       schedule_work(&adapter->adminq_task);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * i40evf_msix_clean_rings - MSIX mode Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a q_vector
+ **/
+static irqreturn_t i40evf_msix_clean_rings(int irq, void *data)
+{
+       struct i40e_q_vector *q_vector = data;
+
+       if (!q_vector->tx.ring && !q_vector->rx.ring)
+               return IRQ_HANDLED;
+
+       napi_schedule(&q_vector->napi);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * i40evf_map_vector_to_rxq - associate irqs with rx queues
+ * @adapter: board private structure
+ * @v_idx: interrupt number
+ * @r_idx: queue number
+ **/
+static void
+i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx)
+{
+       struct i40e_q_vector *q_vector = adapter->q_vector[v_idx];
+       struct i40e_ring *rx_ring = adapter->rx_rings[r_idx];
+
+       rx_ring->q_vector = q_vector;
+       rx_ring->next = q_vector->rx.ring;
+       rx_ring->vsi = &adapter->vsi;
+       q_vector->rx.ring = rx_ring;
+       q_vector->rx.count++;
+       q_vector->rx.latency_range = I40E_LOW_LATENCY;
+}
+
+/**
+ * i40evf_map_vector_to_txq - associate irqs with tx queues
+ * @adapter: board private structure
+ * @v_idx: interrupt number
+ * @t_idx: queue number
+ **/
+static void
+i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)
+{
+       struct i40e_q_vector *q_vector = adapter->q_vector[v_idx];
+       struct i40e_ring *tx_ring = adapter->tx_rings[t_idx];
+
+       tx_ring->q_vector = q_vector;
+       tx_ring->next = q_vector->tx.ring;
+       tx_ring->vsi = &adapter->vsi;
+       q_vector->tx.ring = tx_ring;
+       q_vector->tx.count++;
+       q_vector->tx.latency_range = I40E_LOW_LATENCY;
+       q_vector->num_ringpairs++;
+       q_vector->ring_mask |= (1 << t_idx);
+}
+
+/**
+ * i40evf_map_rings_to_vectors - Maps descriptor rings to vectors
+ * @adapter: board private structure to initialize
+ *
+ * This function maps descriptor rings to the queue-specific vectors
+ * we were allotted through the MSI-X enabling code.  Ideally, we'd have
+ * one vector per ring/queue, but on a constrained vector budget, we
+ * group the rings as "efficiently" as possible.  You would add new
+ * mapping configurations in here.
+ **/
+static int i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
+{
+       int q_vectors;
+       int v_start = 0;
+       int rxr_idx = 0, txr_idx = 0;
+       int rxr_remaining = adapter->vsi_res->num_queue_pairs;
+       int txr_remaining = adapter->vsi_res->num_queue_pairs;
+       int i, j;
+       int rqpv, tqpv;
+       int err = 0;
+
+       q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+       /* The ideal configuration...
+        * We have enough vectors to map one per queue.
+        */
+       if (q_vectors == (rxr_remaining * 2)) {
+               for (; rxr_idx < rxr_remaining; v_start++, rxr_idx++)
+                       i40evf_map_vector_to_rxq(adapter, v_start, rxr_idx);
+
+               for (; txr_idx < txr_remaining; v_start++, txr_idx++)
+                       i40evf_map_vector_to_txq(adapter, v_start, txr_idx);
+               goto out;
+       }
+
+       /* If we don't have enough vectors for a 1-to-1
+        * mapping, we'll have to group them so there are
+        * multiple queues per vector.
+        * Re-adjusting *qpv takes care of the remainder.
+        */
+       for (i = v_start; i < q_vectors; i++) {
+               rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - i);
+               for (j = 0; j < rqpv; j++) {
+                       i40evf_map_vector_to_rxq(adapter, i, rxr_idx);
+                       rxr_idx++;
+                       rxr_remaining--;
+               }
+       }
+       for (i = v_start; i < q_vectors; i++) {
+               tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - i);
+               for (j = 0; j < tqpv; j++) {
+                       i40evf_map_vector_to_txq(adapter, i, txr_idx);
+                       txr_idx++;
+                       txr_remaining--;
+               }
+       }
+
+out:
+       adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
+
+       return err;
+}
+
+/**
+ * i40evf_request_traffic_irqs - Initialize MSI-X interrupts
+ * @adapter: board private structure
+ *
+ * Allocates MSI-X vectors for tx and rx handling, and requests
+ * interrupts from the kernel.
+ **/
+static int
+i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
+{
+       int vector, err, q_vectors;
+       int rx_int_idx = 0, tx_int_idx = 0;
+
+       i40evf_irq_disable(adapter);
+       /* Decrement for Other and TCP Timer vectors */
+       q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+       for (vector = 0; vector < q_vectors; vector++) {
+               struct i40e_q_vector *q_vector = adapter->q_vector[vector];
+
+               if (q_vector->tx.ring && q_vector->rx.ring) {
+                       snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+                                "i40evf-%s-%s-%d", basename,
+                                "TxRx", rx_int_idx++);
+                       tx_int_idx++;
+               } else if (q_vector->rx.ring) {
+                       snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+                                "i40evf-%s-%s-%d", basename,
+                                "rx", rx_int_idx++);
+               } else if (q_vector->tx.ring) {
+                       snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+                                "i40evf-%s-%s-%d", basename,
+                                "tx", tx_int_idx++);
+               } else {
+                       /* 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);
+               if (err) {
+                       dev_info(&adapter->pdev->dev,
+                                "%s: request_irq failed, error: %d\n",
+                               __func__, err);
+                       goto free_queue_irqs;
+               }
+               /* assign the mask for this irq */
+               irq_set_affinity_hint(
+                       adapter->msix_entries[vector + NONQ_VECS].vector,
+                       q_vector->affinity_mask);
+       }
+
+       return 0;
+
+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_vector[vector]);
+       }
+       return err;
+}
+
+/**
+ * i40evf_request_misc_irq - Initialize MSI-X interrupts
+ * @adapter: board private structure
+ *
+ * Allocates MSI-X vector 0 and requests interrupts from the kernel. This
+ * vector is only for the admin queue, and stays active even when the netdev
+ * is closed.
+ **/
+static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       int err;
+
+       sprintf(adapter->name[0], "i40evf:mbx");
+       err = request_irq(adapter->msix_entries[0].vector,
+                         &i40evf_msix_aq, 0, adapter->name[0], netdev);
+       if (err) {
+               dev_err(&adapter->pdev->dev,
+                       "request_irq for msix_aq failed: %d\n", err);
+               free_irq(adapter->msix_entries[0].vector, netdev);
+       }
+       return err;
+}
+
+/**
+ * i40evf_free_traffic_irqs - Free MSI-X interrupts
+ * @adapter: board private structure
+ *
+ * Frees all MSI-X vectors other than 0.
+ **/
+static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter)
+{
+       int i;
+       int 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_vector[i]);
+       }
+}
+
+/**
+ * i40evf_free_misc_irq - Free MSI-X miscellaneous vector
+ * @adapter: board private structure
+ *
+ * Frees MSI-X vector 0.
+ **/
+static void i40evf_free_misc_irq(struct i40evf_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+
+       free_irq(adapter->msix_entries[0].vector, netdev);
+}
+
+/**
+ * i40evf_configure_tx - Configure Transmit Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+static void i40evf_configure_tx(struct i40evf_adapter *adapter)
+{
+       struct i40e_hw *hw = &adapter->hw;
+       int i;
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++)
+               adapter->tx_rings[i]->tail = hw->hw_addr + I40E_QTX_TAIL1(i);
+}
+
+/**
+ * i40evf_configure_rx - Configure Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+static void i40evf_configure_rx(struct i40evf_adapter *adapter)
+{
+       struct i40e_hw *hw = &adapter->hw;
+       struct net_device *netdev = adapter->netdev;
+       int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+       int i;
+       int rx_buf_len;
+
+
+       adapter->flags &= ~I40EVF_FLAG_RX_PS_CAPABLE;
+       adapter->flags |= I40EVF_FLAG_RX_1BUF_CAPABLE;
+
+       /* Decide whether to use packet split mode or not */
+       if (netdev->mtu > ETH_DATA_LEN) {
+               if (adapter->flags & I40EVF_FLAG_RX_PS_CAPABLE)
+                       adapter->flags |= I40EVF_FLAG_RX_PS_ENABLED;
+               else
+                       adapter->flags &= ~I40EVF_FLAG_RX_PS_ENABLED;
+       } else {
+               if (adapter->flags & I40EVF_FLAG_RX_1BUF_CAPABLE)
+                       adapter->flags &= ~I40EVF_FLAG_RX_PS_ENABLED;
+               else
+                       adapter->flags |= I40EVF_FLAG_RX_PS_ENABLED;
+       }
+
+       /* Set the RX buffer length according to the mode */
+       if (adapter->flags & I40EVF_FLAG_RX_PS_ENABLED) {
+               rx_buf_len = I40E_RX_HDR_SIZE;
+       } else {
+               if (netdev->mtu <= ETH_DATA_LEN)
+                       rx_buf_len = I40EVF_RXBUFFER_2048;
+               else
+                       rx_buf_len = ALIGN(max_frame, 1024);
+       }
+
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) {
+               adapter->rx_rings[i]->tail = hw->hw_addr + I40E_QRX_TAIL1(i);
+               adapter->rx_rings[i]->rx_buf_len = rx_buf_len;
+       }
+}
+
+/**
+ * i40evf_find_vlan - Search filter list for specific vlan filter
+ * @adapter: board private structure
+ * @vlan: vlan tag
+ *
+ * Returns ptr to the filter object or NULL
+ **/
+static struct
+i40evf_vlan_filter *i40evf_find_vlan(struct i40evf_adapter *adapter, u16 vlan)
+{
+       struct i40evf_vlan_filter *f;
+
+       list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+               if (vlan == f->vlan)
+                       return f;
+       }
+       return NULL;
+}
+
+/**
+ * i40evf_add_vlan - Add a vlan filter to the list
+ * @adapter: board private structure
+ * @vlan: VLAN tag
+ *
+ * Returns ptr to the filter object or NULL when no memory available.
+ **/
+static struct
+i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan)
+{
+       struct i40evf_vlan_filter *f;
+
+       f = i40evf_find_vlan(adapter, vlan);
+       if (NULL == f) {
+               f = kzalloc(sizeof(*f), GFP_ATOMIC);
+               if (NULL == f) {
+                       dev_info(&adapter->pdev->dev,
+                                "%s: no memory for new VLAN filter\n",
+                                __func__);
+                       return NULL;
+               }
+               f->vlan = vlan;
+
+               INIT_LIST_HEAD(&f->list);
+               list_add(&f->list, &adapter->vlan_filter_list);
+               f->add = true;
+               adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+       }
+
+       return f;
+}
+
+/**
+ * i40evf_del_vlan - Remove a vlan filter from the list
+ * @adapter: board private structure
+ * @vlan: VLAN tag
+ **/
+static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan)
+{
+       struct i40evf_vlan_filter *f;
+
+       f = i40evf_find_vlan(adapter, vlan);
+       if (f) {
+               f->remove = true;
+               adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+       }
+       return;
+}
+
+/**
+ * i40evf_vlan_rx_add_vid - Add a VLAN filter to a device
+ * @netdev: network device struct
+ * @vid: VLAN tag
+ **/
+static int i40evf_vlan_rx_add_vid(struct net_device *netdev,
+                        __always_unused __be16 proto, u16 vid)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+       if (i40evf_add_vlan(adapter, vid) == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+/**
+ * i40evf_vlan_rx_kill_vid - Remove a VLAN filter from a device
+ * @netdev: network device struct
+ * @vid: VLAN tag
+ **/
+static int i40evf_vlan_rx_kill_vid(struct net_device *netdev,
+                         __always_unused __be16 proto, u16 vid)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+       i40evf_del_vlan(adapter, vid);
+       return 0;
+}
+
+/**
+ * i40evf_find_filter - Search filter list for specific mac filter
+ * @adapter: board private structure
+ * @macaddr: the MAC address
+ *
+ * Returns ptr to the filter object or NULL
+ **/
+static struct
+i40evf_mac_filter *i40evf_find_filter(struct i40evf_adapter *adapter,
+                                     u8 *macaddr)
+{
+       struct i40evf_mac_filter *f;
+
+       if (!macaddr)
+               return NULL;
+
+       list_for_each_entry(f, &adapter->mac_filter_list, list) {
+               if (ether_addr_equal(macaddr, f->macaddr))
+                       return f;
+       }
+       return NULL;
+}
+
+/**
+ * i40e_add_filter - Add a mac filter to the filter list
+ * @adapter: board private structure
+ * @macaddr: the MAC address
+ *
+ * Returns ptr to the filter object or NULL when no memory available.
+ **/
+static struct
+i40evf_mac_filter *i40evf_add_filter(struct i40evf_adapter *adapter,
+                                    u8 *macaddr)
+{
+       struct i40evf_mac_filter *f;
+
+       if (!macaddr)
+               return NULL;
+
+       while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
+                               &adapter->crit_section))
+               mdelay(1);
+
+       f = i40evf_find_filter(adapter, macaddr);
+       if (NULL == f) {
+               f = kzalloc(sizeof(*f), GFP_ATOMIC);
+               if (NULL == f) {
+                       dev_info(&adapter->pdev->dev,
+                                "%s: no memory for new filter\n", __func__);
+                       clear_bit(__I40EVF_IN_CRITICAL_TASK,
+                                 &adapter->crit_section);
+                       return NULL;
+               }
+
+               memcpy(f->macaddr, macaddr, ETH_ALEN);
+
+               list_add(&f->list, &adapter->mac_filter_list);
+               f->add = true;
+               adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+       }
+
+       clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       return f;
+}
+
+/**
+ * i40evf_set_mac - NDO callback to set port mac address
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int i40evf_set_mac(struct net_device *netdev, void *p)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       struct i40e_hw *hw = &adapter->hw;
+       struct i40evf_mac_filter *f;
+       struct sockaddr *addr = p;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
+               return 0;
+
+       f = i40evf_add_filter(adapter, addr->sa_data);
+       if (f) {
+               memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
+               memcpy(netdev->dev_addr, adapter->hw.mac.addr,
+                      netdev->addr_len);
+       }
+
+       return (f == NULL) ? -ENOMEM : 0;
+}
+
+/**
+ * i40evf_set_rx_mode - NDO callback to set the netdev filters
+ * @netdev: network interface device structure
+ **/
+static void i40evf_set_rx_mode(struct net_device *netdev)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       struct i40evf_mac_filter *f, *ftmp;
+       struct netdev_hw_addr *uca;
+       struct netdev_hw_addr *mca;
+
+       /* add addr if not already in the filter list */
+       netdev_for_each_uc_addr(uca, netdev) {
+               i40evf_add_filter(adapter, uca->addr);
+       }
+       netdev_for_each_mc_addr(mca, netdev) {
+               i40evf_add_filter(adapter, mca->addr);
+       }
+
+       while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
+                               &adapter->crit_section))
+               mdelay(1);
+       /* remove filter if not in netdev list */
+       list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+               bool found = false;
+
+               if (f->macaddr[0] & 0x01) {
+                       netdev_for_each_mc_addr(mca, netdev) {
+                               if (ether_addr_equal(mca->addr, f->macaddr)) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+               } else {
+                       netdev_for_each_uc_addr(uca, netdev) {
+                               if (ether_addr_equal(uca->addr, f->macaddr)) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+               }
+               if (found) {
+                       f->remove = true;
+                       adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+               }
+       }
+       clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+}
+
+/**
+ * i40evf_napi_enable_all - enable NAPI on all queue vectors
+ * @adapter: board private structure
+ **/
+static void i40evf_napi_enable_all(struct i40evf_adapter *adapter)
+{
+       int q_idx;
+       struct i40e_q_vector *q_vector;
+       int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+       for (q_idx = 0; q_idx < q_vectors; q_idx++) {
+               struct napi_struct *napi;
+               q_vector = adapter->q_vector[q_idx];
+               napi = &q_vector->napi;
+               napi_enable(napi);
+       }
+}
+
+/**
+ * i40evf_napi_disable_all - disable NAPI on all queue vectors
+ * @adapter: board private structure
+ **/
+static void i40evf_napi_disable_all(struct i40evf_adapter *adapter)
+{
+       int q_idx;
+       struct i40e_q_vector *q_vector;
+       int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+       for (q_idx = 0; q_idx < q_vectors; q_idx++) {
+               q_vector = adapter->q_vector[q_idx];
+               napi_disable(&q_vector->napi);
+       }
+}
+
+/**
+ * i40evf_configure - set up transmit and receive data structures
+ * @adapter: board private structure
+ **/
+static void i40evf_configure(struct i40evf_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       int i;
+
+       i40evf_set_rx_mode(netdev);
+
+       i40evf_configure_tx(adapter);
+       i40evf_configure_rx(adapter);
+       adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
+
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) {
+               struct i40e_ring *ring = adapter->rx_rings[i];
+               i40evf_alloc_rx_buffers(ring, ring->count);
+               ring->next_to_use = ring->count - 1;
+               writel(ring->next_to_use, ring->tail);
+       }
+}
+
+/**
+ * i40evf_up_complete - Finish the last steps of bringing up a connection
+ * @adapter: board private structure
+ **/
+static int i40evf_up_complete(struct i40evf_adapter *adapter)
+{
+       adapter->state = __I40EVF_RUNNING;
+       clear_bit(__I40E_DOWN, &adapter->vsi.state);
+
+       i40evf_napi_enable_all(adapter);
+
+       adapter->aq_required |= I40EVF_FLAG_AQ_ENABLE_QUEUES;
+       mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
+       return 0;
+}
+
+/**
+ * i40evf_clean_all_rx_rings - Free Rx Buffers for all queues
+ * @adapter: board private structure
+ **/
+static void i40evf_clean_all_rx_rings(struct i40evf_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++)
+               i40evf_clean_rx_ring(adapter->rx_rings[i]);
+}
+
+/**
+ * i40evf_clean_all_tx_rings - Free Tx Buffers for all queues
+ * @adapter: board private structure
+ **/
+static void i40evf_clean_all_tx_rings(struct i40evf_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++)
+               i40evf_clean_tx_ring(adapter->tx_rings[i]);
+}
+
+/**
+ * i40e_down - Shutdown the connection processing
+ * @adapter: board private structure
+ **/
+void i40evf_down(struct i40evf_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       struct i40evf_mac_filter *f;
+
+       /* remove all MAC filters from the VSI */
+       list_for_each_entry(f, &adapter->mac_filter_list, list) {
+               f->remove = true;
+       }
+       adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+       /* disable receives */
+       adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
+       mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
+       msleep(20);
+
+       netif_tx_disable(netdev);
+
+       netif_tx_stop_all_queues(netdev);
+
+       i40evf_irq_disable(adapter);
+
+       i40evf_napi_disable_all(adapter);
+
+       netif_carrier_off(netdev);
+
+       i40evf_clean_all_tx_rings(adapter);
+       i40evf_clean_all_rx_rings(adapter);
+}
+
+/**
+ * i40evf_acquire_msix_vectors - Setup the MSIX capability
+ * @adapter: board private structure
+ * @vectors: number of vectors to request
+ *
+ * Work with the OS to set up the MSIX vectors needed.
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int
+i40evf_acquire_msix_vectors(struct i40evf_adapter *adapter, int vectors)
+{
+       int err, vector_threshold;
+
+       /* We'll want at least 3 (vector_threshold):
+        * 0) Other (Admin Queue and link, mostly)
+        * 1) TxQ[0] Cleanup
+        * 2) RxQ[0] Cleanup
+        */
+       vector_threshold = MIN_MSIX_COUNT;
+
+       /* The more we get, the more we will assign to Tx/Rx Cleanup
+        * for the separate queues...where Rx Cleanup >= Tx Cleanup.
+        * Right now, we simply care about how many we'll get; we'll
+        * set them up later while requesting irq's.
+        */
+       while (vectors >= vector_threshold) {
+               err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
+                                     vectors);
+               if (!err) /* Success in acquiring all requested vectors. */
+                       break;
+               else if (err < 0)
+                       vectors = 0; /* Nasty failure, quit now */
+               else /* err == number of vectors we should try again with */
+                       vectors = err;
+       }
+
+       if (vectors < vector_threshold) {
+               dev_err(&adapter->pdev->dev, "Unable to allocate MSI-X interrupts.\n");
+               kfree(adapter->msix_entries);
+               adapter->msix_entries = NULL;
+               err = -EIO;
+       } else {
+               /* Adjust for only the vectors we'll use, which is minimum
+                * of max_msix_q_vectors + NONQ_VECS, or the number of
+                * vectors we were allocated.
+                */
+               adapter->num_msix_vectors = vectors;
+       }
+       return err;
+}
+
+/**
+ * i40evf_free_queues - Free memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ * Free all of the memory associated with queue pairs.
+ **/
+static void i40evf_free_queues(struct i40evf_adapter *adapter)
+{
+       int i;
+
+       if (!adapter->vsi_res)
+               return;
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) {
+               if (adapter->tx_rings[i])
+                       kfree_rcu(adapter->tx_rings[i], rcu);
+               adapter->tx_rings[i] = NULL;
+               adapter->rx_rings[i] = NULL;
+       }
+}
+
+/**
+ * i40evf_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one ring per queue at run-time since we don't know the
+ * number of queues at compile-time.  The polling_netdev array is
+ * intended for Multiqueue, but should work fine with a single queue.
+ **/
+static int i40evf_alloc_queues(struct i40evf_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) {
+               struct i40e_ring *tx_ring;
+               struct i40e_ring *rx_ring;
+
+               tx_ring = kzalloc(sizeof(struct i40e_ring) * 2, GFP_KERNEL);
+               if (!tx_ring)
+                       goto err_out;
+
+               tx_ring->queue_index = i;
+               tx_ring->netdev = adapter->netdev;
+               tx_ring->dev = &adapter->pdev->dev;
+               tx_ring->count = I40EVF_DEFAULT_TXD;
+               adapter->tx_rings[i] = tx_ring;
+
+               rx_ring = &tx_ring[1];
+               rx_ring->queue_index = i;
+               rx_ring->netdev = adapter->netdev;
+               rx_ring->dev = &adapter->pdev->dev;
+               rx_ring->count = I40EVF_DEFAULT_RXD;
+               adapter->rx_rings[i] = rx_ring;
+       }
+
+       return 0;
+
+err_out:
+       i40evf_free_queues(adapter);
+       return -ENOMEM;
+}
+
+/**
+ * i40evf_set_interrupt_capability - set MSI-X or FAIL if not supported
+ * @adapter: board private structure to initialize
+ *
+ * Attempt to configure the interrupts using the best available
+ * capabilities of the hardware and the kernel.
+ **/
+static int i40evf_set_interrupt_capability(struct i40evf_adapter *adapter)
+{
+       int vector, v_budget;
+       int pairs = 0;
+       int err = 0;
+
+       if (!adapter->vsi_res) {
+               err = -EIO;
+               goto out;
+       }
+       pairs = adapter->vsi_res->num_queue_pairs;
+
+       /* It's easy to be greedy for MSI-X vectors, but it really
+        * doesn't do us much good if we have a lot more vectors
+        * than CPU's.  So let's be conservative and only ask for
+        * (roughly) twice the number of vectors as there are CPU's.
+        */
+       v_budget = min(pairs, (int)(num_online_cpus() * 2)) + NONQ_VECS;
+       v_budget = min(v_budget, (int)adapter->vf_res->max_vectors + 1);
+
+       /* A failure in MSI-X entry allocation isn't fatal, but it does
+        * mean we disable MSI-X capabilities of the adapter.
+        */
+       adapter->msix_entries = kcalloc(v_budget,
+                                       sizeof(struct msix_entry), GFP_KERNEL);
+       if (!adapter->msix_entries) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       for (vector = 0; vector < v_budget; vector++)
+               adapter->msix_entries[vector].entry = vector;
+
+       i40evf_acquire_msix_vectors(adapter, v_budget);
+
+out:
+       adapter->netdev->real_num_tx_queues = pairs;
+       return err;
+}
+
+/**
+ * i40evf_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one q_vector per queue interrupt.  If allocation fails we
+ * return -ENOMEM.
+ **/
+static int i40evf_alloc_q_vectors(struct i40evf_adapter *adapter)
+{
+       int q_idx, num_q_vectors;
+       struct i40e_q_vector *q_vector;
+
+       num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+       for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
+               q_vector = kzalloc(sizeof(struct i40e_q_vector), GFP_KERNEL);
+               if (!q_vector)
+                       goto err_out;
+               q_vector->adapter = adapter;
+               q_vector->vsi = &adapter->vsi;
+               q_vector->v_idx = q_idx;
+               netif_napi_add(adapter->netdev, &q_vector->napi,
+                                      i40evf_napi_poll, 64);
+               adapter->q_vector[q_idx] = q_vector;
+       }
+
+       return 0;
+
+err_out:
+       while (q_idx) {
+               q_idx--;
+               q_vector = adapter->q_vector[q_idx];
+               netif_napi_del(&q_vector->napi);
+               kfree(q_vector);
+               adapter->q_vector[q_idx] = NULL;
+       }
+       return -ENOMEM;
+}
+
+/**
+ * i40evf_free_q_vectors - Free memory allocated for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * This function frees the memory allocated to the q_vectors.  In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)
+{
+       int q_idx, num_q_vectors;
+       int napi_vectors;
+
+       num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+       napi_vectors = adapter->vsi_res->num_queue_pairs;
+
+       for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
+               struct i40e_q_vector *q_vector = adapter->q_vector[q_idx];
+
+               adapter->q_vector[q_idx] = NULL;
+               if (q_idx < napi_vectors)
+                       netif_napi_del(&q_vector->napi);
+               kfree(q_vector);
+       }
+}
+
+/**
+ * i40evf_reset_interrupt_capability - Reset MSIX setup
+ * @adapter: board private structure
+ *
+ **/
+void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter)
+{
+       pci_disable_msix(adapter->pdev);
+       kfree(adapter->msix_entries);
+       adapter->msix_entries = NULL;
+
+       return;
+}
+
+/**
+ * i40evf_init_interrupt_scheme - Determine if MSIX is supported and init
+ * @adapter: board private structure to initialize
+ *
+ **/
+int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter)
+{
+       int err;
+
+       err = i40evf_set_interrupt_capability(adapter);
+       if (err) {
+               dev_err(&adapter->pdev->dev,
+                       "Unable to setup interrupt capabilities\n");
+               goto err_set_interrupt;
+       }
+
+       err = i40evf_alloc_q_vectors(adapter);
+       if (err) {
+               dev_err(&adapter->pdev->dev,
+                       "Unable to allocate memory for queue vectors\n");
+               goto err_alloc_q_vectors;
+       }
+
+       err = i40evf_alloc_queues(adapter);
+       if (err) {
+               dev_err(&adapter->pdev->dev,
+                       "Unable to allocate memory for queues\n");
+               goto err_alloc_queues;
+       }
+
+       dev_info(&adapter->pdev->dev, "Multiqueue %s: Queue pair count = %u",
+               (adapter->vsi_res->num_queue_pairs > 1) ? "Enabled" :
+               "Disabled", adapter->vsi_res->num_queue_pairs);
+
+       return 0;
+err_alloc_queues:
+       i40evf_free_q_vectors(adapter);
+err_alloc_q_vectors:
+       i40evf_reset_interrupt_capability(adapter);
+err_set_interrupt:
+       return err;
+}
+
+/**
+ * i40evf_watchdog_timer - Periodic call-back timer
+ * @data: pointer to adapter disguised as unsigned long
+ **/
+static void i40evf_watchdog_timer(unsigned long data)
+{
+       struct i40evf_adapter *adapter = (struct i40evf_adapter *)data;
+       schedule_work(&adapter->watchdog_task);
+       /* timer will be rescheduled in watchdog task */
+}
+
+/**
+ * i40evf_watchdog_task - Periodic call-back task
+ * @work: pointer to work_struct
+ **/
+static void i40evf_watchdog_task(struct work_struct *work)
+{
+       struct i40evf_adapter *adapter = container_of(work,
+                                         struct i40evf_adapter,
+                                         watchdog_task);
+       struct i40e_hw *hw = &adapter->hw;
+
+       if (adapter->state < __I40EVF_DOWN)
+               goto watchdog_done;
+
+       if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
+               goto watchdog_done;
+
+       /* check for unannounced reset */
+       if ((adapter->state != __I40EVF_RESETTING) &&
+           (rd32(hw, I40E_VFGEN_RSTAT) & 0x3) != I40E_VFR_VFACTIVE) {
+               adapter->state = __I40EVF_RESETTING;
+               schedule_work(&adapter->reset_task);
+               dev_info(&adapter->pdev->dev, "%s: hardware reset detected\n",
+                        __func__);
+               goto watchdog_done;
+       }
+
+       /* Process admin queue tasks. After init, everything gets done
+        * here so we don't race on the admin queue.
+        */
+       if (adapter->aq_pending)
+               goto watchdog_done;
+
+       if (adapter->aq_required & I40EVF_FLAG_AQ_MAP_VECTORS) {
+               i40evf_map_queues(adapter);
+               goto watchdog_done;
+       }
+
+       if (adapter->aq_required & I40EVF_FLAG_AQ_ADD_MAC_FILTER) {
+               i40evf_add_ether_addrs(adapter);
+               goto watchdog_done;
+       }
+
+       if (adapter->aq_required & I40EVF_FLAG_AQ_ADD_VLAN_FILTER) {
+               i40evf_add_vlans(adapter);
+               goto watchdog_done;
+       }
+
+       if (adapter->aq_required & I40EVF_FLAG_AQ_DEL_MAC_FILTER) {
+               i40evf_del_ether_addrs(adapter);
+               goto watchdog_done;
+       }
+
+       if (adapter->aq_required & I40EVF_FLAG_AQ_DEL_VLAN_FILTER) {
+               i40evf_del_vlans(adapter);
+               goto watchdog_done;
+       }
+
+       if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_QUEUES) {
+               i40evf_disable_queues(adapter);
+               goto watchdog_done;
+       }
+
+       if (adapter->aq_required & I40EVF_FLAG_AQ_CONFIGURE_QUEUES) {
+               i40evf_configure_queues(adapter);
+               goto watchdog_done;
+       }
+
+       if (adapter->aq_required & I40EVF_FLAG_AQ_ENABLE_QUEUES) {
+               i40evf_enable_queues(adapter);
+               goto watchdog_done;
+       }
+
+       if (adapter->state == __I40EVF_RUNNING)
+               i40evf_request_stats(adapter);
+
+       i40evf_irq_enable(adapter, true);
+       i40evf_fire_sw_int(adapter, 0xFF);
+watchdog_done:
+       if (adapter->aq_required)
+               mod_timer(&adapter->watchdog_timer,
+                         jiffies + msecs_to_jiffies(20));
+       else
+               mod_timer(&adapter->watchdog_timer, jiffies + (HZ * 2));
+       clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       schedule_work(&adapter->adminq_task);
+}
+
+/**
+ * i40evf_configure_rss - Prepare for RSS if used
+ * @adapter: board private structure
+ **/
+static void i40evf_configure_rss(struct i40evf_adapter *adapter)
+{
+       struct i40e_hw *hw = &adapter->hw;
+       u32 lut = 0;
+       int i, j;
+       u64 hena;
+
+       /* Set of random keys generated using kernel random number generator */
+       static const u32 seed[I40E_VFQF_HKEY_MAX_INDEX + 1] = {
+                       0x794221b4, 0xbca0c5ab, 0x6cd5ebd9, 0x1ada6127,
+                       0x983b3aa1, 0x1c4e71eb, 0x7f6328b2, 0xfcdc0da0,
+                       0xc135cafa, 0x7a6f7e2d, 0xe7102d28, 0x163cd12e,
+                       0x4954b126 };
+
+       /* Hash type is configured by the PF - we just supply the key */
+
+       /* Fill out hash function seed */
+       for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++)
+               wr32(hw, I40E_VFQF_HKEY(i), seed[i]);
+
+       /* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */
+       hena = I40E_DEFAULT_RSS_HENA;
+       wr32(hw, I40E_VFQF_HENA(0), (u32)hena);
+       wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32));
+
+       /* Populate the LUT with max no. of queues in round robin fashion */
+       for (i = 0, j = 0; i < I40E_VFQF_HLUT_MAX_INDEX; i++, j++) {
+               if (j == adapter->vsi_res->num_queue_pairs)
+                       j = 0;
+               /* lut = 4-byte sliding window of 4 lut entries */
+               lut = (lut << 8) | (j &
+                        ((0x1 << 8) - 1));
+               /* On i = 3, we have 4 entries in lut; write to the register */
+               if ((i & 3) == 3)
+                       wr32(hw, I40E_VFQF_HLUT(i >> 2), lut);
+       }
+       i40e_flush(hw);
+}
+
+/**
+ * i40evf_reset_task - Call-back task to handle hardware reset
+ * @work: pointer to work_struct
+ *
+ * During reset we need to shut down and reinitialize the admin queue
+ * before we can use it to communicate with the PF again. We also clear
+ * and reinit the rings because that context is lost as well.
+ **/
+static void i40evf_reset_task(struct work_struct *work)
+{
+       struct i40evf_adapter *adapter =
+                       container_of(work, struct i40evf_adapter, reset_task);
+       struct i40e_hw *hw = &adapter->hw;
+       int i = 0, err;
+       uint32_t rstat_val;
+
+       while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
+                               &adapter->crit_section))
+               udelay(500);
+
+       /* wait until the reset is complete */
+       for (i = 0; i < 20; i++) {
+               rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
+                           I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+               if (rstat_val == I40E_VFR_COMPLETED)
+                       break;
+               else
+                       mdelay(100);
+       }
+       if (i == 20) {
+               /* reset never finished */
+               dev_info(&adapter->pdev->dev, "%s: reset never finished: %x\n",
+                       __func__, rstat_val);
+               /* carry on anyway */
+       }
+       i40evf_down(adapter);
+       adapter->state = __I40EVF_RESETTING;
+
+       /* kill and reinit the admin queue */
+       if (i40evf_shutdown_adminq(hw))
+               dev_warn(&adapter->pdev->dev,
+                       "%s: Failed to destroy the Admin Queue resources\n",
+                       __func__);
+       err = i40evf_init_adminq(hw);
+       if (err)
+               dev_info(&adapter->pdev->dev, "%s: init_adminq failed: %d\n",
+                       __func__, err);
+
+       adapter->aq_pending = 0;
+       adapter->aq_required = 0;
+       i40evf_map_queues(adapter);
+       clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+
+       mod_timer(&adapter->watchdog_timer, jiffies + 2);
+
+       if (netif_running(adapter->netdev)) {
+               /* allocate transmit descriptors */
+               err = i40evf_setup_all_tx_resources(adapter);
+               if (err)
+                       goto reset_err;
+
+               /* allocate receive descriptors */
+               err = i40evf_setup_all_rx_resources(adapter);
+               if (err)
+                       goto reset_err;
+
+               i40evf_configure(adapter);
+
+               err = i40evf_up_complete(adapter);
+               if (err)
+                       goto reset_err;
+
+               i40evf_irq_enable(adapter, true);
+       }
+       return;
+reset_err:
+       dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit.\n");
+       i40evf_close(adapter->netdev);
+}
+
+/**
+ * i40evf_adminq_task - worker thread to clean the admin queue
+ * @work: pointer to work_struct containing our data
+ **/
+static void i40evf_adminq_task(struct work_struct *work)
+{
+       struct i40evf_adapter *adapter =
+               container_of(work, struct i40evf_adapter, adminq_task);
+       struct i40e_hw *hw = &adapter->hw;
+       struct i40e_arq_event_info event;
+       struct i40e_virtchnl_msg *v_msg;
+       i40e_status ret;
+       u16 pending;
+
+       event.msg_size = I40EVF_MAX_AQ_BUF_SIZE;
+       event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL);
+       if (!event.msg_buf) {
+               dev_info(&adapter->pdev->dev, "%s: no memory for ARQ clean\n",
+                                __func__);
+               return;
+       }
+       v_msg = (struct i40e_virtchnl_msg *)&event.desc;
+       do {
+               ret = i40evf_clean_arq_element(hw, &event, &pending);
+               if (ret)
+                       break; /* No event to process or error cleaning ARQ */
+
+               i40evf_virtchnl_completion(adapter, v_msg->v_opcode,
+                                          v_msg->v_retval, event.msg_buf,
+                                          event.msg_size);
+               if (pending != 0) {
+                       dev_info(&adapter->pdev->dev,
+                                "%s: ARQ: Pending events %d\n",
+                                __func__, pending);
+                       memset(event.msg_buf, 0, I40EVF_MAX_AQ_BUF_SIZE);
+               }
+       } while (pending);
+
+       /* re-enable Admin queue interrupt cause */
+       i40evf_misc_irq_enable(adapter);
+
+       kfree(event.msg_buf);
+}
+
+/**
+ * i40evf_free_all_tx_resources - Free Tx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ **/
+static void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++)
+               if (adapter->tx_rings[i]->desc)
+                       i40evf_free_tx_resources(adapter->tx_rings[i]);
+
+}
+
+/**
+ * i40evf_setup_all_tx_resources - allocate all queues Tx resources
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not).  It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter)
+{
+       int i, err = 0;
+
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) {
+               err = i40evf_setup_tx_descriptors(adapter->tx_rings[i]);
+               if (!err)
+                       continue;
+               dev_err(&adapter->pdev->dev,
+                       "%s: Allocation for Tx Queue %u failed\n",
+                       __func__, i);
+               break;
+       }
+
+       return err;
+}
+
+/**
+ * i40evf_setup_all_rx_resources - allocate all queues Rx resources
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not).  It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter)
+{
+       int i, err = 0;
+
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) {
+               err = i40evf_setup_rx_descriptors(adapter->rx_rings[i]);
+               if (!err)
+                       continue;
+               dev_err(&adapter->pdev->dev,
+                       "%s: Allocation for Rx Queue %u failed\n",
+                       __func__, i);
+               break;
+       }
+       return err;
+}
+
+/**
+ * i40evf_free_all_rx_resources - Free Rx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+static void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++)
+               if (adapter->rx_rings[i]->desc)
+                       i40evf_free_rx_resources(adapter->rx_rings[i]);
+}
+
+/**
+ * i40evf_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP).  At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ **/
+static int i40evf_open(struct net_device *netdev)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       int err;
+
+       if (adapter->state != __I40EVF_DOWN)
+               return -EBUSY;
+
+       /* allocate transmit descriptors */
+       err = i40evf_setup_all_tx_resources(adapter);
+       if (err)
+               goto err_setup_tx;
+
+       /* allocate receive descriptors */
+       err = i40evf_setup_all_rx_resources(adapter);
+       if (err)
+               goto err_setup_rx;
+
+       /* clear any pending interrupts, may auto mask */
+       err = i40evf_request_traffic_irqs(adapter, netdev->name);
+       if (err)
+               goto err_req_irq;
+
+       i40evf_configure(adapter);
+
+       err = i40evf_up_complete(adapter);
+       if (err)
+               goto err_req_irq;
+
+       i40evf_irq_enable(adapter, true);
+
+       return 0;
+
+err_req_irq:
+       i40evf_down(adapter);
+       i40evf_free_traffic_irqs(adapter);
+err_setup_rx:
+       i40evf_free_all_rx_resources(adapter);
+err_setup_tx:
+       i40evf_free_all_tx_resources(adapter);
+
+       return err;
+}
+
+/**
+ * i40evf_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled. All IRQs except vector 0 (reserved for admin queue)
+ * are freed, along with all transmit and receive resources.
+ **/
+static int i40evf_close(struct net_device *netdev)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+       /* signal that we are down to the interrupt handler */
+       adapter->state = __I40EVF_DOWN;
+       set_bit(__I40E_DOWN, &adapter->vsi.state);
+
+       i40evf_down(adapter);
+       i40evf_free_traffic_irqs(adapter);
+
+       i40evf_free_all_tx_resources(adapter);
+       i40evf_free_all_rx_resources(adapter);
+
+       return 0;
+}
+
+/**
+ * i40evf_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ **/
+static struct net_device_stats *i40evf_get_stats(struct net_device *netdev)
+{
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+       /* only return the current stats */
+       return &adapter->net_stats;
+}
+
+/**
+ * i40evf_reinit_locked - Software reinit
+ * @adapter: board private structure
+ *
+ * Reinititalizes the ring structures in response to a software configuration
+ * change. Roughly the same as close followed by open, but skips releasing
+ * and reallocating the interrupts.
+ **/
+void i40evf_reinit_locked(struct i40evf_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       int err;
+
+       WARN_ON(in_interrupt());
+
+       adapter->state = __I40EVF_RESETTING;
+
+       i40evf_down(adapter);
+
+       /* allocate transmit descriptors */
+       err = i40evf_setup_all_tx_resources(adapter);
+       if (err)
+               goto err_reinit;
+
+       /* allocate receive descriptors */
+       err = i40evf_setup_all_rx_resources(adapter);
+       if (err)
+               goto err_reinit;
+
+       i40evf_configure(adapter);
+
+       err = i40evf_up_complete(adapter);
+       if (err)
+               goto err_reinit;
+
+       i40evf_irq_enable(adapter, true);
+       return;
+
+err_reinit:
+       dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit.\n");
+       i40evf_close(netdev);
+}
+
+/**
+ * i40evf_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ **/
+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;
+
+       /* must set new MTU before calling down or up */
+       netdev->mtu = new_mtu;
+       i40evf_reinit_locked(adapter);
+       return 0;
+}
+
+static const struct net_device_ops i40evf_netdev_ops = {
+       .ndo_open               = i40evf_open,
+       .ndo_stop               = i40evf_close,
+       .ndo_start_xmit         = i40evf_xmit_frame,
+       .ndo_get_stats          = i40evf_get_stats,
+       .ndo_set_rx_mode        = i40evf_set_rx_mode,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = i40evf_set_mac,
+       .ndo_change_mtu         = i40evf_change_mtu,
+       .ndo_tx_timeout         = i40evf_tx_timeout,
+       .ndo_vlan_rx_add_vid    = i40evf_vlan_rx_add_vid,
+       .ndo_vlan_rx_kill_vid   = i40evf_vlan_rx_kill_vid,
+};
+
+/**
+ * i40evf_check_reset_complete - check that VF reset is complete
+ * @hw: pointer to hw struct
+ *
+ * Returns 0 if device is ready to use, or -EBUSY if it's in reset.
+ **/
+static int i40evf_check_reset_complete(struct i40e_hw *hw)
+{
+       u32 rstat;
+       int i;
+
+       for (i = 0; i < 100; i++) {
+               rstat = rd32(hw, I40E_VFGEN_RSTAT);
+               if (rstat == I40E_VFR_VFACTIVE)
+                       return 0;
+               udelay(10);
+       }
+       return -EBUSY;
+}
+
+/**
+ * i40evf_init_task - worker thread to perform delayed initialization
+ * @work: pointer to work_struct containing our data
+ *
+ * This task completes the work that was begun in probe. Due to the nature
+ * of VF-PF communications, we may need to wait tens of milliseconds to get
+ * reponses back from the PF. Rather than busy-wait in probe and bog down the
+ * whole system, we'll do it in a task so we can sleep.
+ * This task only runs during driver init. Once we've established
+ * communications with the PF driver and set up our netdev, the watchdog
+ * takes over.
+ **/
+static void i40evf_init_task(struct work_struct *work)
+{
+       struct i40evf_adapter *adapter = container_of(work,
+                                                     struct i40evf_adapter,
+                                                     init_task.work);
+       struct net_device *netdev = adapter->netdev;
+       struct i40evf_mac_filter *f;
+       struct i40e_hw *hw = &adapter->hw;
+       struct pci_dev *pdev = adapter->pdev;
+       int i, err, bufsz;
+
+       switch (adapter->state) {
+       case __I40EVF_STARTUP:
+               /* driver loaded, probe complete */
+               err = i40e_set_mac_type(hw);
+               if (err) {
+                       dev_info(&pdev->dev, "%s: set_mac_type failed: %d\n",
+                               __func__, err);
+               goto err;
+               }
+               err = i40evf_check_reset_complete(hw);
+               if (err) {
+                       dev_info(&pdev->dev, "%s: device is still in reset (%d).\n",
+                               __func__, err);
+                       goto err;
+               }
+               hw->aq.num_arq_entries = I40EVF_AQ_LEN;
+               hw->aq.num_asq_entries = I40EVF_AQ_LEN;
+               hw->aq.arq_buf_size = I40EVF_MAX_AQ_BUF_SIZE;
+               hw->aq.asq_buf_size = I40EVF_MAX_AQ_BUF_SIZE;
+
+               err = i40evf_init_adminq(hw);
+               if (err) {
+                       dev_info(&pdev->dev, "%s: init_adminq failed: %d\n",
+                               __func__, err);
+                       goto err;
+               }
+               err = i40evf_send_api_ver(adapter);
+               if (err) {
+                       dev_info(&pdev->dev, "%s: unable to send to PF (%d)\n",
+                               __func__, err);
+                       i40evf_shutdown_adminq(hw);
+                       goto err;
+               }
+               adapter->state = __I40EVF_INIT_VERSION_CHECK;
+               goto restart;
+               break;
+       case __I40EVF_INIT_VERSION_CHECK:
+               if (!i40evf_asq_done(hw))
+                       goto err;
+
+               /* aq msg sent, awaiting reply */
+               err = i40evf_verify_api_ver(adapter);
+               if (err) {
+                       dev_err(&pdev->dev, "Unable to verify API version, error %d\n",
+                               err);
+                       goto err;
+               }
+               err = i40evf_send_vf_config_msg(adapter);
+               if (err) {
+                       dev_err(&pdev->dev, "Unable send config request, error %d\n",
+                               err);
+                       goto err;
+               }
+               adapter->state = __I40EVF_INIT_GET_RESOURCES;
+               goto restart;
+               break;
+       case __I40EVF_INIT_GET_RESOURCES:
+               /* aq msg sent, awaiting reply */
+               if (!adapter->vf_res) {
+                       bufsz = sizeof(struct i40e_virtchnl_vf_resource) +
+                               (I40E_MAX_VF_VSI *
+                                sizeof(struct i40e_virtchnl_vsi_resource));
+                       adapter->vf_res = kzalloc(bufsz, GFP_KERNEL);
+                       if (!adapter->vf_res) {
+                               dev_err(&pdev->dev, "%s: unable to allocate memory\n",
+                                       __func__);
+                               goto err;
+                       }
+               }
+               err = i40evf_get_vf_config(adapter);
+               if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK)
+                       goto restart;
+               if (err) {
+                       dev_info(&pdev->dev, "%s: unable to get VF config (%d)\n",
+                               __func__, err);
+                       goto err_alloc;
+               }
+               adapter->state = __I40EVF_INIT_SW;
+               break;
+       default:
+               goto err_alloc;
+       }
+       /* got VF config message back from PF, now we can parse it */
+       for (i = 0; i < adapter->vf_res->num_vsis; i++) {
+               if (adapter->vf_res->vsi_res[i].vsi_type == I40E_VSI_SRIOV)
+                       adapter->vsi_res = &adapter->vf_res->vsi_res[i];
+       }
+       if (!adapter->vsi_res) {
+               dev_info(&pdev->dev, "%s: no LAN VSI found\n", __func__);
+               goto err_alloc;
+       }
+
+       adapter->flags |= I40EVF_FLAG_RX_CSUM_ENABLED;
+
+       adapter->txd_count = I40EVF_DEFAULT_TXD;
+       adapter->rxd_count = I40EVF_DEFAULT_RXD;
+
+       netdev->netdev_ops = &i40evf_netdev_ops;
+       i40evf_set_ethtool_ops(netdev);
+       netdev->watchdog_timeo = 5 * HZ;
+
+       netdev->features |= NETIF_F_SG |
+                           NETIF_F_IP_CSUM |
+                           NETIF_F_SCTP_CSUM |
+                           NETIF_F_IPV6_CSUM |
+                           NETIF_F_TSO |
+                           NETIF_F_TSO6 |
+                           NETIF_F_GRO;
+
+       if (adapter->vf_res->vf_offload_flags
+           & I40E_VIRTCHNL_VF_OFFLOAD_VLAN) {
+               netdev->vlan_features = netdev->features;
+               netdev->features |= NETIF_F_HW_VLAN_CTAG_TX |
+                                   NETIF_F_HW_VLAN_CTAG_RX |
+                                   NETIF_F_HW_VLAN_CTAG_FILTER;
+       }
+
+       /* The HW MAC address was set and/or determined in sw_init */
+       if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
+               dev_info(&pdev->dev,
+                       "Invalid MAC address %pMAC, using random\n",
+                       adapter->hw.mac.addr);
+               random_ether_addr(adapter->hw.mac.addr);
+       }
+       memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
+       memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
+
+       INIT_LIST_HEAD(&adapter->mac_filter_list);
+       INIT_LIST_HEAD(&adapter->vlan_filter_list);
+       f = kzalloc(sizeof(*f), GFP_ATOMIC);
+       if (NULL == f)
+               goto err_sw_init;
+
+       memcpy(f->macaddr, adapter->hw.mac.addr, ETH_ALEN);
+       f->add = true;
+       adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+
+       list_add(&f->list, &adapter->mac_filter_list);
+
+       init_timer(&adapter->watchdog_timer);
+       adapter->watchdog_timer.function = &i40evf_watchdog_timer;
+       adapter->watchdog_timer.data = (unsigned long)adapter;
+       mod_timer(&adapter->watchdog_timer, jiffies + 1);
+
+       err = i40evf_init_interrupt_scheme(adapter);
+       if (err)
+               goto err_sw_init;
+       i40evf_map_rings_to_vectors(adapter);
+       i40evf_configure_rss(adapter);
+       err = i40evf_request_misc_irq(adapter);
+       if (err)
+               goto err_sw_init;
+
+       netif_carrier_off(netdev);
+
+       strcpy(netdev->name, "eth%d");
+
+       adapter->vsi.id = adapter->vsi_res->vsi_id;
+       adapter->vsi.seid = adapter->vsi_res->vsi_id; /* dummy */
+       adapter->vsi.back = adapter;
+       adapter->vsi.base_vector = 1;
+       adapter->vsi.work_limit = I40E_DEFAULT_IRQ_WORK;
+       adapter->vsi.rx_itr_setting = I40E_ITR_DYNAMIC;
+       adapter->vsi.tx_itr_setting = I40E_ITR_DYNAMIC;
+       adapter->vsi.netdev = adapter->netdev;
+
+       err = register_netdev(netdev);
+       if (err)
+               goto err_register;
+
+       adapter->netdev_registered = true;
+
+       netif_tx_stop_all_queues(netdev);
+
+       dev_info(&pdev->dev, "MAC address: %pMAC\n", adapter->hw.mac.addr);
+       if (netdev->features & NETIF_F_GRO)
+               dev_info(&pdev->dev, "GRO is enabled\n");
+
+       dev_info(&pdev->dev, "%s\n", i40evf_driver_string);
+       adapter->state = __I40EVF_DOWN;
+       set_bit(__I40E_DOWN, &adapter->vsi.state);
+       i40evf_misc_irq_enable(adapter);
+       return;
+restart:
+       schedule_delayed_work(&adapter->init_task,
+                             msecs_to_jiffies(50));
+       return;
+
+err_register:
+       i40evf_free_misc_irq(adapter);
+err_sw_init:
+       i40evf_reset_interrupt_capability(adapter);
+       adapter->state = __I40EVF_FAILED;
+err_alloc:
+       kfree(adapter->vf_res);
+       adapter->vf_res = NULL;
+err:
+       /* Things went into the weeds, so try again later */
+       if (++adapter->aq_wait_count > I40EVF_AQ_MAX_ERR) {
+               dev_err(&pdev->dev, "Failed to communicate with PF; giving up.\n");
+               if (hw->aq.asq.count)
+                       i40evf_shutdown_adminq(hw); /* ignore error */
+               adapter->state = __I40EVF_FAILED;
+               return; /* do not reschedule */
+       }
+       schedule_delayed_work(&adapter->init_task, HZ * 3);
+       return;
+}
+
+/**
+ * i40evf_shutdown - Shutdown the device in preparation for a reboot
+ * @pdev: pci device structure
+ **/
+static void i40evf_shutdown(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+
+       netif_device_detach(netdev);
+
+       if (netif_running(netdev))
+               i40evf_close(netdev);
+
+#ifdef CONFIG_PM
+       pci_save_state(pdev);
+
+#endif
+       pci_disable_device(pdev);
+}
+
+/**
+ * i40evf_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in i40evf_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * i40evf_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ **/
+static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       struct net_device *netdev;
+       struct i40evf_adapter *adapter = NULL;
+       struct i40e_hw *hw = NULL;
+       int err, pci_using_dac;
+
+       err = pci_enable_device(pdev);
+       if (err)
+               return err;
+
+       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+               pci_using_dac = true;
+               /* coherent mask for the same size will always succeed if
+                * dma_set_mask does
+                */
+               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+       } else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
+               pci_using_dac = false;
+               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       } else {
+               dev_err(&pdev->dev, "%s: DMA configuration failed: %d\n",
+                        __func__, err);
+               err = -EIO;
+               goto err_dma;
+       }
+
+       err = pci_request_regions(pdev, i40evf_driver_name);
+       if (err) {
+               dev_err(&pdev->dev,
+                       "pci_request_regions failed 0x%x\n", err);
+               goto err_pci_reg;
+       }
+
+       pci_enable_pcie_error_reporting(pdev);
+
+       pci_set_master(pdev);
+
+       netdev = alloc_etherdev_mq(sizeof(struct i40evf_adapter),
+                                  MAX_TX_QUEUES);
+       if (!netdev) {
+               err = -ENOMEM;
+               goto err_alloc_etherdev;
+       }
+
+       SET_NETDEV_DEV(netdev, &pdev->dev);
+
+       pci_set_drvdata(pdev, netdev);
+       adapter = netdev_priv(netdev);
+       if (pci_using_dac)
+               netdev->features |= NETIF_F_HIGHDMA;
+
+       adapter->netdev = netdev;
+       adapter->pdev = pdev;
+
+       hw = &adapter->hw;
+       hw->back = adapter;
+
+       adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
+       adapter->state = __I40EVF_STARTUP;
+
+       /* Call save state here because it relies on the adapter struct. */
+       pci_save_state(pdev);
+
+       hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
+                             pci_resource_len(pdev, 0));
+       if (!hw->hw_addr) {
+               err = -EIO;
+               goto err_ioremap;
+       }
+       hw->vendor_id = pdev->vendor;
+       hw->device_id = pdev->device;
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+       hw->subsystem_vendor_id = pdev->subsystem_vendor;
+       hw->subsystem_device_id = pdev->subsystem_device;
+       hw->bus.device = PCI_SLOT(pdev->devfn);
+       hw->bus.func = PCI_FUNC(pdev->devfn);
+
+       INIT_WORK(&adapter->reset_task, i40evf_reset_task);
+       INIT_WORK(&adapter->adminq_task, i40evf_adminq_task);
+       INIT_WORK(&adapter->watchdog_task, i40evf_watchdog_task);
+       INIT_DELAYED_WORK(&adapter->init_task, i40evf_init_task);
+       schedule_delayed_work(&adapter->init_task, 10);
+
+       return 0;
+
+err_ioremap:
+       free_netdev(netdev);
+err_alloc_etherdev:
+       pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+       pci_disable_device(pdev);
+       return err;
+}
+
+#ifdef CONFIG_PM
+/**
+ * i40evf_suspend - Power management suspend routine
+ * @pdev: PCI device information struct
+ * @state: unused
+ *
+ * Called when the system (VM) is entering sleep/suspend.
+ **/
+static int i40evf_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       int retval = 0;
+
+       netif_device_detach(netdev);
+
+       if (netif_running(netdev)) {
+               rtnl_lock();
+               i40evf_down(adapter);
+               rtnl_unlock();
+       }
+       i40evf_free_misc_irq(adapter);
+       i40evf_reset_interrupt_capability(adapter);
+
+       retval = pci_save_state(pdev);
+       if (retval)
+               return retval;
+
+       pci_disable_device(pdev);
+
+       return 0;
+}
+
+/**
+ * i40evf_resume - Power managment resume routine
+ * @pdev: PCI device information struct
+ *
+ * Called when the system (VM) is resumed from sleep/suspend.
+ **/
+static int i40evf_resume(struct pci_dev *pdev)
+{
+       struct i40evf_adapter *adapter = pci_get_drvdata(pdev);
+       struct net_device *netdev = adapter->netdev;
+       u32 err;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       /* pci_restore_state clears dev->state_saved so call
+        * pci_save_state to restore it.
+        */
+       pci_save_state(pdev);
+
+       err = pci_enable_device_mem(pdev);
+       if (err) {
+               dev_err(&pdev->dev, "Cannot enable PCI device from suspend.\n");
+               return err;
+       }
+       pci_set_master(pdev);
+
+       rtnl_lock();
+       err = i40evf_set_interrupt_capability(adapter);
+       if (err) {
+               dev_err(&pdev->dev, "Cannot enable MSI-X interrupts.\n");
+               return err;
+       }
+       err = i40evf_request_misc_irq(adapter);
+       rtnl_unlock();
+       if (err) {
+               dev_err(&pdev->dev, "Cannot get interrupt vector.\n");
+               return err;
+       }
+
+       schedule_work(&adapter->reset_task);
+
+       netif_device_attach(netdev);
+
+       return err;
+}
+
+#endif /* CONFIG_PM */
+/**
+ * i40evf_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * i40evf_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ **/
+static void i40evf_remove(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct i40evf_adapter *adapter = netdev_priv(netdev);
+       struct i40e_hw *hw = &adapter->hw;
+
+       cancel_delayed_work_sync(&adapter->init_task);
+
+       if (adapter->netdev_registered) {
+               unregister_netdev(netdev);
+               adapter->netdev_registered = false;
+       }
+       adapter->state = __I40EVF_REMOVE;
+
+       if (adapter->num_msix_vectors) {
+               i40evf_misc_irq_disable(adapter);
+               del_timer_sync(&adapter->watchdog_timer);
+
+               flush_scheduled_work();
+
+               i40evf_free_misc_irq(adapter);
+
+               i40evf_reset_interrupt_capability(adapter);
+       }
+
+       if (hw->aq.asq.count)
+               i40evf_shutdown_adminq(hw);
+
+       iounmap(hw->hw_addr);
+       pci_release_regions(pdev);
+
+       i40evf_free_queues(adapter);
+       kfree(adapter->vf_res);
+
+       free_netdev(netdev);
+
+       pci_disable_pcie_error_reporting(pdev);
+
+       pci_disable_device(pdev);
+}
+
+static struct pci_driver i40evf_driver = {
+       .name     = i40evf_driver_name,
+       .id_table = i40evf_pci_tbl,
+       .probe    = i40evf_probe,
+       .remove   = i40evf_remove,
+#ifdef CONFIG_PM
+       .suspend  = i40evf_suspend,
+       .resume   = i40evf_resume,
+#endif
+       .shutdown = i40evf_shutdown,
+};
+
+/**
+ * i40e_init_module - Driver Registration Routine
+ *
+ * i40e_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ **/
+static int __init i40evf_init_module(void)
+{
+       int ret;
+       pr_info("i40evf: %s - version %s\n", i40evf_driver_string,
+              i40evf_driver_version);
+
+       pr_info("%s\n", i40evf_copyright);
+
+       ret = pci_register_driver(&i40evf_driver);
+       return ret;
+}
+
+module_init(i40evf_init_module);
+
+/**
+ * i40e_exit_module - Driver Exit Cleanup Routine
+ *
+ * i40e_exit_module is called just before the driver is removed
+ * from memory.
+ **/
+static void __exit i40evf_exit_module(void)
+{
+       pci_unregister_driver(&i40evf_driver);
+}
+
+module_exit(i40evf_exit_module);
+
+/* i40evf_main.c */
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
new file mode 100644 (file)
index 0000000..e6978d7
--- /dev/null
@@ -0,0 +1,772 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#include "i40evf.h"
+#include "i40e_prototype.h"
+
+/* busy wait delay in msec */
+#define I40EVF_BUSY_WAIT_DELAY 10
+#define I40EVF_BUSY_WAIT_COUNT 50
+
+/**
+ * i40evf_send_pf_msg
+ * @adapter: adapter structure
+ * @op: virtual channel opcode
+ * @msg: pointer to message buffer
+ * @len: message length
+ *
+ * Send message to PF and print status if failure.
+ **/
+static int i40evf_send_pf_msg(struct i40evf_adapter *adapter,
+                             enum i40e_virtchnl_ops op, u8 *msg, u16 len)
+{
+       struct i40e_hw *hw = &adapter->hw;
+       i40e_status err;
+
+       err = i40e_aq_send_msg_to_pf(hw, op, 0, msg, len, NULL);
+       if (err)
+               dev_err(&adapter->pdev->dev, "Unable to send opcode %d to PF, error %d, aq status %d\n",
+                       op, err, hw->aq.asq_last_status);
+       return err;
+}
+
+/**
+ * i40evf_send_api_ver
+ * @adapter: adapter structure
+ *
+ * Send API version admin queue message to the PF. The reply is not checked
+ * in this function. Returns 0 if the message was successfully
+ * sent, or one of the I40E_ADMIN_QUEUE_ERROR_ statuses if not.
+ **/
+int i40evf_send_api_ver(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_version_info vvi;
+
+       vvi.major = I40E_VIRTCHNL_VERSION_MAJOR;
+       vvi.minor = I40E_VIRTCHNL_VERSION_MINOR;
+
+       return i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_VERSION, (u8 *)&vvi,
+                                 sizeof(vvi));
+}
+
+/**
+ * i40evf_verify_api_ver
+ * @adapter: adapter structure
+ *
+ * Compare API versions with the PF. Must be called after admin queue is
+ * initialized. Returns 0 if API versions match, -EIO if
+ * they do not, or I40E_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty.
+ **/
+int i40evf_verify_api_ver(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_version_info *pf_vvi;
+       struct i40e_hw *hw = &adapter->hw;
+       struct i40e_arq_event_info event;
+       i40e_status err;
+
+       event.msg_size = I40EVF_MAX_AQ_BUF_SIZE;
+       event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL);
+       if (!event.msg_buf) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = i40evf_clean_arq_element(hw, &event, NULL);
+       if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK)
+               goto out_alloc;
+
+       err = (i40e_status)le32_to_cpu(event.desc.cookie_low);
+       if (err) {
+               err = -EIO;
+               goto out_alloc;
+       }
+
+       if ((enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high) !=
+           I40E_VIRTCHNL_OP_VERSION) {
+               err = -EIO;
+               goto out_alloc;
+       }
+
+       pf_vvi = (struct i40e_virtchnl_version_info *)event.msg_buf;
+       if ((pf_vvi->major != I40E_VIRTCHNL_VERSION_MAJOR) ||
+           (pf_vvi->minor != I40E_VIRTCHNL_VERSION_MINOR))
+               err = -EIO;
+
+out_alloc:
+       kfree(event.msg_buf);
+out:
+       return err;
+}
+
+/**
+ * i40evf_send_vf_config_msg
+ * @adapter: adapter structure
+ *
+ * Send VF configuration request admin queue message to the PF. The reply
+ * is not checked in this function. Returns 0 if the message was
+ * successfully sent, or one of the I40E_ADMIN_QUEUE_ERROR_ statuses if not.
+ **/
+int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
+{
+       return i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_GET_VF_RESOURCES,
+                                 NULL, 0);
+}
+
+/**
+ * i40evf_get_vf_config
+ * @hw: pointer to the hardware structure
+ * @len: length of buffer
+ *
+ * Get VF configuration from PF and populate hw structure. Must be called after
+ * admin queue is initialized. Busy waits until response is received from PF,
+ * with maximum timeout. Response from PF is returned in the buffer for further
+ * processing by the caller.
+ **/
+int i40evf_get_vf_config(struct i40evf_adapter *adapter)
+{
+       struct i40e_hw *hw = &adapter->hw;
+       struct i40e_arq_event_info event;
+       u16 len;
+       i40e_status err;
+
+       len =  sizeof(struct i40e_virtchnl_vf_resource) +
+               I40E_MAX_VF_VSI * sizeof(struct i40e_virtchnl_vsi_resource);
+       event.msg_size = len;
+       event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL);
+       if (!event.msg_buf) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = i40evf_clean_arq_element(hw, &event, NULL);
+       if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK)
+               goto out_alloc;
+
+       err = (i40e_status)le32_to_cpu(event.desc.cookie_low);
+       if (err) {
+               dev_err(&adapter->pdev->dev,
+                       "%s: Error returned from PF, %d, %d\n", __func__,
+                       le32_to_cpu(event.desc.cookie_high),
+                       le32_to_cpu(event.desc.cookie_low));
+               err = -EIO;
+               goto out_alloc;
+       }
+
+       if ((enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high) !=
+           I40E_VIRTCHNL_OP_GET_VF_RESOURCES) {
+               dev_err(&adapter->pdev->dev,
+                       "%s: Invalid response from PF, %d, %d\n", __func__,
+                       le32_to_cpu(event.desc.cookie_high),
+                       le32_to_cpu(event.desc.cookie_low));
+               err = -EIO;
+               goto out_alloc;
+       }
+       memcpy(adapter->vf_res, event.msg_buf, min(event.msg_size, len));
+
+       i40e_vf_parse_hw_config(hw, adapter->vf_res);
+out_alloc:
+       kfree(event.msg_buf);
+out:
+       return err;
+}
+
+/**
+ * i40evf_configure_queues
+ * @adapter: adapter structure
+ *
+ * Request that the PF set up our (previously allocated) queues.
+ **/
+void i40evf_configure_queues(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_vsi_queue_config_info *vqci;
+       struct i40e_virtchnl_queue_pair_info *vqpi;
+       int pairs = adapter->vsi_res->num_queue_pairs;
+       int i, len;
+
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* bail because we already have a command pending */
+               dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
+                       __func__, adapter->current_op);
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES;
+       len = sizeof(struct i40e_virtchnl_vsi_queue_config_info) +
+                      (sizeof(struct i40e_virtchnl_queue_pair_info) * pairs);
+       vqci = kzalloc(len, GFP_ATOMIC);
+       if (!vqci) {
+               dev_err(&adapter->pdev->dev, "%s: unable to allocate memory\n",
+                       __func__);
+               return;
+       }
+       vqci->vsi_id = adapter->vsi_res->vsi_id;
+       vqci->num_queue_pairs = pairs;
+       vqpi = vqci->qpair;
+       /* Size check is not needed here - HW max is 16 queue pairs, and we
+        * can fit info for 31 of them into the AQ buffer before it overflows.
+        */
+       for (i = 0; i < pairs; i++) {
+               vqpi->txq.vsi_id = vqci->vsi_id;
+               vqpi->txq.queue_id = i;
+               vqpi->txq.ring_len = adapter->tx_rings[i]->count;
+               vqpi->txq.dma_ring_addr = adapter->tx_rings[i]->dma;
+
+               vqpi->rxq.vsi_id = vqci->vsi_id;
+               vqpi->rxq.queue_id = i;
+               vqpi->rxq.ring_len = adapter->rx_rings[i]->count;
+               vqpi->rxq.dma_ring_addr = adapter->rx_rings[i]->dma;
+               vqpi->rxq.max_pkt_size = adapter->netdev->mtu
+                                       + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+               vqpi->rxq.databuffer_size = adapter->rx_rings[i]->rx_buf_len;
+               vqpi++;
+       }
+
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+                          (u8 *)vqci, len);
+       kfree(vqci);
+       adapter->aq_pending |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
+       adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
+}
+
+/**
+ * i40evf_enable_queues
+ * @adapter: adapter structure
+ *
+ * Request that the PF enable all of our queues.
+ **/
+void i40evf_enable_queues(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_queue_select vqs;
+
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* bail because we already have a command pending */
+               dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
+                       __func__, adapter->current_op);
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_ENABLE_QUEUES;
+       vqs.vsi_id = adapter->vsi_res->vsi_id;
+       vqs.tx_queues = (1 << adapter->vsi_res->num_queue_pairs) - 1;
+       vqs.rx_queues = vqs.tx_queues;
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
+                          (u8 *)&vqs, sizeof(vqs));
+       adapter->aq_pending |= I40EVF_FLAG_AQ_ENABLE_QUEUES;
+       adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_QUEUES;
+}
+
+/**
+ * i40evf_disable_queues
+ * @adapter: adapter structure
+ *
+ * Request that the PF disable all of our queues.
+ **/
+void i40evf_disable_queues(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_queue_select vqs;
+
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* bail because we already have a command pending */
+               dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
+                       __func__, adapter->current_op);
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_DISABLE_QUEUES;
+       vqs.vsi_id = adapter->vsi_res->vsi_id;
+       vqs.tx_queues = (1 << adapter->vsi_res->num_queue_pairs) - 1;
+       vqs.rx_queues = vqs.tx_queues;
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DISABLE_QUEUES,
+                          (u8 *)&vqs, sizeof(vqs));
+       adapter->aq_pending |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
+       adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_QUEUES;
+}
+
+/**
+ * i40evf_map_queues
+ * @adapter: adapter structure
+ *
+ * Request that the PF map queues to interrupt vectors. Misc causes, including
+ * admin queue, are always mapped to vector 0.
+ **/
+void i40evf_map_queues(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_irq_map_info *vimi;
+       int v_idx, q_vectors, len;
+       struct i40e_q_vector *q_vector;
+
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* bail because we already have a command pending */
+               dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
+                       __func__, adapter->current_op);
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP;
+
+       q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+       len = sizeof(struct i40e_virtchnl_irq_map_info) +
+             (adapter->num_msix_vectors *
+               sizeof(struct i40e_virtchnl_vector_map));
+       vimi = kzalloc(len, GFP_ATOMIC);
+       if (!vimi) {
+               dev_err(&adapter->pdev->dev, "%s: unable to allocate memory\n",
+                       __func__);
+               return;
+       }
+
+       vimi->num_vectors = adapter->num_msix_vectors;
+       /* Queue vectors first */
+       for (v_idx = 0; v_idx < q_vectors; v_idx++) {
+               q_vector = adapter->q_vector[v_idx];
+               vimi->vecmap[v_idx].vsi_id = adapter->vsi_res->vsi_id;
+               vimi->vecmap[v_idx].vector_id = v_idx + NONQ_VECS;
+               vimi->vecmap[v_idx].txq_map = q_vector->ring_mask;
+               vimi->vecmap[v_idx].rxq_map = q_vector->ring_mask;
+       }
+       /* Misc vector last - this is only for AdminQ messages */
+       vimi->vecmap[v_idx].vsi_id = adapter->vsi_res->vsi_id;
+       vimi->vecmap[v_idx].vector_id = 0;
+       vimi->vecmap[v_idx].txq_map = 0;
+       vimi->vecmap[v_idx].rxq_map = 0;
+
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
+                          (u8 *)vimi, len);
+       kfree(vimi);
+       adapter->aq_pending |= I40EVF_FLAG_AQ_MAP_VECTORS;
+       adapter->aq_required &= ~I40EVF_FLAG_AQ_MAP_VECTORS;
+}
+
+/**
+ * i40evf_add_ether_addrs
+ * @adapter: adapter structure
+ * @addrs: the MAC address filters to add (contiguous)
+ * @count: number of filters
+ *
+ * Request that the PF add one or more addresses to our filters.
+ **/
+void i40evf_add_ether_addrs(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_ether_addr_list *veal;
+       int len, i = 0, count = 0;
+       struct i40evf_mac_filter *f;
+
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* bail because we already have a command pending */
+               dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
+                       __func__, adapter->current_op);
+               return;
+       }
+       list_for_each_entry(f, &adapter->mac_filter_list, list) {
+               if (f->add)
+                       count++;
+       }
+       if (!count) {
+               adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS;
+
+       len = sizeof(struct i40e_virtchnl_ether_addr_list) +
+             (count * sizeof(struct i40e_virtchnl_ether_addr));
+       if (len > I40EVF_MAX_AQ_BUF_SIZE) {
+               dev_warn(&adapter->pdev->dev, "%s: Too many MAC address changes in one request.\n",
+                       __func__);
+               count = (I40EVF_MAX_AQ_BUF_SIZE -
+                        sizeof(struct i40e_virtchnl_ether_addr_list)) /
+                       sizeof(struct i40e_virtchnl_ether_addr);
+               len = I40EVF_MAX_AQ_BUF_SIZE;
+       }
+
+       veal = kzalloc(len, GFP_ATOMIC);
+       if (!veal) {
+               dev_err(&adapter->pdev->dev, "%s: unable to allocate memory\n",
+                       __func__);
+               return;
+       }
+       veal->vsi_id = adapter->vsi_res->vsi_id;
+       veal->num_elements = count;
+       list_for_each_entry(f, &adapter->mac_filter_list, list) {
+               if (f->add) {
+                       memcpy(veal->list[i].addr, f->macaddr, ETH_ALEN);
+                       i++;
+                       f->add = false;
+               }
+       }
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
+                          (u8 *)veal, len);
+       kfree(veal);
+       adapter->aq_pending |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+       adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+
+}
+
+/**
+ * i40evf_del_ether_addrs
+ * @adapter: adapter structure
+ * @addrs: the MAC address filters to remove (contiguous)
+ * @count: number of filtes
+ *
+ * Request that the PF remove one or more addresses from our filters.
+ **/
+void i40evf_del_ether_addrs(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_ether_addr_list *veal;
+       struct i40evf_mac_filter *f, *ftmp;
+       int len, i = 0, count = 0;
+
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* bail because we already have a command pending */
+               dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
+                       __func__, adapter->current_op);
+               return;
+       }
+       list_for_each_entry(f, &adapter->mac_filter_list, list) {
+               if (f->remove)
+                       count++;
+       }
+       if (!count) {
+               adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS;
+
+       len = sizeof(struct i40e_virtchnl_ether_addr_list) +
+             (count * sizeof(struct i40e_virtchnl_ether_addr));
+       if (len > I40EVF_MAX_AQ_BUF_SIZE) {
+               dev_warn(&adapter->pdev->dev, "%s: Too many MAC address changes in one request.\n",
+                       __func__);
+               count = (I40EVF_MAX_AQ_BUF_SIZE -
+                        sizeof(struct i40e_virtchnl_ether_addr_list)) /
+                       sizeof(struct i40e_virtchnl_ether_addr);
+               len = I40EVF_MAX_AQ_BUF_SIZE;
+       }
+       veal = kzalloc(len, GFP_ATOMIC);
+       if (!veal) {
+               dev_err(&adapter->pdev->dev, "%s: unable to allocate memory\n",
+                       __func__);
+               return;
+       }
+       veal->vsi_id = adapter->vsi_res->vsi_id;
+       veal->num_elements = count;
+       list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+               if (f->remove) {
+                       memcpy(veal->list[i].addr, f->macaddr, ETH_ALEN);
+                       i++;
+                       list_del(&f->list);
+                       kfree(f);
+               }
+       }
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
+                          (u8 *)veal, len);
+       kfree(veal);
+       adapter->aq_pending |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+       adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+}
+
+/**
+ * i40evf_add_vlans
+ * @adapter: adapter structure
+ * @vlans: the VLANs to add
+ * @count: number of VLANs
+ *
+ * Request that the PF add one or more VLAN filters to our VSI.
+ **/
+void i40evf_add_vlans(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_vlan_filter_list *vvfl;
+       int len, i = 0, count = 0;
+       struct i40evf_vlan_filter *f;
+
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* bail because we already have a command pending */
+               dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
+                       __func__, adapter->current_op);
+               return;
+       }
+
+       list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+               if (f->add)
+                       count++;
+       }
+       if (!count) {
+               adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_ADD_VLAN;
+
+       len = sizeof(struct i40e_virtchnl_vlan_filter_list) +
+             (count * sizeof(u16));
+       if (len > I40EVF_MAX_AQ_BUF_SIZE) {
+               dev_warn(&adapter->pdev->dev, "%s: Too many VLAN changes in one request.\n",
+                       __func__);
+               count = (I40EVF_MAX_AQ_BUF_SIZE -
+                        sizeof(struct i40e_virtchnl_vlan_filter_list)) /
+                       sizeof(u16);
+               len = I40EVF_MAX_AQ_BUF_SIZE;
+       }
+       vvfl = kzalloc(len, GFP_ATOMIC);
+       if (!vvfl) {
+               dev_err(&adapter->pdev->dev, "%s: unable to allocate memory\n",
+                       __func__);
+               return;
+       }
+       vvfl->vsi_id = adapter->vsi_res->vsi_id;
+       vvfl->num_elements = count;
+       list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+               if (f->add) {
+                       vvfl->vlan_id[i] = f->vlan;
+                       i++;
+                       f->add = false;
+               }
+       }
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
+       kfree(vvfl);
+       adapter->aq_pending |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+       adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+}
+
+/**
+ * i40evf_del_vlans
+ * @adapter: adapter structure
+ * @vlans: the VLANs to remove
+ * @count: number of VLANs
+ *
+ * Request that the PF remove one or more VLAN filters from our VSI.
+ **/
+void i40evf_del_vlans(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_vlan_filter_list *vvfl;
+       struct i40evf_vlan_filter *f, *ftmp;
+       int len, i = 0, count = 0;
+
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* bail because we already have a command pending */
+               dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
+                       __func__, adapter->current_op);
+               return;
+       }
+
+       list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+               if (f->remove)
+                       count++;
+       }
+       if (!count) {
+               adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_DEL_VLAN;
+
+       len = sizeof(struct i40e_virtchnl_vlan_filter_list) +
+             (count * sizeof(u16));
+       if (len > I40EVF_MAX_AQ_BUF_SIZE) {
+               dev_warn(&adapter->pdev->dev, "%s: Too many VLAN changes in one request.\n",
+                       __func__);
+               count = (I40EVF_MAX_AQ_BUF_SIZE -
+                        sizeof(struct i40e_virtchnl_vlan_filter_list)) /
+                       sizeof(u16);
+               len = I40EVF_MAX_AQ_BUF_SIZE;
+       }
+       vvfl = kzalloc(len, GFP_ATOMIC);
+       if (!vvfl) {
+               dev_err(&adapter->pdev->dev, "%s: unable to allocate memory\n",
+                       __func__);
+               return;
+       }
+       vvfl->vsi_id = adapter->vsi_res->vsi_id;
+       vvfl->num_elements = count;
+       list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
+               if (f->remove) {
+                       vvfl->vlan_id[i] = f->vlan;
+                       i++;
+                       list_del(&f->list);
+                       kfree(f);
+               }
+       }
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
+       kfree(vvfl);
+       adapter->aq_pending |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+       adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+}
+
+/**
+ * i40evf_set_promiscuous
+ * @adapter: adapter structure
+ * @flags: bitmask to control unicast/multicast promiscuous.
+ *
+ * Request that the PF enable promiscuous mode for our VSI.
+ **/
+void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags)
+{
+       struct i40e_virtchnl_promisc_info vpi;
+
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* bail because we already have a command pending */
+               dev_err(&adapter->pdev->dev, "%s: command %d pending\n",
+                       __func__, adapter->current_op);
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE;
+       vpi.vsi_id = adapter->vsi_res->vsi_id;
+       vpi.flags = flags;
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
+                          (u8 *)&vpi, sizeof(vpi));
+}
+
+/**
+ * i40evf_request_stats
+ * @adapter: adapter structure
+ *
+ * Request VSI statistics from PF.
+ **/
+void i40evf_request_stats(struct i40evf_adapter *adapter)
+{
+       struct i40e_virtchnl_queue_select vqs;
+       if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
+               /* no error message, this isn't crucial */
+               return;
+       }
+       adapter->current_op = I40E_VIRTCHNL_OP_GET_STATS;
+       vqs.vsi_id = adapter->vsi_res->vsi_id;
+       /* queue maps are ignored for this message - only the vsi is used */
+       if (i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_GET_STATS,
+                              (u8 *)&vqs, sizeof(vqs)))
+               /* if the request failed, don't lock out others */
+               adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
+}
+
+/**
+ * i40evf_virtchnl_completion
+ * @adapter: adapter structure
+ * @v_opcode: opcode sent by PF
+ * @v_retval: retval sent by PF
+ * @msg: message sent by PF
+ * @msglen: message length
+ *
+ * Asynchronous completion function for admin queue messages. Rather than busy
+ * wait, we fire off our requests and assume that no errors will be returned.
+ * This function handles the reply messages.
+ **/
+void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
+                               enum i40e_virtchnl_ops v_opcode,
+                               i40e_status v_retval,
+                               u8 *msg, u16 msglen)
+{
+       struct net_device *netdev = adapter->netdev;
+
+       if (v_opcode == I40E_VIRTCHNL_OP_EVENT) {
+               struct i40e_virtchnl_pf_event *vpe =
+                       (struct i40e_virtchnl_pf_event *)msg;
+               switch (vpe->event) {
+               case I40E_VIRTCHNL_EVENT_LINK_CHANGE:
+                       adapter->link_up =
+                               vpe->event_data.link_event.link_status;
+                       if (adapter->link_up && !netif_carrier_ok(netdev)) {
+                               dev_info(&adapter->pdev->dev, "NIC Link is Up\n");
+                               netif_carrier_on(netdev);
+                               netif_tx_wake_all_queues(netdev);
+                       } else if (!adapter->link_up) {
+                               dev_info(&adapter->pdev->dev, "NIC Link is Down\n");
+                               netif_carrier_off(netdev);
+                               netif_tx_stop_all_queues(netdev);
+                       }
+                       break;
+               case I40E_VIRTCHNL_EVENT_RESET_IMPENDING:
+                       adapter->state = __I40EVF_RESETTING;
+                       schedule_work(&adapter->reset_task);
+                       dev_info(&adapter->pdev->dev,
+                                "%s: hardware reset pending\n", __func__);
+                       break;
+               default:
+                       dev_err(&adapter->pdev->dev,
+                               "%s: Unknown event %d from pf\n",
+                               __func__, vpe->event);
+                       break;
+
+               }
+               return;
+       }
+       if (v_opcode != adapter->current_op) {
+               dev_err(&adapter->pdev->dev, "%s: Pending op is %d, received %d.\n",
+                       __func__, adapter->current_op, v_opcode);
+               /* We're probably completely screwed at this point, but clear
+                * the current op and try to carry on....
+                */
+               adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
+               return;
+       }
+       if (v_retval) {
+               dev_err(&adapter->pdev->dev, "%s: PF returned error %d to our request %d!\n",
+                       __func__, v_retval, v_opcode);
+       }
+       switch (v_opcode) {
+       case I40E_VIRTCHNL_OP_GET_STATS: {
+               struct i40e_eth_stats *stats =
+                       (struct i40e_eth_stats *)msg;
+               adapter->net_stats.rx_packets = stats->rx_unicast +
+                                                stats->rx_multicast +
+                                                stats->rx_broadcast;
+               adapter->net_stats.tx_packets = stats->tx_unicast +
+                                                stats->tx_multicast +
+                                                stats->tx_broadcast;
+               adapter->net_stats.rx_bytes = stats->rx_bytes;
+               adapter->net_stats.tx_bytes = stats->tx_bytes;
+               adapter->net_stats.rx_errors = stats->rx_errors;
+               adapter->net_stats.tx_errors = stats->tx_errors;
+               adapter->net_stats.rx_dropped = stats->rx_missed;
+               adapter->net_stats.tx_dropped = stats->tx_discards;
+               adapter->current_stats = *stats;
+               }
+               break;
+       case I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS:
+               adapter->aq_pending &= ~(I40EVF_FLAG_AQ_ADD_MAC_FILTER);
+               break;
+       case I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS:
+               adapter->aq_pending &= ~(I40EVF_FLAG_AQ_DEL_MAC_FILTER);
+               break;
+       case I40E_VIRTCHNL_OP_ADD_VLAN:
+               adapter->aq_pending &= ~(I40EVF_FLAG_AQ_ADD_VLAN_FILTER);
+               break;
+       case I40E_VIRTCHNL_OP_DEL_VLAN:
+               adapter->aq_pending &= ~(I40EVF_FLAG_AQ_DEL_VLAN_FILTER);
+               break;
+       case I40E_VIRTCHNL_OP_ENABLE_QUEUES:
+               adapter->aq_pending &= ~(I40EVF_FLAG_AQ_ENABLE_QUEUES);
+               /* enable transmits */
+               i40evf_irq_enable(adapter, true);
+               netif_tx_start_all_queues(adapter->netdev);
+               netif_carrier_on(adapter->netdev);
+               break;
+       case I40E_VIRTCHNL_OP_DISABLE_QUEUES:
+               adapter->aq_pending &= ~(I40EVF_FLAG_AQ_DISABLE_QUEUES);
+               break;
+       case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES:
+               adapter->aq_pending &= ~(I40EVF_FLAG_AQ_CONFIGURE_QUEUES);
+               break;
+       case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP:
+               adapter->aq_pending &= ~(I40EVF_FLAG_AQ_MAP_VECTORS);
+               break;
+       default:
+               dev_warn(&adapter->pdev->dev, "%s: Received unexpected message %d from PF.\n",
+                       __func__, v_opcode);
+               break;
+       } /* switch v_opcode */
+       adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
+}
index 04bf22e5ee315ffb9c9c789a7dad585e02063ca1..675435fc2e53c8b30c84571a02184e50088a242f 100644 (file)
@@ -1745,7 +1745,7 @@ static int igbvf_set_mac(struct net_device *netdev, void *p)
 
        hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
 
-       if (memcmp(addr->sa_data, hw->mac.addr, 6))
+       if (!ether_addr_equal(addr->sa_data, hw->mac.addr))
                return -EADDRNOTAVAIL;
 
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
index d6f0c0d8cf11ddb395617e2749bbf25329cae42c..359f6e60320d7321388d5c84f6c55827b051ff71 100644 (file)
@@ -291,7 +291,9 @@ static int ixgbe_pci_sriov_disable(struct pci_dev *dev)
 {
        struct ixgbe_adapter *adapter = pci_get_drvdata(dev);
        int err;
+#ifdef CONFIG_PCI_IOV
        u32 current_flags = adapter->flags;
+#endif
 
        err = ixgbe_disable_sriov(adapter);
 
@@ -715,8 +717,7 @@ static int ixgbe_set_vf_mac_addr(struct ixgbe_adapter *adapter,
        }
 
        if (adapter->vfinfo[vf].pf_set_mac &&
-           memcmp(adapter->vfinfo[vf].vf_mac_addresses, new_mac,
-                  ETH_ALEN)) {
+           !ether_addr_equal(adapter->vfinfo[vf].vf_mac_addresses, new_mac)) {
                e_warn(drv,
                       "VF %d attempted to override administratively set MAC address\n"
                       "Reload the VF driver to resume operations\n",
index 7354960b583bc83b45a8aadd001c03c456912f81..c4eeb69a5beee6f4e4214746b9c958c614e64beb 100644 (file)
@@ -92,6 +92,12 @@ static int orion_mdio_wait_ready(struct mii_bus *bus)
                        if (time_is_before_jiffies(end))
                                ++timedout;
                } else {
+                       /* wait_event_timeout does not guarantee a delay of at
+                        * least one whole jiffie, so timeout must be no less
+                        * than two.
+                        */
+                       if (timeout < 2)
+                               timeout = 2;
                        wait_event_timeout(dev->smi_busy_wait,
                                           orion_mdio_smi_is_done(dev),
                                           timeout);
index eb520ab640143b918615ceae86a8f5de36bd23b7..563495d8975a5399c44140f94e096f199ca1a350 100644 (file)
@@ -6,6 +6,7 @@ config MLX4_EN
        tristate "Mellanox Technologies 10Gbit Ethernet support"
        depends on PCI
        select MLX4_CORE
+       select PTP_1588_CLOCK
        ---help---
          This driver supports Mellanox Technologies ConnectX Ethernet
          devices.
index fd644107131931adc89b5713ef74c19c4499347c..abaf6bb22416232fc055f3ef8b6c414be701734d 100644 (file)
@@ -42,6 +42,10 @@ int mlx4_en_timestamp_config(struct net_device *dev, int tx_type, int rx_filter)
        int port_up = 0;
        int err = 0;
 
+       if (priv->hwtstamp_config.tx_type == tx_type &&
+           priv->hwtstamp_config.rx_filter == rx_filter)
+               return 0;
+
        mutex_lock(&mdev->state_lock);
        if (priv->port_up) {
                port_up = 1;
@@ -103,19 +107,191 @@ void mlx4_en_fill_hwtstamps(struct mlx4_en_dev *mdev,
                            struct skb_shared_hwtstamps *hwts,
                            u64 timestamp)
 {
+       unsigned long flags;
        u64 nsec;
 
+       read_lock_irqsave(&mdev->clock_lock, flags);
        nsec = timecounter_cyc2time(&mdev->clock, timestamp);
+       read_unlock_irqrestore(&mdev->clock_lock, flags);
 
        memset(hwts, 0, sizeof(struct skb_shared_hwtstamps));
        hwts->hwtstamp = ns_to_ktime(nsec);
 }
 
+/**
+ * mlx4_en_remove_timestamp - disable PTP device
+ * @mdev: board private structure
+ *
+ * Stop the PTP support.
+ **/
+void mlx4_en_remove_timestamp(struct mlx4_en_dev *mdev)
+{
+       if (mdev->ptp_clock) {
+               ptp_clock_unregister(mdev->ptp_clock);
+               mdev->ptp_clock = NULL;
+               mlx4_info(mdev, "removed PHC\n");
+       }
+}
+
+void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev)
+{
+       bool timeout = time_is_before_jiffies(mdev->last_overflow_check +
+                                             mdev->overflow_period);
+       unsigned long flags;
+
+       if (timeout) {
+               write_lock_irqsave(&mdev->clock_lock, flags);
+               timecounter_read(&mdev->clock);
+               write_unlock_irqrestore(&mdev->clock_lock, flags);
+               mdev->last_overflow_check = jiffies;
+       }
+}
+
+/**
+ * mlx4_en_phc_adjfreq - adjust the frequency of the hardware clock
+ * @ptp: ptp clock structure
+ * @delta: Desired frequency change in parts per billion
+ *
+ * Adjust the frequency of the PHC cycle counter by the indicated delta from
+ * the base frequency.
+ **/
+static int mlx4_en_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
+{
+       u64 adj;
+       u32 diff, mult;
+       int neg_adj = 0;
+       unsigned long flags;
+       struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev,
+                                               ptp_clock_info);
+
+       if (delta < 0) {
+               neg_adj = 1;
+               delta = -delta;
+       }
+       mult = mdev->nominal_c_mult;
+       adj = mult;
+       adj *= delta;
+       diff = div_u64(adj, 1000000000ULL);
+
+       write_lock_irqsave(&mdev->clock_lock, flags);
+       timecounter_read(&mdev->clock);
+       mdev->cycles.mult = neg_adj ? mult - diff : mult + diff;
+       write_unlock_irqrestore(&mdev->clock_lock, flags);
+
+       return 0;
+}
+
+/**
+ * mlx4_en_phc_adjtime - Shift the time of the hardware clock
+ * @ptp: ptp clock structure
+ * @delta: Desired change in nanoseconds
+ *
+ * Adjust the timer by resetting the timecounter structure.
+ **/
+static int mlx4_en_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+       struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev,
+                                               ptp_clock_info);
+       unsigned long flags;
+       s64 now;
+
+       write_lock_irqsave(&mdev->clock_lock, flags);
+       now = timecounter_read(&mdev->clock);
+       now += delta;
+       timecounter_init(&mdev->clock, &mdev->cycles, now);
+       write_unlock_irqrestore(&mdev->clock_lock, flags);
+
+       return 0;
+}
+
+/**
+ * mlx4_en_phc_gettime - Reads the current time from the hardware clock
+ * @ptp: ptp clock structure
+ * @ts: timespec structure to hold the current time value
+ *
+ * Read the timecounter and return the correct value in ns after converting
+ * it into a struct timespec.
+ **/
+static int mlx4_en_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+       struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev,
+                                               ptp_clock_info);
+       unsigned long flags;
+       u32 remainder;
+       u64 ns;
+
+       write_lock_irqsave(&mdev->clock_lock, flags);
+       ns = timecounter_read(&mdev->clock);
+       write_unlock_irqrestore(&mdev->clock_lock, flags);
+
+       ts->tv_sec = div_u64_rem(ns, NSEC_PER_SEC, &remainder);
+       ts->tv_nsec = remainder;
+
+       return 0;
+}
+
+/**
+ * mlx4_en_phc_settime - Set the current time on the hardware clock
+ * @ptp: ptp clock structure
+ * @ts: timespec containing the new time for the cycle counter
+ *
+ * Reset the timecounter to use a new base value instead of the kernel
+ * wall timer value.
+ **/
+static int mlx4_en_phc_settime(struct ptp_clock_info *ptp,
+                              const struct timespec *ts)
+{
+       struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev,
+                                               ptp_clock_info);
+       u64 ns = timespec_to_ns(ts);
+       unsigned long flags;
+
+       /* reset the timecounter */
+       write_lock_irqsave(&mdev->clock_lock, flags);
+       timecounter_init(&mdev->clock, &mdev->cycles, ns);
+       write_unlock_irqrestore(&mdev->clock_lock, flags);
+
+       return 0;
+}
+
+/**
+ * mlx4_en_phc_enable - enable or disable an ancillary feature
+ * @ptp: ptp clock structure
+ * @request: Desired resource to enable or disable
+ * @on: Caller passes one to enable or zero to disable
+ *
+ * Enable (or disable) ancillary features of the PHC subsystem.
+ * Currently, no ancillary features are supported.
+ **/
+static int mlx4_en_phc_enable(struct ptp_clock_info __always_unused *ptp,
+                             struct ptp_clock_request __always_unused *request,
+                             int __always_unused on)
+{
+       return -EOPNOTSUPP;
+}
+
+static const struct ptp_clock_info mlx4_en_ptp_clock_info = {
+       .owner          = THIS_MODULE,
+       .max_adj        = 100000000,
+       .n_alarm        = 0,
+       .n_ext_ts       = 0,
+       .n_per_out      = 0,
+       .pps            = 0,
+       .adjfreq        = mlx4_en_phc_adjfreq,
+       .adjtime        = mlx4_en_phc_adjtime,
+       .gettime        = mlx4_en_phc_gettime,
+       .settime        = mlx4_en_phc_settime,
+       .enable         = mlx4_en_phc_enable,
+};
+
 void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
 {
        struct mlx4_dev *dev = mdev->dev;
+       unsigned long flags;
        u64 ns;
 
+       rwlock_init(&mdev->clock_lock);
+
        memset(&mdev->cycles, 0, sizeof(mdev->cycles));
        mdev->cycles.read = mlx4_en_read_clock;
        mdev->cycles.mask = CLOCKSOURCE_MASK(48);
@@ -127,9 +303,12 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
        mdev->cycles.shift = 14;
        mdev->cycles.mult =
                clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift);
+       mdev->nominal_c_mult = mdev->cycles.mult;
 
+       write_lock_irqsave(&mdev->clock_lock, flags);
        timecounter_init(&mdev->clock, &mdev->cycles,
                         ktime_to_ns(ktime_get_real()));
+       write_unlock_irqrestore(&mdev->clock_lock, flags);
 
        /* Calculate period in seconds to call the overflow watchdog - to make
         * sure counter is checked at least once every wrap around.
@@ -137,15 +316,18 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
        ns = cyclecounter_cyc2ns(&mdev->cycles, mdev->cycles.mask);
        do_div(ns, NSEC_PER_SEC / 2 / HZ);
        mdev->overflow_period = ns;
-}
 
-void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev)
-{
-       bool timeout = time_is_before_jiffies(mdev->last_overflow_check +
-                                             mdev->overflow_period);
+       /* Configure the PHC */
+       mdev->ptp_clock_info = mlx4_en_ptp_clock_info;
+       snprintf(mdev->ptp_clock_info.name, 16, "mlx4 ptp");
 
-       if (timeout) {
-               timecounter_read(&mdev->clock);
-               mdev->last_overflow_check = jiffies;
+       mdev->ptp_clock = ptp_clock_register(&mdev->ptp_clock_info,
+                                            &mdev->pdev->dev);
+       if (IS_ERR(mdev->ptp_clock)) {
+               mdev->ptp_clock = NULL;
+               mlx4_err(mdev, "ptp_clock_register failed\n");
+       } else {
+               mlx4_info(mdev, "registered PHC clock\n");
        }
+
 }
index 0596f9f85a0efe120ce9841390ff58a5743cf30e..3e8d33605fe7b17d7cde81092c92f132163abdc2 100644 (file)
@@ -1193,6 +1193,9 @@ static int mlx4_en_get_ts_info(struct net_device *dev,
                info->rx_filters =
                        (1 << HWTSTAMP_FILTER_NONE) |
                        (1 << HWTSTAMP_FILTER_ALL);
+
+               if (mdev->ptp_clock)
+                       info->phc_index = ptp_clock_index(mdev->ptp_clock);
        }
 
        return ret;
index 725a4e1b5f67db07a9c576e051a128aced6e5f2a..d357bf5a46860314a4c74ae10c630bae8f61f096 100644 (file)
@@ -199,6 +199,9 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr)
                if (mdev->pndev[i])
                        mlx4_en_destroy_netdev(mdev->pndev[i]);
 
+       if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
+               mlx4_en_remove_timestamp(mdev);
+
        flush_workqueue(mdev->workqueue);
        destroy_workqueue(mdev->workqueue);
        (void) mlx4_mr_free(dev, &mdev->mr);
index 6f920900e841f91d1d709c4fc0de0350edc2bc42..fad45316200aa0fbcb115e3f6b4ec56a24ca29cd 100644 (file)
@@ -468,6 +468,53 @@ static void mlx4_en_u64_to_mac(unsigned char dst_mac[ETH_ALEN + 2], u64 src_mac)
        memset(&dst_mac[ETH_ALEN], 0, 2);
 }
 
+
+static int mlx4_en_tunnel_steer_add(struct mlx4_en_priv *priv, unsigned char *addr,
+                                   int qpn, u64 *reg_id)
+{
+       int err;
+       struct mlx4_spec_list spec_eth_outer = { {NULL} };
+       struct mlx4_spec_list spec_vxlan     = { {NULL} };
+       struct mlx4_spec_list spec_eth_inner = { {NULL} };
+
+       struct mlx4_net_trans_rule rule = {
+               .queue_mode = MLX4_NET_TRANS_Q_FIFO,
+               .exclusive = 0,
+               .allow_loopback = 1,
+               .promisc_mode = MLX4_FS_REGULAR,
+               .priority = MLX4_DOMAIN_NIC,
+       };
+
+       __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
+
+       if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
+               return 0; /* do nothing */
+
+       rule.port = priv->port;
+       rule.qpn = qpn;
+       INIT_LIST_HEAD(&rule.list);
+
+       spec_eth_outer.id = MLX4_NET_TRANS_RULE_ID_ETH;
+       memcpy(spec_eth_outer.eth.dst_mac, addr, ETH_ALEN);
+       memcpy(spec_eth_outer.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
+
+       spec_vxlan.id = MLX4_NET_TRANS_RULE_ID_VXLAN;    /* any vxlan header */
+       spec_eth_inner.id = MLX4_NET_TRANS_RULE_ID_ETH;  /* any inner eth header */
+
+       list_add_tail(&spec_eth_outer.list, &rule.list);
+       list_add_tail(&spec_vxlan.list,     &rule.list);
+       list_add_tail(&spec_eth_inner.list, &rule.list);
+
+       err = mlx4_flow_attach(priv->mdev->dev, &rule, reg_id);
+       if (err) {
+               en_err(priv, "failed to add vxlan steering rule, err %d\n", err);
+               return err;
+       }
+       en_dbg(DRV, priv, "added vxlan steering rule, mac %pM reg_id %llx\n", addr, *reg_id);
+       return 0;
+}
+
+
 static int mlx4_en_uc_steer_add(struct mlx4_en_priv *priv,
                                unsigned char *mac, int *qpn, u64 *reg_id)
 {
@@ -585,6 +632,11 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
        if (err)
                goto steer_err;
 
+       err = mlx4_en_tunnel_steer_add(priv, priv->dev->dev_addr, *qpn,
+                                      &priv->tunnel_reg_id);
+       if (err)
+               goto tunnel_err;
+
        entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry) {
                err = -ENOMEM;
@@ -599,6 +651,9 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
        return 0;
 
 alloc_err:
+       if (priv->tunnel_reg_id)
+               mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
+tunnel_err:
        mlx4_en_uc_steer_release(priv, priv->dev->dev_addr, *qpn, reg_id);
 
 steer_err:
@@ -642,6 +697,11 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
                        }
                }
 
+               if (priv->tunnel_reg_id) {
+                       mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
+                       priv->tunnel_reg_id = 0;
+               }
+
                en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
                       priv->port, qpn);
                mlx4_qp_release_range(dev, qpn, 1);
@@ -782,7 +842,7 @@ static void update_mclist_flags(struct mlx4_en_priv *priv,
        list_for_each_entry(dst_tmp, dst, list) {
                found = false;
                list_for_each_entry(src_tmp, src, list) {
-                       if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
+                       if (ether_addr_equal(dst_tmp->addr, src_tmp->addr)) {
                                found = true;
                                break;
                        }
@@ -797,7 +857,7 @@ static void update_mclist_flags(struct mlx4_en_priv *priv,
        list_for_each_entry(src_tmp, src, list) {
                found = false;
                list_for_each_entry(dst_tmp, dst, list) {
-                       if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
+                       if (ether_addr_equal(dst_tmp->addr, src_tmp->addr)) {
                                dst_tmp->action = MCLIST_NONE;
                                found = true;
                                break;
@@ -1044,6 +1104,12 @@ static void mlx4_en_do_multicast(struct mlx4_en_priv *priv,
                                if (err)
                                        en_err(priv, "Fail to detach multicast address\n");
 
+                               if (mclist->tunnel_reg_id) {
+                                       err = mlx4_flow_detach(priv->mdev->dev, mclist->tunnel_reg_id);
+                                       if (err)
+                                               en_err(priv, "Failed to detach multicast address\n");
+                               }
+
                                /* remove from list */
                                list_del(&mclist->list);
                                kfree(mclist);
@@ -1061,6 +1127,10 @@ static void mlx4_en_do_multicast(struct mlx4_en_priv *priv,
                                if (err)
                                        en_err(priv, "Fail to attach multicast address\n");
 
+                               err = mlx4_en_tunnel_steer_add(priv, &mc_list[10], priv->base_qpn,
+                                                              &mclist->tunnel_reg_id);
+                               if (err)
+                                       en_err(priv, "Failed to attach multicast address\n");
                        }
                }
        }
@@ -1598,6 +1668,15 @@ int mlx4_en_start_port(struct net_device *dev)
                goto tx_err;
        }
 
+       if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
+               err = mlx4_SET_PORT_VXLAN(mdev->dev, priv->port, VXLAN_STEER_BY_OUTER_MAC);
+               if (err) {
+                       en_err(priv, "Failed setting port L2 tunnel configuration, err %d\n",
+                              err);
+                       goto tx_err;
+               }
+       }
+
        /* Init port */
        en_dbg(HW, priv, "Initializing port\n");
        err = mlx4_INIT_PORT(mdev->dev, priv->port);
@@ -2400,6 +2479,13 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
                dev->priv_flags |= IFF_UNICAST_FLT;
 
+       if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
+               dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+                                       NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL;
+               dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+               dev->features    |= NETIF_F_GSO_UDP_TUNNEL;
+       }
+
        mdev->pndev[port] = dev;
 
        netif_carrier_off(dev);
@@ -2429,6 +2515,15 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
                goto out;
        }
 
+       if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
+               err = mlx4_SET_PORT_VXLAN(mdev->dev, priv->port, VXLAN_STEER_BY_OUTER_MAC);
+               if (err) {
+                       en_err(priv, "Failed setting port L2 tunnel configuration, err %d\n",
+                              err);
+                       goto out;
+               }
+       }
+
        /* Init port */
        en_warn(priv, "Initializing port\n");
        err = mlx4_INIT_PORT(mdev->dev, priv->port);
index d3f508697a3dd664f65a687c81964f30fee04a93..f1a5500ff72de1ee07d7d8bfd2dc91e02e2d6388 100644 (file)
@@ -68,6 +68,12 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
        context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
        if (!(dev->features & NETIF_F_HW_VLAN_CTAG_RX))
                context->param3 |= cpu_to_be32(1 << 30);
+
+       if (!is_tx && !rss &&
+           (mdev->dev->caps.tunnel_offload_mode ==  MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)) {
+               en_dbg(HW, priv, "Setting RX qp %x tunnel mode to RX tunneled & non-tunneled\n", qpn);
+               context->srqn = cpu_to_be32(7 << 28); /* this fills bits 30:28 */
+       }
 }
 
 
index 2aa0ae1ea45ad47078c5c88f7e3f1eab92ecb962..890922c1c8eea11d4d737d81aefffde4e157e3a2 100644 (file)
@@ -631,6 +631,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
        int ip_summed;
        int factor = priv->cqe_factor;
        u64 timestamp;
+       bool l2_tunnel;
 
        if (!priv->port_up)
                return 0;
@@ -709,6 +710,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                length -= ring->fcs_del;
                ring->bytes += length;
                ring->packets++;
+               l2_tunnel = (dev->hw_enc_features & NETIF_F_RXCSUM) &&
+                       (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_L2_TUNNEL));
 
                if (likely(dev->features & NETIF_F_RXCSUM)) {
                        if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
@@ -721,7 +724,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                                 * - not an IP fragment
                                 * - no LLS polling in progress
                                 */
-                               if (!mlx4_en_cq_ll_polling(cq) &&
+                               if (!mlx4_en_cq_busy_polling(cq) &&
                                    (dev->features & NETIF_F_GRO)) {
                                        struct sk_buff *gro_skb = napi_get_frags(&cq->napi);
                                        if (!gro_skb)
@@ -738,6 +741,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                                        gro_skb->data_len = length;
                                        gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
 
+                                       if (l2_tunnel)
+                                               gro_skb->encapsulation = 1;
                                        if ((cqe->vlan_my_qpn &
                                            cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) &&
                                            (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
@@ -790,6 +795,9 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                skb->protocol = eth_type_trans(skb, dev);
                skb_record_rx_queue(skb, cq->ring);
 
+               if (l2_tunnel)
+                       skb->encapsulation = 1;
+
                if (dev->features & NETIF_F_RXHASH)
                        skb_set_hash(skb,
                                     be32_to_cpu(cqe->immed_rss_invalid),
@@ -808,8 +816,10 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 
                skb_mark_napi_id(skb, &cq->napi);
 
-               /* Push it up the stack */
-               netif_receive_skb(skb);
+               if (!mlx4_en_cq_busy_polling(cq))
+                       napi_gro_receive(&cq->napi, skb);
+               else
+                       netif_receive_skb(skb);
 
 next:
                for (nr = 0; nr < priv->num_frags; nr++)
@@ -1057,6 +1067,12 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
                rss_mask |=  MLX4_RSS_UDP_IPV4 | MLX4_RSS_UDP_IPV6;
                rss_context->base_qpn_udp = rss_context->default_qpn;
        }
+
+       if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
+               en_info(priv, "Setting RSS context tunnel type to RSS on inner headers\n");
+               rss_mask |= MLX4_RSS_BY_INNER_HEADERS;
+       }
+
        rss_context->flags = rss_mask;
        rss_context->hash_fn = MLX4_RSS_HASH_TOP;
        for (i = 0; i < 10; i++)
index e3adcebfdfb8f1c20519fe8f66581d36782b6b2f..160e86d216074193865c5fdcacf6e3389b92f9e0 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/if_vlan.h>
 #include <linux/vmalloc.h>
 #include <linux/tcp.h>
+#include <linux/ip.h>
 #include <linux/moduleparam.h>
 
 #include "mlx4_en.h"
@@ -560,7 +561,10 @@ static int get_real_size(struct sk_buff *skb, struct net_device *dev,
        int real_size;
 
        if (skb_is_gso(skb)) {
-               *lso_header_size = skb_transport_offset(skb) + tcp_hdrlen(skb);
+               if (skb->encapsulation)
+                       *lso_header_size = (skb_inner_transport_header(skb) - skb->data) + inner_tcp_hdrlen(skb);
+               else
+                       *lso_header_size = skb_transport_offset(skb) + tcp_hdrlen(skb);
                real_size = CTRL_SIZE + skb_shinfo(skb)->nr_frags * DS_SIZE +
                        ALIGN(*lso_header_size + 4, DS_SIZE);
                if (unlikely(*lso_header_size != skb_headlen(skb))) {
@@ -859,6 +863,14 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
                tx_info->inl = 1;
        }
 
+       if (skb->encapsulation) {
+               struct iphdr *ipv4 = (struct iphdr *)skb_inner_network_header(skb);
+               if (ipv4->protocol == IPPROTO_TCP || ipv4->protocol == IPPROTO_UDP)
+                       op_own |= cpu_to_be32(MLX4_WQE_CTRL_IIP | MLX4_WQE_CTRL_ILP);
+               else
+                       op_own |= cpu_to_be32(MLX4_WQE_CTRL_IIP);
+       }
+
        ring->prod += nr_txbb;
 
        /* If we used a bounce buffer then copy descriptor back into place */
index 27a84342525fc712cfcac525beb5e59155cb7dd0..55c4ea7402586f8f2b3124f570ca6bd4246046bd 100644 (file)
@@ -134,7 +134,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
                [5] = "Time stamping support",
                [6] = "VST (control vlan insertion/stripping) support",
                [7] = "FSM (MAC anti-spoofing) support",
-               [8] = "Dynamic QP updates support"
+               [8] = "Dynamic QP updates support",
+               [9] = "TCP/IP offloads/flow-steering for VXLAN support"
        };
        int i;
 
@@ -536,6 +537,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET         0x98
 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET                0xa0
 #define QUERY_DEV_CAP_FW_REASSIGN_MAC          0x9d
+#define QUERY_DEV_CAP_VXLAN                    0x9e
 
        dev_cap->flags2 = 0;
        mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -701,6 +703,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
        MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC);
        if (field & 1<<6)
                dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_REASSIGN_MAC_EN;
+       MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN);
+       if (field & 1<<3)
+               dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS;
        MLX4_GET(dev_cap->max_icm_sz, outbox,
                 QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
        if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
@@ -849,6 +854,11 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
        field &= 0x7f;
        MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
 
+       /* For guests, disable vxlan tunneling */
+       MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN);
+       field &= 0xf7;
+       MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VXLAN);
+
        /* For guests, report Blueflame disabled */
        MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
        field &= 0x7f;
@@ -1274,6 +1284,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
 #define INIT_HCA_IN_SIZE                0x200
 #define INIT_HCA_VERSION_OFFSET                 0x000
 #define         INIT_HCA_VERSION                2
+#define INIT_HCA_VXLAN_OFFSET           0x0c
 #define INIT_HCA_CACHELINE_SZ_OFFSET    0x0e
 #define INIT_HCA_FLAGS_OFFSET           0x014
 #define INIT_HCA_QPC_OFFSET             0x020
@@ -1432,6 +1443,12 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
        MLX4_PUT(inbox, param->uar_page_sz,     INIT_HCA_UAR_PAGE_SZ_OFFSET);
        MLX4_PUT(inbox, param->log_uar_sz,      INIT_HCA_LOG_UAR_SZ_OFFSET);
 
+       /* set parser VXLAN attributes */
+       if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS) {
+               u8 parser_params = 0;
+               MLX4_PUT(inbox, parser_params,  INIT_HCA_VXLAN_OFFSET);
+       }
+
        err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 10000,
                       MLX4_CMD_NATIVE);
 
index fbebfb0a64362516b44a03f9bc677f3271aa578c..d711158b0d4b1ab59bb3d1cf8973e8d4936ce853 100644 (file)
@@ -388,6 +388,84 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 
        return 0;
 }
+
+static int mlx4_get_pcie_dev_link_caps(struct mlx4_dev *dev,
+                                      enum pci_bus_speed *speed,
+                                      enum pcie_link_width *width)
+{
+       u32 lnkcap1, lnkcap2;
+       int err1, err2;
+
+#define  PCIE_MLW_CAP_SHIFT 4  /* start of MLW mask in link capabilities */
+
+       *speed = PCI_SPEED_UNKNOWN;
+       *width = PCIE_LNK_WIDTH_UNKNOWN;
+
+       err1 = pcie_capability_read_dword(dev->pdev, PCI_EXP_LNKCAP, &lnkcap1);
+       err2 = pcie_capability_read_dword(dev->pdev, PCI_EXP_LNKCAP2, &lnkcap2);
+       if (!err2 && lnkcap2) { /* PCIe r3.0-compliant */
+               if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
+                       *speed = PCIE_SPEED_8_0GT;
+               else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
+                       *speed = PCIE_SPEED_5_0GT;
+               else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB)
+                       *speed = PCIE_SPEED_2_5GT;
+       }
+       if (!err1) {
+               *width = (lnkcap1 & PCI_EXP_LNKCAP_MLW) >> PCIE_MLW_CAP_SHIFT;
+               if (!lnkcap2) { /* pre-r3.0 */
+                       if (lnkcap1 & PCI_EXP_LNKCAP_SLS_5_0GB)
+                               *speed = PCIE_SPEED_5_0GT;
+                       else if (lnkcap1 & PCI_EXP_LNKCAP_SLS_2_5GB)
+                               *speed = PCIE_SPEED_2_5GT;
+               }
+       }
+
+       if (*speed == PCI_SPEED_UNKNOWN || *width == PCIE_LNK_WIDTH_UNKNOWN) {
+               return err1 ? err1 :
+                       err2 ? err2 : -EINVAL;
+       }
+       return 0;
+}
+
+static void mlx4_check_pcie_caps(struct mlx4_dev *dev)
+{
+       enum pcie_link_width width, width_cap;
+       enum pci_bus_speed speed, speed_cap;
+       int err;
+
+#define PCIE_SPEED_STR(speed) \
+       (speed == PCIE_SPEED_8_0GT ? "8.0GT/s" : \
+        speed == PCIE_SPEED_5_0GT ? "5.0GT/s" : \
+        speed == PCIE_SPEED_2_5GT ? "2.5GT/s" : \
+        "Unknown")
+
+       err = mlx4_get_pcie_dev_link_caps(dev, &speed_cap, &width_cap);
+       if (err) {
+               mlx4_warn(dev,
+                         "Unable to determine PCIe device BW capabilities\n");
+               return;
+       }
+
+       err = pcie_get_minimum_link(dev->pdev, &speed, &width);
+       if (err || speed == PCI_SPEED_UNKNOWN ||
+           width == PCIE_LNK_WIDTH_UNKNOWN) {
+               mlx4_warn(dev,
+                         "Unable to determine PCI device chain minimum BW\n");
+               return;
+       }
+
+       if (width != width_cap || speed != speed_cap)
+               mlx4_warn(dev,
+                         "PCIe BW is different than device's capability\n");
+
+       mlx4_info(dev, "PCIe link speed is %s, device supports %s\n",
+                 PCIE_SPEED_STR(speed), PCIE_SPEED_STR(speed_cap));
+       mlx4_info(dev, "PCIe link width is x%d, device supports x%d\n",
+                 width, width_cap);
+       return;
+}
+
 /*The function checks if there are live vf, return the num of them*/
 static int mlx4_how_many_lives_vf(struct mlx4_dev *dev)
 {
@@ -1444,6 +1522,19 @@ static void choose_steering_mode(struct mlx4_dev *dev,
                 mlx4_log_num_mgm_entry_size);
 }
 
+static void choose_tunnel_offload_mode(struct mlx4_dev *dev,
+                                      struct mlx4_dev_cap *dev_cap)
+{
+       if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED &&
+           dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS)
+               dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_VXLAN;
+       else
+               dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_NONE;
+
+       mlx4_dbg(dev, "Tunneling offload mode is: %s\n",  (dev->caps.tunnel_offload_mode
+                == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) ? "vxlan" : "none");
+}
+
 static int mlx4_init_hca(struct mlx4_dev *dev)
 {
        struct mlx4_priv          *priv = mlx4_priv(dev);
@@ -1484,6 +1575,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
                }
 
                choose_steering_mode(dev, &dev_cap);
+               choose_tunnel_offload_mode(dev, &dev_cap);
 
                err = mlx4_get_phys_port_id(dev);
                if (err)
@@ -2292,6 +2384,12 @@ slave_start:
                        goto err_mfunc;
        }
 
+       /* check if the device is functioning at its maximum possible speed.
+        * No return code for this call, just warn the user in case of PCI
+        * express device capabilities are under-satisfied by the bus.
+        */
+       mlx4_check_pcie_caps(dev);
+
        /* In master functions, the communication channel must be initialized
         * after obtaining its address from fw */
        if (mlx4_is_master(dev)) {
index 7c83e6ccc9da2f7490971bc3af153780cdb37420..bfe65f7be91c7f46b50c8afc4bd03272112e7ab4 100644 (file)
@@ -697,7 +697,8 @@ const u16 __sw_id_hw[] = {
        [MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003,
        [MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002,
        [MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004,
-       [MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006
+       [MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006,
+       [MLX4_NET_TRANS_RULE_ID_VXLAN]   = 0xE008
 };
 
 int mlx4_map_sw_to_hw_steering_id(struct mlx4_dev *dev,
@@ -722,7 +723,9 @@ static const int __rule_hw_sz[] = {
        [MLX4_NET_TRANS_RULE_ID_TCP] =
                sizeof(struct mlx4_net_trans_rule_hw_tcp_udp),
        [MLX4_NET_TRANS_RULE_ID_UDP] =
-               sizeof(struct mlx4_net_trans_rule_hw_tcp_udp)
+               sizeof(struct mlx4_net_trans_rule_hw_tcp_udp),
+       [MLX4_NET_TRANS_RULE_ID_VXLAN] =
+               sizeof(struct mlx4_net_trans_rule_hw_vxlan)
 };
 
 int mlx4_hw_rule_sz(struct mlx4_dev *dev,
@@ -787,6 +790,13 @@ static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec,
                rule_hw->tcp_udp.src_port_msk = spec->tcp_udp.src_port_msk;
                break;
 
+       case MLX4_NET_TRANS_RULE_ID_VXLAN:
+               rule_hw->vxlan.vni =
+                       cpu_to_be32(be32_to_cpu(spec->vxlan.vni) << 8);
+               rule_hw->vxlan.vni_mask =
+                       cpu_to_be32(be32_to_cpu(spec->vxlan.vni_mask) << 8);
+               break;
+
        default:
                return -EINVAL;
        }
index 123714cbd35f6bdc126adf96e6004c6c9b163436..fe7bdfebf353e745e3c447b820d5c72c413c06e4 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/dcbnl.h>
 #endif
 #include <linux/cpu_rmap.h>
+#include <linux/ptp_clock_kernel.h>
 
 #include <linux/mlx4/device.h>
 #include <linux/mlx4/qp.h>
@@ -375,10 +376,14 @@ struct mlx4_en_dev {
        u32                     priv_pdn;
        spinlock_t              uar_lock;
        u8                      mac_removed[MLX4_MAX_PORTS + 1];
+       rwlock_t                clock_lock;
+       u32                     nominal_c_mult;
        struct cyclecounter     cycles;
        struct timecounter      clock;
        unsigned long           last_overflow_check;
        unsigned long           overflow_period;
+       struct ptp_clock        *ptp_clock;
+       struct ptp_clock_info   ptp_clock_info;
 };
 
 
@@ -436,6 +441,7 @@ struct mlx4_en_mc_list {
        enum mlx4_en_mclist_act action;
        u8                      addr[ETH_ALEN];
        u64                     reg_id;
+       u64                     tunnel_reg_id;
 };
 
 struct mlx4_en_frag_info {
@@ -567,7 +573,7 @@ struct mlx4_en_priv {
        struct list_head filters;
        struct hlist_head filter_hash[1 << MLX4_EN_FILTER_HASH_SHIFT];
 #endif
-
+       u64 tunnel_reg_id;
 };
 
 enum mlx4_en_wol {
@@ -655,7 +661,7 @@ static inline bool mlx4_en_cq_unlock_poll(struct mlx4_en_cq *cq)
 }
 
 /* true if a socket is polling, even if it did not get the lock */
-static inline bool mlx4_en_cq_ll_polling(struct mlx4_en_cq *cq)
+static inline bool mlx4_en_cq_busy_polling(struct mlx4_en_cq *cq)
 {
        WARN_ON(!(cq->state & MLX4_CQ_LOCKED));
        return cq->state & CQ_USER_PEND;
@@ -685,7 +691,7 @@ static inline bool mlx4_en_cq_unlock_poll(struct mlx4_en_cq *cq)
        return false;
 }
 
-static inline bool mlx4_en_cq_ll_polling(struct mlx4_en_cq *cq)
+static inline bool mlx4_en_cq_busy_polling(struct mlx4_en_cq *cq)
 {
        return false;
 }
@@ -790,6 +796,7 @@ void mlx4_en_fill_hwtstamps(struct mlx4_en_dev *mdev,
                            struct skb_shared_hwtstamps *hwts,
                            u64 timestamp);
 void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev);
+void mlx4_en_remove_timestamp(struct mlx4_en_dev *mdev);
 int mlx4_en_timestamp_config(struct net_device *dev,
                             int tx_type,
                             int rx_filter);
index 97d342fa5032e0ed1a90207bea0a01d2fc203b5c..93f75ec78c8224b36822103aafb4f15c437119e3 100644 (file)
@@ -800,6 +800,47 @@ int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
 }
 EXPORT_SYMBOL(mlx4_SET_PORT_SCHEDULER);
 
+enum {
+       VXLAN_ENABLE_MODIFY     = 1 << 7,
+       VXLAN_STEERING_MODIFY   = 1 << 6,
+
+       VXLAN_ENABLE            = 1 << 7,
+};
+
+struct mlx4_set_port_vxlan_context {
+       u32     reserved1;
+       u8      modify_flags;
+       u8      reserved2;
+       u8      enable_flags;
+       u8      steering;
+};
+
+int mlx4_SET_PORT_VXLAN(struct mlx4_dev *dev, u8 port, u8 steering)
+{
+       int err;
+       u32 in_mod;
+       struct mlx4_cmd_mailbox *mailbox;
+       struct mlx4_set_port_vxlan_context  *context;
+
+       mailbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(mailbox))
+               return PTR_ERR(mailbox);
+       context = mailbox->buf;
+       memset(context, 0, sizeof(*context));
+
+       context->modify_flags = VXLAN_ENABLE_MODIFY | VXLAN_STEERING_MODIFY;
+       context->enable_flags = VXLAN_ENABLE;
+       context->steering  = steering;
+
+       in_mod = MLX4_SET_PORT_VXLAN << 8 | port;
+       err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+                      MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+
+       mlx4_free_cmd_mailbox(dev, mailbox);
+       return err;
+}
+EXPORT_SYMBOL(mlx4_SET_PORT_VXLAN);
+
 int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave,
                                struct mlx4_vhcr *vhcr,
                                struct mlx4_cmd_mailbox *inbox,
index 2f3f2bc7f2837e2d7eef7c42ced3a2ffad8f0e56..2e3232cad0ae27573d7679936933492206939c49 100644 (file)
@@ -3634,7 +3634,7 @@ static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header,
            !is_broadcast_ether_addr(eth_header->eth.dst_mac)) {
                list_for_each_entry_safe(res, tmp, rlist, list) {
                        be_mac = cpu_to_be64(res->mac << 16);
-                       if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN))
+                       if (ether_addr_equal((u8 *)&be_mac, eth_header->eth.dst_mac))
                                return 0;
                }
                pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n",
index ddd252a3da9c023794e0bde418d689d87cb4b8c4..8e9dad770900a21658aa6d1454266ea0cf440c80 100644 (file)
@@ -4128,10 +4128,10 @@ static int hw_add_addr(struct ksz_hw *hw, u8 *mac_addr)
        int i;
        int j = ADDITIONAL_ENTRIES;
 
-       if (!memcmp(hw->override_addr, mac_addr, ETH_ALEN))
+       if (ether_addr_equal(hw->override_addr, mac_addr))
                return 0;
        for (i = 0; i < hw->addr_list_size; i++) {
-               if (!memcmp(hw->address[i], mac_addr, ETH_ALEN))
+               if (ether_addr_equal(hw->address[i], mac_addr))
                        return 0;
                if (ADDITIONAL_ENTRIES == j && empty_addr(hw->address[i]))
                        j = i;
@@ -4149,7 +4149,7 @@ static int hw_del_addr(struct ksz_hw *hw, u8 *mac_addr)
        int i;
 
        for (i = 0; i < hw->addr_list_size; i++) {
-               if (!memcmp(hw->address[i], mac_addr, ETH_ALEN)) {
+               if (ether_addr_equal(hw->address[i], mac_addr)) {
                        memset(hw->address[i], 0, ETH_ALEN);
                        writel(0, hw->io + ADD_ADDR_INCR * i +
                                KS_ADD_ADDR_0_HI);
@@ -7104,8 +7104,7 @@ static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id)
                               ETH_ALEN);
                else {
                        memcpy(dev->dev_addr, sw->other_addr, ETH_ALEN);
-                       if (!memcmp(sw->other_addr, hw->override_addr,
-                                   ETH_ALEN))
+                       if (ether_addr_equal(sw->other_addr, hw->override_addr))
                                dev->dev_addr[5] += port->first_port;
                }
 
index 11b1c70df2b80e6963cfe6fddd7831ae3c7be299..6eae2168fff92419dfc3b2148bcdd844df653340 100644 (file)
@@ -1430,7 +1430,7 @@ vxge_search_mac_addr_in_da_table(struct vxge_vpath *vpath, struct macInfo *mac)
                return status;
        }
 
-       while (memcmp(mac->macaddr, macaddr, ETH_ALEN)) {
+       while (!ether_addr_equal(mac->macaddr, macaddr)) {
                status = vxge_hw_vpath_mac_addr_get_next(vpath->handle,
                                macaddr, macmask);
                if (status != VXGE_HW_OK)
index 07a890eb72ad8677a47782f84f79c6f02ee1140e..9a6cb482dcd0b8bf5e26e3e2c784f57b032f5236 100644 (file)
@@ -1053,7 +1053,7 @@ static int yellowfin_rx(struct net_device *dev)
                struct sk_buff *rx_skb = yp->rx_skbuff[entry];
                s16 frame_status;
                u16 desc_status;
-               int data_size;
+               int data_size, yf_size;
                u8 *buf_addr;
 
                if(!desc->result_status)
@@ -1070,6 +1070,9 @@ static int yellowfin_rx(struct net_device *dev)
                               __func__, frame_status);
                if (--boguscnt < 0)
                        break;
+
+               yf_size = sizeof(struct yellowfin_desc);
+
                if ( ! (desc_status & RX_EOP)) {
                        if (data_size != 0)
                                netdev_warn(dev, "Oversized Ethernet frame spanned multiple buffers, status %04x, data_size %d!\n",
@@ -1096,12 +1099,12 @@ static int yellowfin_rx(struct net_device *dev)
                        if (status2 & 0x80) dev->stats.rx_dropped++;
 #ifdef YF_PROTOTYPE            /* Support for prototype hardware errata. */
                } else if ((yp->flags & HasMACAddrBug)  &&
-                       memcmp(le32_to_cpu(yp->rx_ring_dma +
-                               entry*sizeof(struct yellowfin_desc)),
-                               dev->dev_addr, 6) != 0 &&
-                       memcmp(le32_to_cpu(yp->rx_ring_dma +
-                               entry*sizeof(struct yellowfin_desc)),
-                               "\377\377\377\377\377\377", 6) != 0) {
+                       !ether_addr_equal(le32_to_cpu(yp->rx_ring_dma +
+                                                     entry * yf_size),
+                                         dev->dev_addr) &&
+                       !ether_addr_equal(le32_to_cpu(yp->rx_ring_dma +
+                                                     entry * yf_size),
+                                         "\377\377\377\377\377\377")) {
                        if (bogus_rx++ == 0)
                                netdev_warn(dev, "Bad frame to %pM\n",
                                            buf_addr);
index b72b6bea326eaac359fe38f2ce3cc516424e7484..db4280ce9c09a9018401bd05b9193d5e7efee392 100644 (file)
@@ -661,7 +661,7 @@ static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
        list_for_each(head, del_list) {
                cur = list_entry(head, nx_mac_list_t, list);
 
-               if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+               if (ether_addr_equal(addr, cur->mac_addr)) {
                        list_move_tail(head, &adapter->mac_list);
                        return 0;
                }
index 3010abb55fbdb22173930b36d896ad10934dc357..32058614151ae8c498887da42278521e4f8bed3b 100644 (file)
@@ -1602,13 +1602,13 @@ netxen_process_lro(struct netxen_adapter *adapter,
        u32 seq_number;
        u8 vhdr_len = 0;
 
-       if (unlikely(ring > adapter->max_rds_rings))
+       if (unlikely(ring >= adapter->max_rds_rings))
                return NULL;
 
        rds_ring = &recv_ctx->rds_rings[ring];
 
        index = netxen_get_lro_sts_refhandle(sts_data0);
-       if (unlikely(index > rds_ring->num_desc))
+       if (unlikely(index >= rds_ring->num_desc))
                return NULL;
 
        buffer = &rds_ring->rx_buf_arr[index];
index 4afdef0cc1755b57f534142b1ba240ac0f065f51..25e1492ad5287a034c90e0bc17768ad4163452d7 100644 (file)
@@ -38,8 +38,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 3
-#define _QLCNIC_LINUX_SUBVERSION 53
-#define QLCNIC_LINUX_VERSIONID  "5.3.53"
+#define _QLCNIC_LINUX_SUBVERSION 54
+#define QLCNIC_LINUX_VERSIONID  "5.3.54"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
                 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -493,6 +493,7 @@ struct qlcnic_hardware_context {
        struct qlcnic_mailbox *mailbox;
        u8 extend_lb_time;
        u8 phys_port_id[ETH_ALEN];
+       u8 lb_mode;
 };
 
 struct qlcnic_adapter_stats {
@@ -584,6 +585,8 @@ struct qlcnic_host_tx_ring {
        dma_addr_t phys_addr;
        dma_addr_t hw_cons_phys_addr;
        struct netdev_queue *txq;
+       /* Lock to protect Tx descriptors cleanup */
+       spinlock_t tx_clean_lock;
 } ____cacheline_internodealigned_in_smp;
 
 /*
@@ -815,6 +818,7 @@ struct qlcnic_mac_vlan_list {
 
 #define QLCNIC_ILB_MODE                0x1
 #define QLCNIC_ELB_MODE                0x2
+#define QLCNIC_LB_MODE_MASK    0x3
 
 #define QLCNIC_LINKEVENT       0x1
 #define QLCNIC_LB_RESPONSE     0x2
@@ -966,6 +970,9 @@ struct qlcnic_ipaddr {
 #define QLCNIC_BEACON_EANBLE           0xC
 #define QLCNIC_BEACON_DISABLE          0xD
 
+#define QLCNIC_BEACON_ON               2
+#define QLCNIC_BEACON_OFF              0
+
 #define QLCNIC_MSIX_TBL_SPACE          8192
 #define QLCNIC_PCI_REG_MSIX_TBL        0x44
 #define QLCNIC_MSIX_TBL_PGSIZE         4096
@@ -1075,6 +1082,7 @@ struct qlcnic_adapter {
        u64 dev_rst_time;
        bool drv_mac_learn;
        bool fdb_mac_learn;
+       u8 rx_mac_learn;
        unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
        u8 flash_mfg_id;
        struct qlcnic_npar_info *npars;
@@ -1100,7 +1108,6 @@ struct qlcnic_adapter {
        struct qlcnic_filter_hash rx_fhash;
        struct list_head vf_mc_list;
 
-       spinlock_t tx_clean_lock;
        spinlock_t mac_learn_lock;
        /* spinlock for catching rcv filters for eswitch traffic */
        spinlock_t rx_mac_learn_lock;
@@ -1264,7 +1271,7 @@ struct qlcnic_pci_func_cfg {
        u16     port_num;
        u8      pci_func;
        u8      func_state;
-       u8      def_mac_addr[6];
+       u8      def_mac_addr[ETH_ALEN];
 };
 
 struct qlcnic_npar_func_cfg {
@@ -1637,7 +1644,6 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *);
 int qlcnic_reset_npar_config(struct qlcnic_adapter *);
 int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *);
 void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16);
-int qlcnic_get_beacon_state(struct qlcnic_adapter *, u8 *);
 int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
 int qlcnic_read_mac_addr(struct qlcnic_adapter *);
 int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
@@ -1764,6 +1770,7 @@ struct qlcnic_hardware_ops {
                                               pci_channel_state_t);
        pci_ers_result_t (*io_slot_reset) (struct pci_dev *);
        void (*io_resume) (struct pci_dev *);
+       void (*get_beacon_state)(struct qlcnic_adapter *);
 };
 
 extern struct qlcnic_nic_template qlcnic_vf_ops;
@@ -1990,6 +1997,11 @@ static inline void qlcnic_set_mac_filter_count(struct qlcnic_adapter *adapter)
                adapter->ahw->hw_ops->set_mac_filter_count(adapter);
 }
 
+static inline void qlcnic_get_beacon_state(struct qlcnic_adapter *adapter)
+{
+       adapter->ahw->hw_ops->get_beacon_state(adapter);
+}
+
 static inline void qlcnic_read_phys_port_id(struct qlcnic_adapter *adapter)
 {
        if (adapter->ahw->hw_ops->read_phys_port_id)
index b3fd1605773ebcef1e7bdff77c8005538aef2a27..a684d28e37af692b5d0db3e480807b352594cd9a 100644 (file)
@@ -181,7 +181,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
        .io_error_detected              = qlcnic_83xx_io_error_detected,
        .io_slot_reset                  = qlcnic_83xx_io_slot_reset,
        .io_resume                      = qlcnic_83xx_io_resume,
-
+       .get_beacon_state               = qlcnic_83xx_get_beacon_state,
 };
 
 static struct qlcnic_nic_template qlcnic_83xx_ops = {
@@ -1388,6 +1388,33 @@ out:
        netif_device_attach(netdev);
 }
 
+void qlcnic_83xx_get_beacon_state(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       struct qlcnic_cmd_args cmd;
+       u8 beacon_state;
+       int err = 0;
+
+       err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LED_CONFIG);
+       if (!err) {
+               err = qlcnic_issue_cmd(adapter, &cmd);
+               if (!err) {
+                       beacon_state = cmd.rsp.arg[4];
+                       if (beacon_state == QLCNIC_BEACON_DISABLE)
+                               ahw->beacon_state = QLC_83XX_BEACON_OFF;
+                       else if (beacon_state == QLC_83XX_ENABLE_BEACON)
+                               ahw->beacon_state = QLC_83XX_BEACON_ON;
+               }
+       } else {
+               netdev_err(adapter->netdev, "Get beacon state failed, err=%d\n",
+                          err);
+       }
+
+       qlcnic_free_mbx_args(&cmd);
+
+       return;
+}
+
 int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
                           u32 beacon)
 {
@@ -1591,7 +1618,9 @@ static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,
                                                 u32 *interface_id)
 {
        if (qlcnic_sriov_pf_check(adapter)) {
+               qlcnic_alloc_lb_filters_mem(adapter);
                qlcnic_pf_set_interface_id_promisc(adapter, interface_id);
+               adapter->rx_mac_learn = 1;
        } else {
                if (!qlcnic_sriov_vf_check(adapter))
                        *interface_id = adapter->recv_ctx->context_id << 16;
@@ -1618,6 +1647,10 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
 
        cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
        qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
+
+       if (qlcnic_84xx_check(adapter) && qlcnic_sriov_pf_check(adapter))
+               mode = VPORT_MISS_MODE_ACCEPT_ALL;
+
        cmd->req.arg[1] = mode | temp;
        err = qlcnic_issue_cmd(adapter, cmd);
        if (!err)
@@ -1685,12 +1718,6 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
                }
        } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
 
-       /* Make sure carrier is off and queue is stopped during loopback */
-       if (netif_running(netdev)) {
-               netif_carrier_off(netdev);
-               netif_tx_stop_all_queues(netdev);
-       }
-
        ret = qlcnic_do_lb_test(adapter, mode);
 
        qlcnic_83xx_clear_lb_mode(adapter, mode);
@@ -2122,6 +2149,7 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
        ahw->link_autoneg = MSB(MSW(data[3]));
        ahw->module_type = MSB(LSW(data[3]));
        ahw->has_link_events = 1;
+       ahw->lb_mode = data[4] & QLCNIC_LB_MODE_MASK;
        qlcnic_advert_link_change(adapter, link_status);
 }
 
index 34d291168b79d4c0723933d84a7d7f1dc002f7ce..4643b159df867b08603d6ec2c6545f44736cd84f 100644 (file)
@@ -381,6 +381,8 @@ enum qlcnic_83xx_states {
 
 /* LED configuration settings */
 #define QLC_83XX_ENABLE_BEACON         0xe
+#define QLC_83XX_BEACON_ON             1
+#define QLC_83XX_BEACON_OFF            0
 #define QLC_83XX_LED_RATE              0xff
 #define QLC_83XX_LED_ACT               (1 << 10)
 #define QLC_83XX_LED_MOD               (0 << 13)
@@ -559,6 +561,7 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *);
 void qlcnic_83xx_napi_enable(struct qlcnic_adapter *);
 void qlcnic_83xx_napi_disable(struct qlcnic_adapter *);
 int qlcnic_83xx_config_led(struct qlcnic_adapter *, u32, u32);
+void qlcnic_83xx_get_beacon_state(struct qlcnic_adapter *);
 void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32);
 int qlcnic_ind_rd(struct qlcnic_adapter *, u32);
 int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *);
index 22ae884728b81eb27aabb8ca9d73c90a2f4e10ae..abe3924c61c5e265964104cfd1267111b9e096d3 100644 (file)
@@ -2214,6 +2214,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        int err = 0;
 
+       adapter->rx_mac_learn = 0;
        ahw->msix_supported = !!qlcnic_use_msi_x;
 
        qlcnic_83xx_init_rings(adapter);
index 474320a5f0c15aeac1956b6d528cbc5c5a2f0566..23c4fd10e505a3f877b77aa105cc488aa7634a6f 100644 (file)
@@ -224,10 +224,14 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
                return -EIO;
        }
 
-       if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
+       if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) {
                adapter->flags |= QLCNIC_ESWITCH_ENABLED;
-       else
+               if (adapter->drv_mac_learn)
+                       adapter->rx_mac_learn = 1;
+       } else {
                adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
+               adapter->rx_mac_learn = 0;
+       }
 
        ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
        ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
index 3fe971c59b8c0856a695360c5555aecb77d45115..6ca5e57da3da049b0a6679dbf6de8f29b975e6ac 100644 (file)
@@ -462,7 +462,7 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr)
        /* Delete MAC from the existing list */
        list_for_each(head, &adapter->mac_list) {
                cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
-               if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+               if (ether_addr_equal(addr, cur->mac_addr)) {
                        err = qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
                                                        0, QLCNIC_MAC_DEL);
                        if (err)
@@ -483,7 +483,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
        /* look up if already exists */
        list_for_each(head, &adapter->mac_list) {
                cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
-               if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0 &&
+               if (ether_addr_equal(addr, cur->mac_addr) &&
                    cur->vlan_id == vlan)
                        return 0;
        }
@@ -546,8 +546,11 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
            !adapter->fdb_mac_learn) {
                qlcnic_alloc_lb_filters_mem(adapter);
                adapter->drv_mac_learn = 1;
+               if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+                       adapter->rx_mac_learn = 1;
        } else {
                adapter->drv_mac_learn = 0;
+               adapter->rx_mac_learn = 0;
        }
 
        qlcnic_nic_set_promisc(adapter, mode);
@@ -779,8 +782,8 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
                        "Could not send interrupt coalescing parameters\n");
 }
 
-#define QLCNIC_ENABLE_IPV4_LRO         1
-#define QLCNIC_ENABLE_IPV6_LRO         2
+#define QLCNIC_ENABLE_IPV4_LRO         BIT_0
+#define QLCNIC_ENABLE_IPV6_LRO         (BIT_1 | BIT_9)
 
 int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
 {
@@ -1530,19 +1533,34 @@ int qlcnic_82xx_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
        return rv;
 }
 
-int qlcnic_get_beacon_state(struct qlcnic_adapter *adapter, u8 *h_state)
+void qlcnic_82xx_get_beacon_state(struct qlcnic_adapter *adapter)
 {
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_cmd_args cmd;
-       int err;
+       u8 beacon_state;
+       int err = 0;
 
-       err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LED_STATUS);
-       if (!err) {
-               err = qlcnic_issue_cmd(adapter, &cmd);
-               if (!err)
-                       *h_state = cmd.rsp.arg[1];
+       if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_BEACON) {
+               err = qlcnic_alloc_mbx_args(&cmd, adapter,
+                                           QLCNIC_CMD_GET_LED_STATUS);
+               if (!err) {
+                       err = qlcnic_issue_cmd(adapter, &cmd);
+                       if (err) {
+                               netdev_err(adapter->netdev,
+                                          "Failed to get current beacon state, err=%d\n",
+                                          err);
+                       } else {
+                               beacon_state = cmd.rsp.arg[1];
+                               if (beacon_state == QLCNIC_BEACON_DISABLE)
+                                       ahw->beacon_state = QLCNIC_BEACON_OFF;
+                               else if (beacon_state == QLCNIC_BEACON_EANBLE)
+                                       ahw->beacon_state = QLCNIC_BEACON_ON;
+                       }
+               }
+               qlcnic_free_mbx_args(&cmd);
        }
-       qlcnic_free_mbx_args(&cmd);
-       return err;
+
+       return;
 }
 
 void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter)
index 13303e7d1ed7afaec0c5fd41bd530f435cbb62e9..0e739aed1bc621fd0e702388998325c6aab246c0 100644 (file)
@@ -169,6 +169,7 @@ int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int);
 int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32);
 int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
                         struct net_device *netdev);
+void qlcnic_82xx_get_beacon_state(struct qlcnic_adapter *);
 void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter,
                               u64 *uaddr, u16 vlan_id);
 void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter);
index e9c21e5d0ca95c7cc08df0c5f29cca2f7b473ba4..c4262c23ed7c77b009f6c5cebf233a54ebfd685b 100644 (file)
@@ -134,6 +134,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
        struct qlcnic_skb_frag *buffrag;
        int i, j;
 
+       spin_lock(&tx_ring->tx_clean_lock);
+
        cmd_buf = tx_ring->cmd_buf_arr;
        for (i = 0; i < tx_ring->num_desc; i++) {
                buffrag = cmd_buf->frag_array;
@@ -157,6 +159,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
                }
                cmd_buf++;
        }
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 }
 
 void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
index 0538022779928a538b52c3020f2cf8d09f2a0063..cbe4a30abd7921a1dcde90ec7ed85135b144515f 100644 (file)
@@ -156,9 +156,9 @@ static inline void qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter,
        writel(1, tx_ring->crb_intr_mask);
 }
 
-static inline u8 qlcnic_mac_hash(u64 mac)
+static inline u8 qlcnic_mac_hash(u64 mac, u16 vlan)
 {
-       return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff));
+       return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff) ^ (vlan & 0xff));
 }
 
 static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter,
@@ -202,7 +202,7 @@ static struct qlcnic_filter *qlcnic_find_mac_filter(struct hlist_head *head,
        struct hlist_node *n;
 
        hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
-               if (!memcmp(tmp_fil->faddr, addr, ETH_ALEN) &&
+               if (ether_addr_equal(tmp_fil->faddr, addr) &&
                    tmp_fil->vlan_id == vlan_id)
                        return tmp_fil;
        }
@@ -221,8 +221,11 @@ void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter, struct sk_buff *skb,
        u8 hindex, op;
        int ret;
 
+       if (!qlcnic_sriov_pf_check(adapter) || (vlan_id == 0xffff))
+               vlan_id = 0;
+
        memcpy(&src_addr, phdr->h_source, ETH_ALEN);
-       hindex = qlcnic_mac_hash(src_addr) &
+       hindex = qlcnic_mac_hash(src_addr, vlan_id) &
                 (adapter->fhash.fbucket_size - 1);
 
        if (loopback_pkt) {
@@ -322,31 +325,47 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
                               struct cmd_desc_type0 *first_desc,
                               struct sk_buff *skb)
 {
+       struct vlan_ethhdr *vh = (struct vlan_ethhdr *)(skb->data);
+       struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+       struct net_device *netdev = adapter->netdev;
+       u16 protocol = ntohs(skb->protocol);
        struct qlcnic_filter *fil, *tmp_fil;
-       struct hlist_node *n;
        struct hlist_head *head;
-       struct net_device *netdev = adapter->netdev;
-       struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+       struct hlist_node *n;
        u64 src_addr = 0;
        u16 vlan_id = 0;
-       u8 hindex;
+       u8 hindex, hval;
 
-       if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
-               return;
+       if (!qlcnic_sriov_pf_check(adapter)) {
+               if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
+                       return;
+       } else {
+               if (protocol == ETH_P_8021Q) {
+                       vh = (struct vlan_ethhdr *)skb->data;
+                       vlan_id = ntohs(vh->h_vlan_TCI);
+               } else if (vlan_tx_tag_present(skb)) {
+                       vlan_id = vlan_tx_tag_get(skb);
+               }
+
+               if (ether_addr_equal(phdr->h_source, adapter->mac_addr) &&
+                   !vlan_id)
+                       return;
+       }
 
        if (adapter->fhash.fnum >= adapter->fhash.fmax) {
                adapter->stats.mac_filter_limit_overrun++;
-               netdev_info(netdev, "Can not add more than %d mac addresses\n",
-                           adapter->fhash.fmax);
+               netdev_info(netdev, "Can not add more than %d mac-vlan filters, configured %d\n",
+                           adapter->fhash.fmax, adapter->fhash.fnum);
                return;
        }
 
        memcpy(&src_addr, phdr->h_source, ETH_ALEN);
-       hindex = qlcnic_mac_hash(src_addr) & (adapter->fhash.fbucket_size - 1);
+       hval = qlcnic_mac_hash(src_addr, vlan_id);
+       hindex = hval & (adapter->fhash.fbucket_size - 1);
        head = &(adapter->fhash.fhead[hindex]);
 
        hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
-               if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
+               if (ether_addr_equal(tmp_fil->faddr, &src_addr) &&
                    tmp_fil->vlan_id == vlan_id) {
                        if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
                                qlcnic_change_filter(adapter, &src_addr,
@@ -689,6 +708,10 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
                adapter->ahw->linkup = 0;
                netif_carrier_off(netdev);
        } else if (!adapter->ahw->linkup && linkup) {
+               /* Do not advertise Link up if the port is in loopback mode */
+               if (qlcnic_83xx_check(adapter) && adapter->ahw->lb_mode)
+                       return;
+
                netdev_info(netdev, "NIC Link is up\n");
                adapter->ahw->linkup = 1;
                netif_carrier_on(netdev);
@@ -778,7 +801,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
        struct net_device *netdev = adapter->netdev;
        struct qlcnic_skb_frag *frag;
 
-       if (!spin_trylock(&adapter->tx_clean_lock))
+       if (!spin_trylock(&tx_ring->tx_clean_lock))
                return 1;
 
        sw_consumer = tx_ring->sw_consumer;
@@ -807,8 +830,9 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
                        break;
        }
 
+       tx_ring->sw_consumer = sw_consumer;
+
        if (count && netif_running(netdev)) {
-               tx_ring->sw_consumer = sw_consumer;
                smp_mb();
                if (netif_tx_queue_stopped(tx_ring->txq) &&
                    netif_carrier_ok(netdev)) {
@@ -834,7 +858,8 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
         */
        hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
        done = (sw_consumer == hw_consumer);
-       spin_unlock(&adapter->tx_clean_lock);
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 
        return done;
 }
@@ -1593,7 +1618,8 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
        struct sk_buff *skb;
        struct qlcnic_host_rds_ring *rds_ring;
        int index, length, cksum, is_lb_pkt;
-       u16 vid = 0xffff, t_vid;
+       u16 vid = 0xffff;
+       int err;
 
        if (unlikely(ring >= adapter->max_rds_rings))
                return NULL;
@@ -1611,19 +1637,19 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
        if (!skb)
                return buffer;
 
-       if (adapter->drv_mac_learn &&
-           (adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
-               t_vid = 0;
-               is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
-               qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
-       }
-
        if (length > rds_ring->skb_size)
                skb_put(skb, rds_ring->skb_size);
        else
                skb_put(skb, length);
 
-       if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+       err = qlcnic_check_rx_tagging(adapter, skb, &vid);
+
+       if (adapter->rx_mac_learn) {
+               is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
+               qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
+       }
+
+       if (unlikely(err)) {
                adapter->stats.rxdropped++;
                dev_kfree_skb(skb);
                return buffer;
@@ -1658,7 +1684,8 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
        int l2_hdr_offset, l4_hdr_offset;
        int index, is_lb_pkt;
        u16 lro_length, length, data_offset, gso_size;
-       u16 vid = 0xffff, t_vid;
+       u16 vid = 0xffff;
+       int err;
 
        if (unlikely(ring > adapter->max_rds_rings))
                return NULL;
@@ -1680,12 +1707,6 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
        if (!skb)
                return buffer;
 
-       if (adapter->drv_mac_learn &&
-           (adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
-               t_vid = 0;
-               is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
-               qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
-       }
        if (qlcnic_83xx_is_tstamp(sts_data[1]))
                data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE;
        else
@@ -1694,7 +1715,14 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
        skb_put(skb, lro_length + data_offset);
        skb_pull(skb, l2_hdr_offset);
 
-       if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+       err = qlcnic_check_rx_tagging(adapter, skb, &vid);
+
+       if (adapter->rx_mac_learn) {
+               is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
+               qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
+       }
+
+       if (unlikely(err)) {
                adapter->stats.rxdropped++;
                dev_kfree_skb(skb);
                return buffer;
index bf132c9f916fcce4fd1786e7f815108c13d6e995..a57dfe4ad40e71ea82584d23e7f026fe17fa8001 100644 (file)
@@ -313,7 +313,7 @@ static void qlcnic_delete_adapter_mac(struct qlcnic_adapter *adapter)
 
        list_for_each(head, &adapter->mac_list) {
                cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
-               if (!memcmp(adapter->mac_addr, cur->mac_addr, ETH_ALEN)) {
+               if (ether_addr_equal_unaligned(adapter->mac_addr, cur->mac_addr)) {
                        qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
                                                  0, QLCNIC_MAC_DEL);
                        list_del(&cur->list);
@@ -337,7 +337,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EINVAL;
 
-       if (!memcmp(adapter->mac_addr, addr->sa_data, ETH_ALEN))
+       if (ether_addr_equal_unaligned(adapter->mac_addr, addr->sa_data))
                return 0;
 
        if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
@@ -546,6 +546,7 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
        .io_error_detected              = qlcnic_82xx_io_error_detected,
        .io_slot_reset                  = qlcnic_82xx_io_slot_reset,
        .io_resume                      = qlcnic_82xx_io_resume,
+       .get_beacon_state               = qlcnic_82xx_get_beacon_state,
 };
 
 static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter)
@@ -1757,7 +1758,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
        if (qlcnic_sriov_vf_check(adapter))
                qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
        smp_mb();
-       spin_lock(&adapter->tx_clean_lock);
        netif_carrier_off(netdev);
        adapter->ahw->linkup = 0;
        netif_tx_disable(netdev);
@@ -1778,7 +1778,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
 
        for (ring = 0; ring < adapter->drv_tx_rings; ring++)
                qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]);
-       spin_unlock(&adapter->tx_clean_lock);
 }
 
 /* Usage: During suspend and firmware recovery module */
@@ -2173,6 +2172,7 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
                }
                memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
                tx_ring->cmd_buf_arr = cmd_buf_arr;
+               spin_lock_init(&tx_ring->tx_clean_lock);
        }
 
        if (qlcnic_83xx_check(adapter) ||
@@ -2300,7 +2300,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        rwlock_init(&adapter->ahw->crb_lock);
        mutex_init(&adapter->ahw->mem_lock);
 
-       spin_lock_init(&adapter->tx_clean_lock);
        INIT_LIST_HEAD(&adapter->mac_list);
 
        qlcnic_register_dcb(adapter);
index bf8fca7d874f12b897ac36c159fbdb4905ec8de3..f998fdcd7551b5f9796be5aa7fba4140d8c0bb87 100644 (file)
@@ -277,9 +277,7 @@ static void qlcnic_sriov_vf_cleanup(struct qlcnic_adapter *adapter)
 
 void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
 {
-       struct qlcnic_sriov *sriov = adapter->ahw->sriov;
-
-       if (!sriov)
+       if (!test_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state))
                return;
 
        qlcnic_sriov_free_vlans(adapter);
index 98b621fb12274d3209957527beffd16a951984fc..09acf15c3a564d1482a6e40960c6ef8dafa6f1cc 100644 (file)
@@ -9,9 +9,14 @@
 #include "qlcnic.h"
 #include <linux/types.h>
 
-#define QLCNIC_SRIOV_VF_MAX_MAC 8
+#define QLCNIC_SRIOV_VF_MAX_MAC 7
 #define QLC_VF_MIN_TX_RATE     100
 #define QLC_VF_MAX_TX_RATE     9999
+#define QLC_MAC_OPCODE_MASK    0x7
+#define QLC_MAC_STAR_ADD       6
+#define QLC_MAC_STAR_DEL       7
+#define QLC_VF_FLOOD_BIT       BIT_16
+#define QLC_FLOOD_MODE         0x5
 
 static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *, u8);
 
@@ -81,9 +86,12 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
        if (qlcnic_83xx_pf_check(adapter))
                num_macs = 1;
 
+       info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
+
        if (adapter->ahw->pci_func == func) {
                info->min_tx_bw = 0;
                info->max_tx_bw = MAX_BW;
+
                temp = res->num_rx_ucast_mac_filters - num_macs * num_vfs;
                info->max_rx_ucast_mac_filters = temp;
                temp = res->num_tx_mac_filters - num_macs * num_vfs;
@@ -92,6 +100,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                temp = res->num_rx_mcast_mac_filters - temp;
                info->max_rx_mcast_mac_filters = temp;
 
+               info->max_tx_ques = res->num_tx_queues - sriov->num_vfs;
        } else {
                id = qlcnic_sriov_func_to_index(adapter, func);
                if (id < 0)
@@ -99,10 +108,13 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                vp = sriov->vf_info[id].vp;
                info->min_tx_bw = vp->min_tx_bw;
                info->max_tx_bw = vp->max_tx_bw;
+
                info->max_rx_ucast_mac_filters = num_macs;
                info->max_tx_mac_filters = num_macs;
                temp = num_macs * QLCNIC_SRIOV_VF_MAX_MAC;
                info->max_rx_mcast_mac_filters = temp;
+
+               info->max_tx_ques = QLCNIC_SINGLE_RING;
        }
 
        info->max_rx_ip_addr = res->num_destip / max;
@@ -337,6 +349,28 @@ static int qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter *adapter,
        return err;
 }
 
+/* On configuring VF flood bit, PFD will receive traffic from all VFs */
+static int qlcnic_sriov_pf_cfg_flood(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_cmd_args cmd;
+       int err;
+
+       err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
+       if (err)
+               return err;
+
+       cmd.req.arg[1] = QLC_FLOOD_MODE | QLC_VF_FLOOD_BIT;
+
+       err = qlcnic_issue_cmd(adapter, &cmd);
+       if (err)
+               dev_err(&adapter->pdev->dev,
+                       "Failed to configure VF Flood bit on PF, err=%d\n",
+                       err);
+
+       qlcnic_free_mbx_args(&cmd);
+       return err;
+}
+
 static int qlcnic_sriov_pf_cfg_eswitch(struct qlcnic_adapter *adapter,
                                       u8 func, u8 enable)
 {
@@ -464,6 +498,12 @@ static int qlcnic_sriov_pf_init(struct qlcnic_adapter *adapter)
        if (err)
                return err;
 
+       if (qlcnic_84xx_check(adapter)) {
+               err = qlcnic_sriov_pf_cfg_flood(adapter);
+               if (err)
+                       goto disable_vlan_filtering;
+       }
+
        err = qlcnic_sriov_pf_cfg_eswitch(adapter, func, 1);
        if (err)
                goto disable_vlan_filtering;
@@ -1166,6 +1206,13 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
        struct qlcnic_vport *vp = vf->vp;
        u8 op, new_op;
 
+       if (((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_ADD) ||
+           ((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_DEL)) {
+               netdev_err(adapter->netdev, "MAC + any VLAN filter not allowed from VF %d\n",
+                          vf->pci_func);
+               return -EINVAL;
+       }
+
        if (!(cmd->req.arg[1] & BIT_8))
                return -EINVAL;
 
index b5296672c4476b15abb89d3489011c1112b5d7f0..1c8552f682d604fced1ae0f75b03d7cd4dbef317 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 
 #include "qlcnic.h"
@@ -127,6 +126,8 @@ static int qlcnic_83xx_store_beacon(struct qlcnic_adapter *adapter,
        if (kstrtoul(buf, 2, &h_beacon))
                return -EINVAL;
 
+       qlcnic_get_beacon_state(adapter);
+
        if (ahw->beacon_state == h_beacon)
                return len;
 
@@ -158,7 +159,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        int err, drv_sds_rings = adapter->drv_sds_rings;
        u16 beacon;
-       u8 h_beacon_state, b_state, b_rate;
+       u8 b_state, b_rate;
 
        if (len != sizeof(u16))
                return QL_STATUS_INVALID_PARAM;
@@ -168,18 +169,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
        if (err)
                return err;
 
-       if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_BEACON) {
-               err = qlcnic_get_beacon_state(adapter, &h_beacon_state);
-               if (err) {
-                       netdev_err(adapter->netdev,
-                                  "Failed to get current beacon state\n");
-               } else {
-                       if (h_beacon_state == QLCNIC_BEACON_DISABLE)
-                               ahw->beacon_state = 0;
-                       else if (h_beacon_state == QLCNIC_BEACON_EANBLE)
-                               ahw->beacon_state = 2;
-               }
-       }
+       qlcnic_get_beacon_state(adapter);
 
        if (ahw->beacon_state == b_state)
                return len;
@@ -927,38 +917,35 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
        u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
        struct qlcnic_pci_func_cfg *pci_cfg;
        struct qlcnic_pci_info *pci_info;
-       size_t pci_info_sz, pci_cfg_sz;
+       size_t pci_cfg_sz;
        int i, ret;
 
        pci_cfg_sz = pci_func_count * sizeof(*pci_cfg);
        if (size != pci_cfg_sz)
                return QL_STATUS_INVALID_PARAM;
 
-       pci_info_sz = pci_func_count * sizeof(*pci_info);
-       pci_info = vmalloc(pci_info_sz);
+       pci_info = kcalloc(pci_func_count, sizeof(*pci_info), GFP_KERNEL);
        if (!pci_info)
                return -ENOMEM;
 
-       memset(pci_info, 0, pci_info_sz);
-       memset(buf, 0, pci_cfg_sz);
-       pci_cfg = (struct qlcnic_pci_func_cfg *)buf;
-
        ret = qlcnic_get_pci_info(adapter, pci_info);
        if (ret) {
-               vfree(pci_info);
+               kfree(pci_info);
                return ret;
        }
 
+       pci_cfg = (struct qlcnic_pci_func_cfg *)buf;
        for (i = 0; i < pci_func_count; i++) {
                pci_cfg[i].pci_func = pci_info[i].id;
                pci_cfg[i].func_type = pci_info[i].type;
+               pci_cfg[i].func_state = 0;
                pci_cfg[i].port_num = pci_info[i].default_port;
                pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
                pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
                memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
        }
 
-       vfree(pci_info);
+       kfree(pci_info);
        return size;
 }
 
index 03517478e589495dd763a13eaab31101a9ea0a08..ef332708e5f28d7fcd95710af833572e0069ab4d 100644 (file)
@@ -2248,7 +2248,6 @@ int ql_mb_get_port_cfg(struct ql_adapter *qdev);
 int ql_mb_set_port_cfg(struct ql_adapter *qdev);
 int ql_wait_fifo_empty(struct ql_adapter *qdev);
 void ql_get_dump(struct ql_adapter *qdev, void *buff);
-void ql_gen_reg_dump(struct ql_adapter *qdev, struct ql_reg_dump *mpi_coredump);
 netdev_tx_t ql_lb_send(struct sk_buff *skb, struct net_device *ndev);
 void ql_check_lb_frame(struct ql_adapter *, struct sk_buff *);
 int ql_own_firmware(struct ql_adapter *qdev);
index 6bc5db7039201a1af0a835867e900ed59ab0af13..829be21f97b21dd694c6cad732b06a899be106c8 100644 (file)
@@ -1242,8 +1242,8 @@ static void ql_get_core_dump(struct ql_adapter *qdev)
        ql_queue_fw_error(qdev);
 }
 
-void ql_gen_reg_dump(struct ql_adapter *qdev,
-                       struct ql_reg_dump *mpi_coredump)
+static void ql_gen_reg_dump(struct ql_adapter *qdev,
+                           struct ql_reg_dump *mpi_coredump)
 {
        int i, status;
 
index ca742e1f704e027ba0b4651c98e94fd26148c590..888410737dbdc5270774efb57e3196f35814b901 100644 (file)
@@ -1,5 +1,4 @@
-/*
- *  SuperH Ethernet device driver
+/*  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
  *  Copyright (C) 2008-2013 Renesas Solutions Corp.
@@ -13,9 +12,6 @@
  *  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, write to the Free Software Foundation, Inc.,
- *  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  *
  *  The full GNU General Public License is included in this distribution in
  *  the file called "COPYING".
@@ -646,8 +642,8 @@ static struct sh_eth_cpu_data sh7763_data = {
        .eesipr_value   = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
 
        .tx_check       = EESR_TC1 | EESR_FTC,
-       .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
-                         EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
+       .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
+                         EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE |
                          EESR_ECI,
 
        .apr            = 1,
@@ -732,7 +728,7 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
                cd->ecsipr_value = DEFAULT_ECSIPR_INIT;
 
        if (!cd->fcftr_value)
-               cd->fcftr_value = DEFAULT_FIFO_F_D_RFF | \
+               cd->fcftr_value = DEFAULT_FIFO_F_D_RFF |
                                  DEFAULT_FIFO_F_D_RFD;
 
        if (!cd->fdr_value)
@@ -849,20 +845,17 @@ static inline __u32 edmac_to_cpu(struct sh_eth_private *mdp, u32 x)
        return x;
 }
 
-/*
- * Program the hardware MAC address from dev->dev_addr.
- */
+/* Program the hardware MAC address from dev->dev_addr. */
 static void update_mac_address(struct net_device *ndev)
 {
        sh_eth_write(ndev,
-               (ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
-               (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
+                    (ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
+                    (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
        sh_eth_write(ndev,
-               (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
+                    (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
 }
 
-/*
- * Get MAC address from SuperH MAC address register
+/* Get MAC address from SuperH MAC address register
  *
  * SuperH's Ethernet device doesn't have 'ROM' to MAC address.
  * This driver get MAC address that use by bootloader(U-boot or sh-ipl+g).
@@ -1019,8 +1012,10 @@ static void sh_eth_ring_format(struct net_device *ndev)
        int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
        int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
 
-       mdp->cur_rx = mdp->cur_tx = 0;
-       mdp->dirty_rx = mdp->dirty_tx = 0;
+       mdp->cur_rx = 0;
+       mdp->cur_tx = 0;
+       mdp->dirty_rx = 0;
+       mdp->dirty_tx = 0;
 
        memset(mdp->rx_ring, 0, rx_ringsize);
 
@@ -1033,7 +1028,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
                if (skb == NULL)
                        break;
                dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
-                               DMA_FROM_DEVICE);
+                              DMA_FROM_DEVICE);
                sh_eth_set_receive_align(skb);
 
                /* RX descriptor */
@@ -1081,8 +1076,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
        struct sh_eth_private *mdp = netdev_priv(ndev);
        int rx_ringsize, tx_ringsize, ret = 0;
 
-       /*
-        * +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
+       /* +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
         * card needs room to do 8 byte alignment, +2 so we can reserve
         * the first 2 bytes, and +16 gets room for the status word from the
         * card.
@@ -1257,7 +1251,7 @@ static int sh_eth_txfree(struct net_device *ndev)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        struct sh_eth_txdesc *txdesc;
-       int freeNum = 0;
+       int free_num = 0;
        int entry = 0;
 
        for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
@@ -1271,7 +1265,7 @@ static int sh_eth_txfree(struct net_device *ndev)
                                         txdesc->buffer_length, DMA_TO_DEVICE);
                        dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
                        mdp->tx_skbuff[entry] = NULL;
-                       freeNum++;
+                       free_num++;
                }
                txdesc->status = cpu_to_edmac(mdp, TD_TFP);
                if (entry >= mdp->num_tx_ring - 1)
@@ -1280,7 +1274,7 @@ static int sh_eth_txfree(struct net_device *ndev)
                ndev->stats.tx_packets++;
                ndev->stats.tx_bytes += txdesc->buffer_length;
        }
-       return freeNum;
+       return free_num;
 }
 
 /* Packet receive function */
@@ -1313,8 +1307,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                if (!(desc_status & RDFEND))
                        ndev->stats.rx_length_errors++;
 
-               /*
-                * In case of almost all GETHER/ETHERs, the Receive Frame State
+               /* In case of almost all GETHER/ETHERs, the Receive Frame State
                 * (RFS) bits in the Receive Descriptor 0 are from bit 9 to
                 * bit 0. However, in case of the R8A7740's GETHER, the RFS
                 * bits are from bit 25 to bit 16. So, the driver needs right
@@ -1374,7 +1367,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                        if (skb == NULL)
                                break;  /* Better luck next round. */
                        dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
-                                       DMA_FROM_DEVICE);
+                                      DMA_FROM_DEVICE);
                        sh_eth_set_receive_align(skb);
 
                        skb_checksum_none_assert(skb);
@@ -1392,10 +1385,13 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        /* If we don't need to check status, don't. -KDU */
        if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
                /* fix the values for the next receiving if RDE is set */
-               if (intr_status & EESR_RDE)
-                       mdp->cur_rx = mdp->dirty_rx =
-                               (sh_eth_read(ndev, RDFAR) -
-                                sh_eth_read(ndev, RDLAR)) >> 4;
+               if (intr_status & EESR_RDE) {
+                       u32 count = (sh_eth_read(ndev, RDFAR) -
+                                    sh_eth_read(ndev, RDLAR)) >> 4;
+
+                       mdp->cur_rx = count;
+                       mdp->dirty_rx = count;
+               }
                sh_eth_write(ndev, EDRRR_R, EDRRR);
        }
 
@@ -1438,17 +1434,17 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
                                if (mdp->ether_link_active_low)
                                        link_stat = ~link_stat;
                        }
-                       if (!(link_stat & PHY_ST_LINK))
+                       if (!(link_stat & PHY_ST_LINK)) {
                                sh_eth_rcv_snd_disable(ndev);
-                       else {
+                       else {
                                /* Link Up */
                                sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) &
-                                         ~DMAC_M_ECI, EESIPR);
-                               /*clear int */
+                                                  ~DMAC_M_ECI, EESIPR);
+                               /* clear int */
                                sh_eth_write(ndev, sh_eth_read(ndev, ECSR),
-                                         ECSR);
+                                            ECSR);
                                sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) |
-                                         DMAC_M_ECI, EESIPR);
+                                                  DMAC_M_ECI, EESIPR);
                                /* enable tx and rx */
                                sh_eth_rcv_snd_enable(ndev);
                        }
@@ -1519,9 +1515,9 @@ ignore_link:
                u32 edtrr = sh_eth_read(ndev, EDTRR);
                /* dmesg */
                dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
-                               intr_status, mdp->cur_tx);
+                       intr_status, mdp->cur_tx);
                dev_err(&ndev->dev, "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
-                               mdp->dirty_tx, (u32) ndev->state, edtrr);
+                       mdp->dirty_tx, (u32) ndev->state, edtrr);
                /* dirty buffer free */
                sh_eth_txfree(ndev);
 
@@ -1644,7 +1640,8 @@ static void sh_eth_adjust_link(struct net_device *ndev)
                }
                if (!mdp->link) {
                        sh_eth_write(ndev,
-                               (sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
+                                    sh_eth_read(ndev, ECMR) & ~ECMR_TXF,
+                                    ECMR);
                        new_state = 1;
                        mdp->link = phydev->link;
                        if (mdp->cd->no_psr || mdp->no_ether_link)
@@ -1671,7 +1668,7 @@ static int sh_eth_phy_init(struct net_device *ndev)
        struct phy_device *phydev = NULL;
 
        snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
-               mdp->mii_bus->id , mdp->phy_id);
+                mdp->mii_bus->id, mdp->phy_id);
 
        mdp->link = 0;
        mdp->speed = 0;
@@ -1709,7 +1706,7 @@ static int sh_eth_phy_start(struct net_device *ndev)
 }
 
 static int sh_eth_get_settings(struct net_device *ndev,
-                       struct ethtool_cmd *ecmd)
+                              struct ethtool_cmd *ecmd)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        unsigned long flags;
@@ -1723,7 +1720,7 @@ static int sh_eth_get_settings(struct net_device *ndev,
 }
 
 static int sh_eth_set_settings(struct net_device *ndev,
-               struct ethtool_cmd *ecmd)
+                              struct ethtool_cmd *ecmd)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        unsigned long flags;
@@ -1799,7 +1796,7 @@ static int sh_eth_get_sset_count(struct net_device *netdev, int sset)
 }
 
 static void sh_eth_get_ethtool_stats(struct net_device *ndev,
-                       struct ethtool_stats *stats, u64 *data)
+                                    struct ethtool_stats *stats, u64 *data)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        int i = 0;
@@ -1816,7 +1813,7 @@ static void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
        switch (stringset) {
        case ETH_SS_STATS:
                memcpy(data, *sh_eth_gstrings_stats,
-                                       sizeof(sh_eth_gstrings_stats));
+                      sizeof(sh_eth_gstrings_stats));
                break;
        }
 }
@@ -1951,9 +1948,10 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
 
        netif_stop_queue(ndev);
 
-       if (netif_msg_timer(mdp))
-               dev_err(&ndev->dev, "%s: transmit timed out, status %8.8x,"
-              " resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR));
+       if (netif_msg_timer(mdp)) {
+               dev_err(&ndev->dev, "%s: transmit timed out, status %8.8x, resetting...\n",
+                       ndev->name, (int)sh_eth_read(ndev, EESR));
+       }
 
        /* tx_errors count up */
        ndev->stats.tx_errors++;
@@ -2086,8 +2084,7 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
 }
 
 /* ioctl to device function */
-static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
-                               int cmd)
+static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        struct phy_device *phydev = mdp->phydev;
@@ -2207,7 +2204,7 @@ static int sh_eth_tsu_find_entry(struct net_device *ndev, const u8 *addr)
 
        for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
                sh_eth_tsu_read_entry(reg_offset, c_addr);
-               if (memcmp(addr, c_addr, ETH_ALEN) == 0)
+               if (ether_addr_equal(addr, c_addr))
                        return i;
        }
 
@@ -2342,8 +2339,7 @@ static void sh_eth_set_multicast_list(struct net_device *ndev)
        unsigned long flags;
 
        spin_lock_irqsave(&mdp->lock, flags);
-       /*
-        * Initial condition is MCT = 1, PRM = 0.
+       /* Initial condition is MCT = 1, PRM = 0.
         * Depending on ndev->flags, set PRM or clear MCT
         */
        ecmr_bits = (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) | ECMR_MCT;
@@ -2409,8 +2405,7 @@ static int sh_eth_vlan_rx_add_vid(struct net_device *ndev,
 
        mdp->vlan_num_ids++;
 
-       /*
-        * The controller has one VLAN tag HW filter. So, if the filter is
+       /* The controller has one VLAN tag HW filter. So, if the filter is
         * already enabled, the driver disables it and the filte
         */
        if (mdp->vlan_num_ids > 1) {
@@ -2526,7 +2521,7 @@ static int sh_mdio_init(struct net_device *ndev, int id,
        mdp->mii_bus->name = "sh_mii";
        mdp->mii_bus->parent = &ndev->dev;
        snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
-               mdp->pdev->name, id);
+                mdp->pdev->name, id);
 
        /* PHY IRQ */
        mdp->mii_bus->irq = devm_kzalloc(&ndev->dev,
@@ -2739,7 +2734,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 
        /* print device information */
        pr_info("Base address at 0x%x, %pM, IRQ %d.\n",
-              (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
+               (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
 
        platform_set_drvdata(pdev, ndev);
 
@@ -2777,8 +2772,7 @@ static int sh_eth_drv_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int sh_eth_runtime_nop(struct device *dev)
 {
-       /*
-        * Runtime PM callback shared between ->runtime_suspend()
+       /* Runtime PM callback shared between ->runtime_suspend()
         * and ->runtime_resume(). Simply returns success.
         *
         * This driver re-initializes all registers after
index f32c1692d31017186e0e33aaf408eddf7d16a3fa..0fe35b72a1d0bbf119f084b3b7580109fc930b55 100644 (file)
@@ -1,5 +1,4 @@
-/*
- *  SuperH Ethernet device driver
+/*  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
  *  Copyright (C) 2008-2012 Renesas Solutions Corp.
@@ -12,9 +11,6 @@
  *  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, write to the Free Software Foundation, Inc.,
- *  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  *
  *  The full GNU General Public License is included in this distribution in
  *  the file called "COPYING".
@@ -171,8 +167,7 @@ enum {
 #define SH2_SH3_SKB_RX_ALIGN   2
 #endif
 
-/*
- * Register's bits
+/* Register's bits
  */
 /* EDSR : sh7734, sh7757, sh7763, and r8a7740 only */
 enum EDSR_BIT {
@@ -199,7 +194,7 @@ enum DMAC_T_BIT {
        EDTRR_TRNS_ETHER = 0x01,
 };
 
-/* EDRRR*/
+/* EDRRR */
 enum EDRRR_R_BIT {
        EDRRR_R = 0x01,
 };
@@ -422,8 +417,7 @@ enum TSU_FWSLC_BIT {
 #define TSU_VTAG_ENABLE                0x80000000
 #define TSU_VTAG_VID_MASK      0x00000fff
 
-/*
- * The sh ether Tx buffer descriptors.
+/* The sh ether Tx buffer descriptors.
  * This structure should be 20 bytes.
  */
 struct sh_eth_txdesc {
@@ -437,10 +431,9 @@ struct sh_eth_txdesc {
 #endif
        u32 addr;               /* TD2 */
        u32 pad1;               /* padding data */
-} __attribute__((aligned(2), packed));
+} __aligned(2) __packed;
 
-/*
- * The sh ether Rx buffer descriptors.
+/* The sh ether Rx buffer descriptors.
  * This structure should be 20 bytes.
  */
 struct sh_eth_rxdesc {
@@ -454,7 +447,7 @@ struct sh_eth_rxdesc {
 #endif
        u32 addr;               /* RD2 */
        u32 pad0;               /* padding data */
-} __attribute__((aligned(2), packed));
+} __aligned(2) __packed;
 
 /* This structure is used by each CPU dependency handling. */
 struct sh_eth_cpu_data {
@@ -480,16 +473,16 @@ struct sh_eth_cpu_data {
        unsigned long eesr_err_check;
 
        /* hardware features */
-       unsigned long irq_flags;        /* IRQ configuration flags */
-       unsigned no_psr:1;              /* EtherC DO NOT have PSR */
-       unsigned apr:1;                 /* EtherC have APR */
-       unsigned mpr:1;                 /* EtherC have MPR */
-       unsigned tpauser:1;             /* EtherC have TPAUSER */
-       unsigned bculr:1;               /* EtherC have BCULR */
-       unsigned tsu:1;                 /* EtherC have TSU */
-       unsigned hw_swap:1;             /* E-DMAC have DE bit in EDMR */
-       unsigned rpadir:1;              /* E-DMAC have RPADIR */
-       unsigned no_trimd:1;            /* E-DMAC DO NOT have TRIMD */
+       unsigned long irq_flags; /* IRQ configuration flags */
+       unsigned no_psr:1;      /* EtherC DO NOT have PSR */
+       unsigned apr:1;         /* EtherC have APR */
+       unsigned mpr:1;         /* EtherC have MPR */
+       unsigned tpauser:1;     /* EtherC have TPAUSER */
+       unsigned bculr:1;       /* EtherC have BCULR */
+       unsigned tsu:1;         /* EtherC have TSU */
+       unsigned hw_swap:1;     /* E-DMAC have DE bit in EDMR */
+       unsigned rpadir:1;      /* E-DMAC have RPADIR */
+       unsigned no_trimd:1;    /* E-DMAC DO NOT have TRIMD */
        unsigned no_ade:1;      /* E-DMAC DO NOT have ADE bit in EESR */
        unsigned hw_crc:1;      /* E-DMAC have CSMR */
        unsigned select_mii:1;  /* EtherC have RMII_MII (MII select register) */
@@ -511,14 +504,14 @@ struct sh_eth_private {
        struct sh_eth_txdesc *tx_ring;
        struct sk_buff **rx_skbuff;
        struct sk_buff **tx_skbuff;
-       spinlock_t lock;
-       u32 cur_rx, dirty_rx;   /* Producer/consumer ring indices */
+       spinlock_t lock;                /* Register access lock */
+       u32 cur_rx, dirty_rx;           /* Producer/consumer ring indices */
        u32 cur_tx, dirty_tx;
-       u32 rx_buf_sz;          /* Based on MTU+slack. */
+       u32 rx_buf_sz;                  /* Based on MTU+slack. */
        int edmac_endian;
        struct napi_struct napi;
        /* MII transceiver section. */
-       u32 phy_id;                                     /* PHY ID */
+       u32 phy_id;                     /* PHY ID */
        struct mii_bus *mii_bus;        /* MDIO bus control */
        struct phy_device *phydev;      /* PHY device control */
        int link;
@@ -526,8 +519,8 @@ struct sh_eth_private {
        int msg_enable;
        int speed;
        int duplex;
-       int port;               /* for TSU */
-       int vlan_num_ids;       /* for VLAN tag filter */
+       int port;                       /* for TSU */
+       int vlan_num_ids;               /* for VLAN tag filter */
 
        unsigned no_ether_link:1;
        unsigned ether_link_active_low:1;
index c765718860114f42849faa0d8086e78711c867dc..ced5b13d937f33111d86255395870dec95bf96fc 100644 (file)
@@ -356,7 +356,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
                if (pkt_status & SEEQ_RSTAT_FIG) {
                        /* Packet is OK. */
                        /* We don't want to receive our own packets */
-                       if (memcmp(rd->skb->data + 6, dev->dev_addr, ETH_ALEN)) {
+                       if (!ether_addr_equal(rd->skb->data + 6, dev->dev_addr)) {
                                if (len > rx_copybreak) {
                                        skb = rd->skb;
                                        newskb = netdev_alloc_skb(dev, PKT_BUF_SZ);
index 96f79f7c439546dc1f015dfea3055b5cb0492ae6..a6a9e1ebe30c5eb0d849d8e63db667923fbce62d 100644 (file)
@@ -1894,7 +1894,7 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
        SMC_SELECT_BANK(lp, 1);
        val = SMC_GET_BASE(lp);
        val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
-       if (((unsigned int)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) {
+       if (((unsigned long)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) {
                netdev_warn(dev, "%s: IOADDR %p doesn't match configuration (%x).\n",
                            CARDNAME, ioaddr, val);
        }
index 9d6effe5f699a08a01dc64e047be64e6c898690c..d3b967aff9e006ab771a1218bb643f2756f5076d 100644 (file)
@@ -1540,7 +1540,7 @@ static int smsc9420_resume(struct pci_dev *pdev)
 
        pci_set_master(pdev);
 
-       err = pci_enable_wake(pdev, 0, 0);
+       err = pci_enable_wake(pdev, PCI_D0, 0);
        if (err)
                netif_warn(pd, ifup, pd->dev, "pci_enable_wake failed: %d\n",
                           err);
index 22f89ffdfd95fc3e8ca530808e4d6d0dfdcfeaf2..92be6b3fe547ef700a24044a18cac48b1982459b 100644 (file)
@@ -108,8 +108,6 @@ struct stmmac_priv {
        spinlock_t ptp_lock;
 };
 
-extern int phyaddr;
-
 int stmmac_mdio_unregister(struct net_device *ndev);
 int stmmac_mdio_register(struct net_device *ndev);
 void stmmac_set_ethtool_ops(struct net_device *netdev);
index 8a7a23a84ac5c3b6a7b7d4979e8c5866097895a5..b8e3a4ce24b0469118b55590d93efec228374937 100644 (file)
@@ -64,7 +64,7 @@ static int debug = -1;
 module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)");
 
-int phyaddr = -1;
+static int phyaddr = -1;
 module_param(phyaddr, int, S_IRUGO);
 MODULE_PARM_DESC(phyaddr, "Physical device address");
 
@@ -622,17 +622,15 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
        if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
                return -EOPNOTSUPP;
 
-       if (netif_msg_hw(priv)) {
-               if (priv->dma_cap.time_stamp) {
-                       pr_debug("IEEE 1588-2002 Time Stamp supported\n");
-                       priv->adv_ts = 0;
-               }
-               if (priv->dma_cap.atime_stamp && priv->extend_desc) {
-                       pr_debug
-                           ("IEEE 1588-2008 Advanced Time Stamp supported\n");
-                       priv->adv_ts = 1;
-               }
-       }
+       priv->adv_ts = 0;
+       if (priv->dma_cap.atime_stamp && priv->extend_desc)
+               priv->adv_ts = 1;
+
+       if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
+               pr_debug("IEEE 1588-2002 Time Stamp supported\n");
+
+       if (netif_msg_hw(priv) && priv->adv_ts)
+               pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
 
        priv->hw->ptp = &stmmac_ptp;
        priv->hwts_tx_en = 0;
index 644d80ece067717f3dd296d6ed5f54d9c90a7134..37ba2e0808255659e9e71c0b397aeebc9695fe55 100644 (file)
@@ -26,9 +26,9 @@
 #include <linux/pci.h>
 #include "stmmac.h"
 
-struct plat_stmmacenet_data plat_dat;
-struct stmmac_mdio_bus_data mdio_data;
-struct stmmac_dma_cfg dma_cfg;
+static struct plat_stmmacenet_data plat_dat;
+static struct stmmac_mdio_bus_data mdio_data;
+static struct stmmac_dma_cfg dma_cfg;
 
 static void stmmac_default_data(void)
 {
index b8b0eeed0f92bb68f34e1dac22e1f072faec77ce..7680581ebe12fe58a60de42b419467e3f2f065f7 100644 (file)
@@ -56,7 +56,7 @@ static int stmmac_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
 
        priv->hw->ptp->config_addend(priv->ioaddr, addend);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
@@ -91,7 +91,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
 
        priv->hw->ptp->adjust_systime(priv->ioaddr, sec, nsec, neg_adj);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
index 3df56840a3b9282c7ab308682d448bba6dac53f4..1c24a8f368bd86a25835053de21ee6f96df78adb 100644 (file)
@@ -751,7 +751,7 @@ static struct vnet_mcast_entry *__vnet_mc_find(struct vnet *vp, u8 *addr)
        struct vnet_mcast_entry *m;
 
        for (m = vp->mcast_list; m; m = m->next) {
-               if (!memcmp(m->addr, addr, ETH_ALEN))
+               if (ether_addr_equal(m->addr, addr))
                        return m;
        }
        return NULL;
index 243fffbe18e8a9d9888ede4b16f4af64287c0da5..e8bb77d25d987bc15fbd9b90bc6d307a1ba889e7 100644 (file)
@@ -740,6 +740,8 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
                /* set speed_in input in case RMII mode is used in 100Mbps */
                if (phy->speed == 100)
                        mac_control |= BIT(15);
+               else if (phy->speed == 10)
+                       mac_control |= BIT(18); /* In Band mode */
 
                *link = true;
        } else {
@@ -2126,7 +2128,7 @@ static int cpsw_probe(struct platform_device *pdev)
        while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
                for (i = res->start; i <= res->end; i++) {
                        if (devm_request_irq(&pdev->dev, i, cpsw_interrupt, 0,
-                                            dev_name(priv->dev), priv)) {
+                                            dev_name(&pdev->dev), priv)) {
                                dev_err(priv->dev, "error attaching irq\n");
                                goto clean_ale_ret;
                        }
index 7fa60d6092edf9c4fa1caf641dbe0764ea583e7a..63e981975059677c2715c72971bba04d94b0e5da 100644 (file)
@@ -163,7 +163,7 @@ int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
                if (cpsw_ale_get_vlan_id(ale_entry) != vid)
                        continue;
                cpsw_ale_get_addr(ale_entry, entry_addr);
-               if (memcmp(entry_addr, addr, 6) == 0)
+               if (ether_addr_equal(entry_addr, addr))
                        return idx;
        }
        return -ENOENT;
index 4083ba8839e1f2e73d1a1b872c4e4149a6db419e..f59a6c265331b159521b45e57c5f9ccdbdf98d70 100644 (file)
@@ -9,20 +9,10 @@ config TILE_NET
        select CRC32
        select TILE_GXIO_MPIPE if TILEGX
        select HIGH_RES_TIMERS if TILEGX
+       select PTP_1588_CLOCK if TILEGX
        ---help---
          This is a standard Linux network device driver for the
          on-chip Tilera Gigabit Ethernet and XAUI interfaces.
 
          To compile this driver as a module, choose M here: the module
          will be called tile_net.
-
-config PTP_1588_CLOCK_TILEGX
-        tristate "Tilera TILE-Gx mPIPE as PTP clock"
-        select PTP_1588_CLOCK
-        depends on TILE_NET
-        depends on TILEGX
-        ---help---
-          This driver adds support for using the mPIPE as a PTP
-          clock. This clock is only useful if your PTP programs are
-          getting hardware time stamps on the PTP Ethernet packets
-          using the SO_TIMESTAMPING API.
index 858f9a786b8cf3b27be0bdc51f287e029579d167..570495be77f3a69eff6e9f4daa72c7f0ce658ce7 100644 (file)
@@ -187,10 +187,8 @@ struct tile_net_priv {
        int echannel;
        /* mPIPE instance, 0 or 1. */
        int instance;
-#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
        /* The timestamp config. */
        struct hwtstamp_config stamp_cfg;
-#endif
 };
 
 static struct mpipe_data {
@@ -229,14 +227,12 @@ static struct mpipe_data {
        int first_bucket;
        int num_buckets;
 
-#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
        /* PTP-specific data. */
        struct ptp_clock *ptp_clock;
        struct ptp_clock_info caps;
 
        /* Lock for ptp accessors. */
        struct mutex ptp_lock;
-#endif
 
 } mpipe_data[NR_MPIPE_MAX] = {
        [0 ... (NR_MPIPE_MAX - 1)] {
@@ -451,20 +447,17 @@ static void tile_net_provide_needed_buffers(void)
 static void tile_rx_timestamp(struct tile_net_priv *priv, struct sk_buff *skb,
                              gxio_mpipe_idesc_t *idesc)
 {
-#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
        if (unlikely(priv->stamp_cfg.rx_filter != HWTSTAMP_FILTER_NONE)) {
                struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
                memset(shhwtstamps, 0, sizeof(*shhwtstamps));
                shhwtstamps->hwtstamp = ktime_set(idesc->time_stamp_sec,
                                                  idesc->time_stamp_ns);
        }
-#endif
 }
 
 /* Get TX timestamp, and store it in the skb. */
 static void tile_tx_timestamp(struct sk_buff *skb, int instance)
 {
-#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
        struct skb_shared_info *shtx = skb_shinfo(skb);
        if (unlikely((shtx->tx_flags & SKBTX_HW_TSTAMP) != 0)) {
                struct mpipe_data *md = &mpipe_data[instance];
@@ -477,13 +470,11 @@ static void tile_tx_timestamp(struct sk_buff *skb, int instance)
                shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
                skb_tstamp_tx(skb, &shhwtstamps);
        }
-#endif
 }
 
 /* Use ioctl() to enable or disable TX or RX timestamping. */
 static int tile_hwtstamp_set(struct net_device *dev, struct ifreq *rq)
 {
-#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
        struct hwtstamp_config config;
        struct tile_net_priv *priv = netdev_priv(dev);
 
@@ -529,14 +520,10 @@ static int tile_hwtstamp_set(struct net_device *dev, struct ifreq *rq)
 
        priv->stamp_cfg = config;
        return 0;
-#else
-       return -EOPNOTSUPP;
-#endif
 }
 
 static int tile_hwtstamp_get(struct net_device *dev, struct ifreq *rq)
 {
-#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
        struct tile_net_priv *priv = netdev_priv(dev);
 
        if (copy_to_user(rq->ifr_data, &priv->stamp_cfg,
@@ -544,9 +531,6 @@ static int tile_hwtstamp_get(struct net_device *dev, struct ifreq *rq)
                return -EFAULT;
 
        return 0;
-#else
-       return -EOPNOTSUPP;
-#endif
 }
 
 static inline bool filter_packet(struct net_device *dev, void *buf)
@@ -828,8 +812,6 @@ static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t)
        return HRTIMER_NORESTART;
 }
 
-#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
-
 /* PTP clock operations. */
 
 static int ptp_mpipe_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
@@ -896,12 +878,9 @@ static struct ptp_clock_info ptp_mpipe_caps = {
        .enable         = ptp_mpipe_enable,
 };
 
-#endif /* CONFIG_PTP_1588_CLOCK_TILEGX */
-
 /* Sync mPIPE's timestamp up with Linux system time and register PTP clock. */
 static void register_ptp_clock(struct net_device *dev, struct mpipe_data *md)
 {
-#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
        struct timespec ts;
 
        getnstimeofday(&ts);
@@ -913,16 +892,13 @@ static void register_ptp_clock(struct net_device *dev, struct mpipe_data *md)
        if (IS_ERR(md->ptp_clock))
                netdev_err(dev, "ptp_clock_register failed %ld\n",
                           PTR_ERR(md->ptp_clock));
-#endif
 }
 
 /* Initialize PTP fields in a new device. */
 static void init_ptp_dev(struct tile_net_priv *priv)
 {
-#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
        priv->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
        priv->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
-#endif
 }
 
 /* Helper functions for "tile_net_update()". */
index f7f2ef49c0c1cbbe4756c805797bedb71cc6495f..d899d0072ae050d481b9d4510956bfb6146efac2 100644 (file)
@@ -1739,12 +1739,14 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
                GELIC_CARD_PORT_STATUS_CHANGED;
 
 
-       if (gelic_card_init_chain(card, &card->tx_chain,
-                       card->descr, GELIC_NET_TX_DESCRIPTORS))
+       result = gelic_card_init_chain(card, &card->tx_chain,
+                                      card->descr, GELIC_NET_TX_DESCRIPTORS);
+       if (result)
                goto fail_alloc_tx;
-       if (gelic_card_init_chain(card, &card->rx_chain,
-                                card->descr + GELIC_NET_TX_DESCRIPTORS,
-                                GELIC_NET_RX_DESCRIPTORS))
+       result = gelic_card_init_chain(card, &card->rx_chain,
+                                      card->descr + GELIC_NET_TX_DESCRIPTORS,
+                                      GELIC_NET_RX_DESCRIPTORS);
+       if (result)
                goto fail_alloc_rx;
 
        /* head of chain */
@@ -1754,7 +1756,8 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
                card->rx_top, card->tx_top, sizeof(struct gelic_descr),
                GELIC_NET_RX_DESCRIPTORS);
        /* allocate rx skbs */
-       if (gelic_card_alloc_rx_skbs(card))
+       result = gelic_card_alloc_rx_skbs(card);
+       if (result)
                goto fail_alloc_skbs;
 
        spin_lock_init(&card->tx_lock);
@@ -1772,7 +1775,8 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
        }
 
 #ifdef CONFIG_GELIC_WIRELESS
-       if (gelic_wl_driver_probe(card)) {
+       result = gelic_wl_driver_probe(card);
+       if (result) {
                dev_dbg(&dev->core, "%s: WL init failed\n", __func__);
                goto fail_setup_netdev;
        }
index d918d8a426672c113b64f0608f85c4c973129714..7d3779ae73771e0e9b908a09aa5a7ebe080bb4b4 100644 (file)
@@ -23,6 +23,7 @@
 #include "h/smc.h"
 #include "h/supern_2.h"
 #include <linux/bitrev.h>
+#include <linux/etherdevice.h>
 
 #ifndef        lint
 static const char ID_sccs[] = "@(#)fplustm.c   1.32 99/02/23 (C) SK " ;
@@ -1082,7 +1083,7 @@ static struct s_fpmc* mac_get_mc_table(struct s_smc *smc,
                                slot = tb ;
                        continue ;
                }
-               if (memcmp((char *)&tb->a,(char *)own,6))
+               if (!ether_addr_equal((char *)&tb->a, (char *)own))
                        continue ;
                return tb;
        }
index 1450e33fc250e7e0bb4edf73aa6abc06df1a1855..66e2b19ef709ef9180578a3f300b0d029d06805a 100644 (file)
@@ -662,7 +662,8 @@ static int sixpack_open(struct tty_struct *tty)
        tty->receive_room = 65536;
 
        /* Now we're ready to register. */
-       if (register_netdev(dev))
+       err = register_netdev(dev);
+       if (err)
                goto out_free;
 
        tnc_init(sp);
index f91bf0ddf031a077b89d961ca5cb16c87f8321ac..d50b23cf9ea922e66495c68db0fd3fb830815ec2 100644 (file)
@@ -208,7 +208,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
        eth = eth_hdr(skb);
 
        if (!(bpq->acpt_addr[0] & 0x01) &&
-           memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN))
+           !ether_addr_equal(eth->h_source, bpq->acpt_addr))
                goto drop_unlock;
 
        if (skb_cow(skb, sizeof(struct ethhdr)))
index 3169252613faae400904201fa5ad9f1a7decf1cf..5d78c1d08abd60fcc6bcee5dea5ab178a2a166da 100644 (file)
@@ -571,6 +571,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case HDLCDRVCTL_CALIBRATE:
                if(!capable(CAP_SYS_RAWIO))
                        return -EPERM;
+               if (bi.data.calibrate > INT_MAX / s->par.bitrate)
+                       return -EINVAL;
                s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
                return 0;
 
index 1971411574db1c7ae2dd6549490ab6975e816cd1..61dd2447e1bb4eedb5d8e6b72abcf21e9f273afb 100644 (file)
@@ -1057,6 +1057,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                break;
 
        case SIOCYAMGCFG:
+               memset(&yi, 0, sizeof(yi));
                yi.cfg.mask = 0xffffffff;
                yi.cfg.iobase = yp->iobase;
                yi.cfg.irq = yp->irq;
index f80bd0c90f1e1901adc0cf88754e0b37b70d8773..7756118c2f0aee4c3671f45bc0bd13e15143d607 100644 (file)
@@ -260,9 +260,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
        struct sk_buff *skb;
 
        net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev;
-       if (!net) {
-               netdev_err(net, "got receive callback but net device"
-                       " not initialized yet\n");
+       if (!net || net->reg_state != NETREG_REGISTERED) {
                packet->status = NVSP_STAT_FAIL;
                return 0;
        }
@@ -434,19 +432,11 @@ static int netvsc_probe(struct hv_device *dev,
        SET_ETHTOOL_OPS(net, &ethtool_ops);
        SET_NETDEV_DEV(net, &dev->device);
 
-       ret = register_netdev(net);
-       if (ret != 0) {
-               pr_err("Unable to register netdev.\n");
-               free_netdev(net);
-               goto out;
-       }
-
        /* Notify the netvsc driver of the new device */
        device_info.ring_size = ring_size;
        ret = rndis_filter_device_add(dev, &device_info);
        if (ret != 0) {
                netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
-               unregister_netdev(net);
                free_netdev(net);
                hv_set_drvdata(dev, NULL);
                return ret;
@@ -455,7 +445,13 @@ static int netvsc_probe(struct hv_device *dev,
 
        netif_carrier_on(net);
 
-out:
+       ret = register_netdev(net);
+       if (ret != 0) {
+               pr_err("Unable to register netdev.\n");
+               rndis_filter_device_remove(dev);
+               free_netdev(net);
+       }
+
        return ret;
 }
 
index 2a30193d0d50b5f5a348bc21056ec0cfd2224098..2dc82f1d2e700be81f999d8922348dc05288c580 100644 (file)
@@ -62,8 +62,6 @@ config SIR_BFIN_PIO
        bool "PIO mode"
 endchoice
 
-comment "Dongle support"
-
 config SH_SIR
        tristate "SuperH SIR on UART"
        depends on IRDA && SUPERH && \
@@ -74,6 +72,8 @@ config SH_SIR
          Say Y here if your want to enable SIR function on SuperH UART
          devices.
 
+comment "Dongle support"
+
 config DONGLE
        bool "Serial dongle support"
        depends on IRTTY_SIR
index ff45cd0d60e84f88b5e34ec40f61e2e5e0d85eb3..c96b46b2c3a8db6452bd68c7750613514102340b 100644 (file)
@@ -804,7 +804,7 @@ static int sh_irda_probe(struct platform_device *pdev)
                goto err_mem_4;
 
        platform_set_drvdata(pdev, ndev);
-       err = request_irq(irq, sh_irda_irq, 0, "sh_irda", self);
+       err = devm_request_irq(&pdev->dev, irq, sh_irda_irq, 0, "sh_irda", self);
        if (err) {
                dev_warn(&pdev->dev, "Unable to attach sh_irda interrupt\n");
                goto err_mem_4;
index 8d9ae5a086d54d8d78ba8ae8ee4fee1c9fd76475..cadf52e224645f1f5f06f588447686015bf67e3a 100644 (file)
@@ -761,7 +761,7 @@ static int sh_sir_probe(struct platform_device *pdev)
                goto err_mem_4;
 
        platform_set_drvdata(pdev, ndev);
-       err = request_irq(irq, sh_sir_irq, 0, "sh_sir", self);
+       err = devm_request_irq(&pdev->dev, irq, sh_sir_irq, 0, "sh_sir", self);
        if (err) {
                dev_warn(&pdev->dev, "Unable to attach sh_sir interrupt\n");
                goto err_mem_4;
index 24ea994b6274c324143973a74aeedf78088ffc74..09ababe54a5b050ba247f9e61a0e34ade148d515 100644 (file)
@@ -290,8 +290,8 @@ xmit_world:
        return dev_queue_xmit(skb);
 }
 
-netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
-                              struct net_device *dev)
+static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
+                                     struct net_device *dev)
 {
        unsigned int len = skb->len;
        int ret;
@@ -305,7 +305,7 @@ netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
        }
 
        if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
-               struct macvlan_pcpu_stats *pcpu_stats;
+               struct vlan_pcpu_stats *pcpu_stats;
 
                pcpu_stats = this_cpu_ptr(vlan->pcpu_stats);
                u64_stats_update_begin(&pcpu_stats->syncp);
@@ -317,7 +317,6 @@ netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
        }
        return ret;
 }
-EXPORT_SYMBOL_GPL(macvlan_start_xmit);
 
 static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
                               unsigned short type, const void *daddr,
@@ -546,12 +545,12 @@ static int macvlan_init(struct net_device *dev)
 
        macvlan_set_lockdep_class(dev);
 
-       vlan->pcpu_stats = alloc_percpu(struct macvlan_pcpu_stats);
+       vlan->pcpu_stats = alloc_percpu(struct vlan_pcpu_stats);
        if (!vlan->pcpu_stats)
                return -ENOMEM;
 
        for_each_possible_cpu(i) {
-               struct macvlan_pcpu_stats *mvlstats;
+               struct vlan_pcpu_stats *mvlstats;
                mvlstats = per_cpu_ptr(vlan->pcpu_stats, i);
                u64_stats_init(&mvlstats->syncp);
        }
@@ -577,7 +576,7 @@ static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
        struct macvlan_dev *vlan = netdev_priv(dev);
 
        if (vlan->pcpu_stats) {
-               struct macvlan_pcpu_stats *p;
+               struct vlan_pcpu_stats *p;
                u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes;
                u32 rx_errors = 0, tx_dropped = 0;
                unsigned int start;
@@ -690,8 +689,19 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
                                              netdev_features_t features)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
+       netdev_features_t mask;
 
-       return features & (vlan->set_features | ~MACVLAN_FEATURES);
+       features |= NETIF_F_ALL_FOR_ALL;
+       features &= (vlan->set_features | ~MACVLAN_FEATURES);
+       mask = features;
+
+       features = netdev_increment_features(vlan->lowerdev->features,
+                                            features,
+                                            mask);
+       if (!vlan->fwd_priv)
+               features |= NETIF_F_LLTX;
+
+       return features;
 }
 
 static const struct ethtool_ops macvlan_ethtool_ops = {
@@ -1010,9 +1020,8 @@ static int macvlan_device_event(struct notifier_block *unused,
                break;
        case NETDEV_FEAT_CHANGE:
                list_for_each_entry(vlan, &port->vlans, list) {
-                       vlan->dev->features = dev->features & MACVLAN_FEATURES;
                        vlan->dev->gso_max_size = dev->gso_max_size;
-                       netdev_features_change(vlan->dev);
+                       netdev_update_features(vlan->dev);
                }
                break;
        case NETDEV_UNREGISTER:
index 8403316eb02bbad1c0bd91344ef82f774552d602..3e027ed0b3bbccaf399e2800bcdd0983979b7c4a 100644 (file)
@@ -341,34 +341,6 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
 }
 EXPORT_SYMBOL(mdio45_ethtool_gset_npage);
 
-/**
- * mdio45_ethtool_spauseparam_an - set auto-negotiated pause parameters
- * @mdio: MDIO interface
- * @ecmd: Ethtool request structure
- *
- * This function assumes that the PHY has an auto-negotiation MMD.  It
- * will enable and disable advertising of flow control as appropriate.
- */
-void mdio45_ethtool_spauseparam_an(const struct mdio_if_info *mdio,
-                                  const struct ethtool_pauseparam *ecmd)
-{
-       int adv, old_adv;
-
-       WARN_ON(!(mdio->mmds & MDIO_DEVS_AN));
-
-       old_adv = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
-                                 MDIO_AN_ADVERTISE);
-       adv = ((old_adv & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) |
-              mii_advertise_flowctrl((ecmd->rx_pause ? FLOW_CTRL_RX : 0) |
-                                     (ecmd->tx_pause ? FLOW_CTRL_TX : 0)));
-       if (adv != old_adv) {
-               mdio->mdio_write(mdio->dev, mdio->prtad, MDIO_MMD_AN,
-                                MDIO_AN_ADVERTISE, adv);
-               mdio45_nway_restart(mdio);
-       }
-}
-EXPORT_SYMBOL(mdio45_ethtool_spauseparam_an);
-
 /**
  * mdio_mii_ioctl - MII ioctl interface for MDIO (clause 22 or 45) PHYs
  * @mdio: MDIO interface
index 33e1c861d9ba5569f0aa659d38a6d2db71f862e7..930694d3a13f7e7568fab6997ccdcd0ecabbb063 100644 (file)
@@ -1,7 +1,4 @@
-/*
- * drivers/net/phy/mdio_bus.c
- *
- * MDIO Bus interface
+/* MDIO Bus interface
  *
  * Author: Andy Fleming
  *
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/phy.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
 
-#include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
 
 /**
  * mdiobus_alloc_size - allocate a mii_bus structure
@@ -139,8 +136,7 @@ int mdiobus_register(struct mii_bus *bus)
        int i, err;
 
        if (NULL == bus || NULL == bus->name ||
-                       NULL == bus->read ||
-                       NULL == bus->write)
+           NULL == bus->read || NULL == bus->write)
                return -EINVAL;
 
        BUG_ON(bus->state != MDIOBUS_ALLOCATED &&
@@ -214,9 +210,7 @@ EXPORT_SYMBOL(mdiobus_unregister);
  */
 void mdiobus_free(struct mii_bus *bus)
 {
-       /*
-        * For compatibility with error handling in drivers.
-        */
+       /* For compatibility with error handling in drivers. */
        if (bus->state == MDIOBUS_ALLOCATED) {
                kfree(bus);
                return;
@@ -335,15 +329,13 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
        if (!netdev)
                return true;
 
-       /*
-        * Don't suspend PHY if the attched netdev parent may wakeup.
+       /* Don't suspend PHY if the attched netdev parent may wakeup.
         * The parent may point to a PCI device, as in tg3 driver.
         */
        if (netdev->dev.parent && device_may_wakeup(netdev->dev.parent))
                return false;
 
-       /*
-        * Also don't suspend PHY if the netdev itself may wakeup. This
+       /* Also don't suspend PHY if the netdev itself may wakeup. This
         * is the case for devices w/o underlaying pwr. mgmt. aware bus,
         * e.g. SoC devices.
         */
@@ -358,8 +350,7 @@ static int mdio_bus_suspend(struct device *dev)
        struct phy_driver *phydrv = to_phy_driver(dev->driver);
        struct phy_device *phydev = to_phy_device(dev);
 
-       /*
-        * We must stop the state machine manually, otherwise it stops out of
+       /* We must stop the state machine manually, otherwise it stops out of
         * control, possibly with the phydev->lock held. Upon resume, netdev
         * may call phy routines that try to grab the same lock, and that may
         * lead to a deadlock.
@@ -388,7 +379,7 @@ static int mdio_bus_resume(struct device *dev)
 
 no_resume:
        if (phydev->attached_dev && phydev->adjust_link)
-               phy_start_machine(phydev, NULL);
+               phy_start_machine(phydev);
 
        return 0;
 }
@@ -410,12 +401,12 @@ static int mdio_bus_restore(struct device *dev)
        phydev->link = 0;
        phydev->state = PHY_UP;
 
-       phy_start_machine(phydev, NULL);
+       phy_start_machine(phydev);
 
        return 0;
 }
 
-static struct dev_pm_ops mdio_bus_pm_ops = {
+static const struct dev_pm_ops mdio_bus_pm_ops = {
        .suspend = mdio_bus_suspend,
        .resume = mdio_bus_resume,
        .freeze = mdio_bus_suspend,
index 20908865709fb186814d32fbfbb247387cfb6e79..76e8936ab9e463ae3fb86692cf7de85a5528e6c0 100644 (file)
@@ -1,7 +1,4 @@
-/*
- * drivers/net/phy/phy.c
- *
- * Framework for configuring and reading PHY devices
+/* Framework for configuring and reading PHY devices
  * Based on code in sungem_phy.c and gianfar_phy.c
  *
  * Author: Andy Fleming
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/mdio.h>
-
+#include <linux/io.h>
+#include <linux/uaccess.h>
 #include <linux/atomic.h>
-#include <asm/io.h>
+
 #include <asm/irq.h>
-#include <asm/uaccess.h>
 
 /**
  * phy_print_status - Convenience function to print out the current phy status
  */
 void phy_print_status(struct phy_device *phydev)
 {
-       if (phydev->link)
+       if (phydev->link) {
                pr_info("%s - Link is Up - %d/%s\n",
                        dev_name(&phydev->dev),
                        phydev->speed,
                        DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
-       else
+       } else  {
                pr_info("%s - Link is Down\n", dev_name(&phydev->dev));
+       }
 }
 EXPORT_SYMBOL(phy_print_status);
 
@@ -69,12 +67,10 @@ EXPORT_SYMBOL(phy_print_status);
  */
 static int phy_clear_interrupt(struct phy_device *phydev)
 {
-       int err = 0;
-
        if (phydev->drv->ack_interrupt)
-               err = phydev->drv->ack_interrupt(phydev);
+               return phydev->drv->ack_interrupt(phydev);
 
-       return err;
+       return 0;
 }
 
 /**
@@ -86,13 +82,11 @@ static int phy_clear_interrupt(struct phy_device *phydev)
  */
 static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
 {
-       int err = 0;
-
        phydev->interrupts = interrupts;
        if (phydev->drv->config_intr)
-               err = phydev->drv->config_intr(phydev);
+               return phydev->drv->config_intr(phydev);
 
-       return err;
+       return 0;
 }
 
 
@@ -106,15 +100,14 @@ static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
  */
 static inline int phy_aneg_done(struct phy_device *phydev)
 {
-       int retval;
-
-       retval = phy_read(phydev, MII_BMSR);
+       int retval = phy_read(phydev, MII_BMSR);
 
        return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
 }
 
 /* A structure for mapping a particular speed and duplex
- * combination to a particular SUPPORTED and ADVERTISED value */
+ * combination to a particular SUPPORTED and ADVERTISED value
+ */
 struct phy_setting {
        int speed;
        int duplex;
@@ -177,8 +170,7 @@ static inline int phy_find_setting(int speed, int duplex)
        int idx = 0;
 
        while (idx < ARRAY_SIZE(settings) &&
-                       (settings[idx].speed != speed ||
-                       settings[idx].duplex != duplex))
+              (settings[idx].speed != speed || settings[idx].duplex != duplex))
                idx++;
 
        return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
@@ -245,8 +237,7 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
        if (cmd->phy_address != phydev->addr)
                return -EINVAL;
 
-       /* We make sure that we don't pass unsupported
-        * values in to the PHY */
+       /* We make sure that we don't pass unsupported values in to the PHY */
        cmd->advertising &= phydev->supported;
 
        /* Verify the settings we care about. */
@@ -313,12 +304,10 @@ EXPORT_SYMBOL(phy_ethtool_gset);
  * PHYCONTROL layer.  It changes registers without regard to
  * current state.  Use at own risk.
  */
-int phy_mii_ioctl(struct phy_device *phydev,
-               struct ifreq *ifr, int cmd)
+int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
 {
        struct mii_ioctl_data *mii_data = if_mii(ifr);
        u16 val = mii_data->val_in;
-       int ret = 0;
 
        switch (cmd) {
        case SIOCGMIIPHY:
@@ -328,25 +317,24 @@ int phy_mii_ioctl(struct phy_device *phydev,
        case SIOCGMIIREG:
                mii_data->val_out = mdiobus_read(phydev->bus, mii_data->phy_id,
                                                 mii_data->reg_num);
-               break;
+               return 0;
 
        case SIOCSMIIREG:
                if (mii_data->phy_id == phydev->addr) {
                        switch (mii_data->reg_num) {
                        case MII_BMCR:
-                               if ((val & (BMCR_RESET|BMCR_ANENABLE)) == 0)
+                               if ((val & (BMCR_RESET | BMCR_ANENABLE)) == 0)
                                        phydev->autoneg = AUTONEG_DISABLE;
                                else
                                        phydev->autoneg = AUTONEG_ENABLE;
-                               if ((!phydev->autoneg) && (val & BMCR_FULLDPLX))
+                               if (!phydev->autoneg && (val & BMCR_FULLDPLX))
                                        phydev->duplex = DUPLEX_FULL;
                                else
                                        phydev->duplex = DUPLEX_HALF;
-                               if ((!phydev->autoneg) &&
-                                               (val & BMCR_SPEED1000))
+                               if (!phydev->autoneg && (val & BMCR_SPEED1000))
                                        phydev->speed = SPEED_1000;
-                               else if ((!phydev->autoneg) &&
-                                               (val & BMCR_SPEED100))
+                               else if (!phydev->autoneg &&
+                                        (val & BMCR_SPEED100))
                                        phydev->speed = SPEED_100;
                                break;
                        case MII_ADVERTISE:
@@ -363,8 +351,8 @@ int phy_mii_ioctl(struct phy_device *phydev,
 
                if (mii_data->reg_num == MII_BMCR &&
                    val & BMCR_RESET)
-                       ret = phy_init_hw(phydev);
-               break;
+                       return phy_init_hw(phydev);
+               return 0;
 
        case SIOCSHWTSTAMP:
                if (phydev->drv->hwtstamp)
@@ -374,8 +362,6 @@ int phy_mii_ioctl(struct phy_device *phydev,
        default:
                return -EOPNOTSUPP;
        }
-
-       return ret;
 }
 EXPORT_SYMBOL(phy_mii_ioctl);
 
@@ -398,7 +384,6 @@ int phy_start_aneg(struct phy_device *phydev)
                phy_sanitize_settings(phydev);
 
        err = phydev->drv->config_aneg(phydev);
-
        if (err < 0)
                goto out_unlock;
 
@@ -418,25 +403,18 @@ out_unlock:
 }
 EXPORT_SYMBOL(phy_start_aneg);
 
-
 /**
  * phy_start_machine - start PHY state machine tracking
  * @phydev: the phy_device struct
- * @handler: callback function for state change notifications
  *
  * Description: The PHY infrastructure can run a state machine
  *   which tracks whether the PHY is starting up, negotiating,
  *   etc.  This function starts the timer which tracks the state
- *   of the PHY.  If you want to be notified when the state changes,
- *   pass in the callback @handler, otherwise, pass NULL.  If you
- *   want to maintain your own state machine, do not call this
- *   function.
+ *   of the PHY.  If you want to maintain your own state machine,
+ *   do not call this function.
  */
-void phy_start_machine(struct phy_device *phydev,
-               void (*handler)(struct net_device *))
+void phy_start_machine(struct phy_device *phydev)
 {
-       phydev->adjust_state = handler;
-
        queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, HZ);
 }
 
@@ -456,8 +434,6 @@ void phy_stop_machine(struct phy_device *phydev)
        if (phydev->state > PHY_UP)
                phydev->state = PHY_UP;
        mutex_unlock(&phydev->lock);
-
-       phydev->adjust_state = NULL;
 }
 
 /**
@@ -494,7 +470,8 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
        /* 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. */
+        * interrupt, and then reenable the irq line.
+        */
        disable_irq_nosync(irq);
        atomic_inc(&phydev->irq_disable);
 
@@ -509,16 +486,12 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
  */
 static int phy_enable_interrupts(struct phy_device *phydev)
 {
-       int err;
-
-       err = phy_clear_interrupt(phydev);
+       int err = phy_clear_interrupt(phydev);
 
        if (err < 0)
                return err;
 
-       err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
-
-       return err;
+       return phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
 }
 
 /**
@@ -531,13 +504,11 @@ static int phy_disable_interrupts(struct phy_device *phydev)
 
        /* Disable PHY interrupts */
        err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
-
        if (err)
                goto phy_err;
 
        /* Clear the interrupt */
        err = phy_clear_interrupt(phydev);
-
        if (err)
                goto phy_err;
 
@@ -561,22 +532,16 @@ phy_err:
  */
 int phy_start_interrupts(struct phy_device *phydev)
 {
-       int err = 0;
-
        atomic_set(&phydev->irq_disable, 0);
-       if (request_irq(phydev->irq, phy_interrupt,
-                               IRQF_SHARED,
-                               "phy_interrupt",
-                               phydev) < 0) {
+       if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt",
+                       phydev) < 0) {
                pr_warn("%s: Can't get IRQ %d (PHY)\n",
                        phydev->bus->name, phydev->irq);
                phydev->irq = PHY_POLL;
                return 0;
        }
 
-       err = phy_enable_interrupts(phydev);
-
-       return err;
+       return phy_enable_interrupts(phydev);
 }
 EXPORT_SYMBOL(phy_start_interrupts);
 
@@ -586,24 +551,20 @@ EXPORT_SYMBOL(phy_start_interrupts);
  */
 int phy_stop_interrupts(struct phy_device *phydev)
 {
-       int err;
-
-       err = phy_disable_interrupts(phydev);
+       int err = phy_disable_interrupts(phydev);
 
        if (err)
                phy_error(phydev);
 
        free_irq(phydev->irq, phydev);
 
-       /*
-        * Cannot call flush_scheduled_work() here as desired because
+       /* 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
+       /* 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.
         */
@@ -614,14 +575,12 @@ 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
  */
 void phy_change(struct work_struct *work)
 {
-       int err;
        struct phy_device *phydev =
                container_of(work, struct phy_device, phy_queue);
 
@@ -629,9 +588,7 @@ void phy_change(struct work_struct *work)
            !phydev->drv->did_interrupt(phydev))
                goto ignore;
 
-       err = phy_disable_interrupts(phydev);
-
-       if (err)
+       if (phy_disable_interrupts(phydev))
                goto phy_err;
 
        mutex_lock(&phydev->lock);
@@ -643,16 +600,13 @@ void phy_change(struct work_struct *work)
        enable_irq(phydev->irq);
 
        /* Reenable interrupts */
-       if (PHY_HALTED != phydev->state)
-               err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
-
-       if (err)
+       if (PHY_HALTED != phydev->state &&
+           phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED))
                goto irq_enable_err;
 
        /* reschedule state queue work to run as soon as possible */
        cancel_delayed_work_sync(&phydev->state_queue);
        queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0);
-
        return;
 
 ignore:
@@ -691,13 +645,12 @@ void phy_stop(struct phy_device *phydev)
 out_unlock:
        mutex_unlock(&phydev->lock);
 
-       /*
-        * Cannot call flush_scheduled_work() here as desired because
+       /* Cannot call flush_scheduled_work() here as desired because
         * of rtnl_lock(), but PHY_HALTED shall guarantee phy_change()
         * will not reenable interrupts.
         */
 }
-
+EXPORT_SYMBOL(phy_stop);
 
 /**
  * phy_start - start or restart a PHY device
@@ -727,7 +680,6 @@ void phy_start(struct phy_device *phydev)
        }
        mutex_unlock(&phydev->lock);
 }
-EXPORT_SYMBOL(phy_stop);
 EXPORT_SYMBOL(phy_start);
 
 /**
@@ -744,9 +696,6 @@ void phy_state_machine(struct work_struct *work)
 
        mutex_lock(&phydev->lock);
 
-       if (phydev->adjust_state)
-               phydev->adjust_state(phydev->attached_dev);
-
        switch (phydev->state) {
        case PHY_DOWN:
        case PHY_STARTING:
@@ -761,12 +710,10 @@ void phy_state_machine(struct work_struct *work)
                break;
        case PHY_AN:
                err = phy_read_status(phydev);
-
                if (err < 0)
                        break;
 
-               /* If the link is down, give up on
-                * negotiation for now */
+               /* If the link is down, give up on negotiation for now */
                if (!phydev->link) {
                        phydev->state = PHY_NOLINK;
                        netif_carrier_off(phydev->attached_dev);
@@ -774,8 +721,7 @@ void phy_state_machine(struct work_struct *work)
                        break;
                }
 
-               /* Check if negotiation is done.  Break
-                * if there's an error */
+               /* Check if negotiation is done.  Break if there's an error */
                err = phy_aneg_done(phydev);
                if (err < 0)
                        break;
@@ -788,15 +734,13 @@ void phy_state_machine(struct work_struct *work)
 
                } else if (0 == phydev->link_timeout--) {
                        needs_aneg = 1;
-                       /* If we have the magic_aneg bit,
-                        * we try again */
+                       /* If we have the magic_aneg bit, we try again */
                        if (phydev->drv->flags & PHY_HAS_MAGICANEG)
                                break;
                }
                break;
        case PHY_NOLINK:
                err = phy_read_status(phydev);
-
                if (err)
                        break;
 
@@ -808,7 +752,6 @@ void phy_state_machine(struct work_struct *work)
                break;
        case PHY_FORCING:
                err = genphy_update_link(phydev);
-
                if (err)
                        break;
 
@@ -831,7 +774,6 @@ void phy_state_machine(struct work_struct *work)
                break;
        case PHY_CHANGELINK:
                err = phy_read_status(phydev);
-
                if (err)
                        break;
 
@@ -847,7 +789,7 @@ void phy_state_machine(struct work_struct *work)
 
                if (phy_interrupt_is_valid(phydev))
                        err = phy_config_interrupt(phydev,
-                                       PHY_INTERRUPT_ENABLED);
+                                                  PHY_INTERRUPT_ENABLED);
                break;
        case PHY_HALTED:
                if (phydev->link) {
@@ -858,15 +800,11 @@ void phy_state_machine(struct work_struct *work)
                }
                break;
        case PHY_RESUMING:
-
                err = phy_clear_interrupt(phydev);
-
                if (err)
                        break;
 
-               err = phy_config_interrupt(phydev,
-                               PHY_INTERRUPT_ENABLED);
-
+               err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
                if (err)
                        break;
 
@@ -876,8 +814,8 @@ void phy_state_machine(struct work_struct *work)
                                break;
 
                        /* err > 0 if AN is done.
-                        * Otherwise, it's 0, and we're
-                        * still waiting for AN */
+                        * Otherwise, it's 0, and we're  still waiting for AN
+                        */
                        if (err > 0) {
                                err = phy_read_status(phydev);
                                if (err)
@@ -886,8 +824,9 @@ void phy_state_machine(struct work_struct *work)
                                if (phydev->link) {
                                        phydev->state = PHY_RUNNING;
                                        netif_carrier_on(phydev->attached_dev);
-                               } else
+                               } else  {
                                        phydev->state = PHY_NOLINK;
+                               }
                                phydev->adjust_link(phydev->attached_dev);
                        } else {
                                phydev->state = PHY_AN;
@@ -901,8 +840,9 @@ void phy_state_machine(struct work_struct *work)
                        if (phydev->link) {
                                phydev->state = PHY_RUNNING;
                                netif_carrier_on(phydev->attached_dev);
-                       } else
+                       } else  {
                                phydev->state = PHY_NOLINK;
+                       }
                        phydev->adjust_link(phydev->attached_dev);
                }
                break;
@@ -920,7 +860,7 @@ void phy_state_machine(struct work_struct *work)
                phy_error(phydev);
 
        queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
-                       PHY_STATE_TIME * HZ);
+                          PHY_STATE_TIME * HZ);
 }
 
 void phy_mac_interrupt(struct phy_device *phydev, int new_link)
@@ -962,14 +902,10 @@ static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
 static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
                                 int addr)
 {
-       u32 ret;
-
        mmd_phy_indirect(bus, prtad, devad, addr);
 
        /* Read the content of the MMD's selected register */
-       ret = bus->read(bus, addr, MII_MMD_DATA);
-
-       return ret;
+       return bus->read(bus, addr, MII_MMD_DATA);
 }
 
 /**
@@ -1009,8 +945,6 @@ static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
  */
 int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
 {
-       int ret = -EPROTONOSUPPORT;
-
        /* According to 802.3az,the EEE is supported only in full duplex-mode.
         * Also EEE feature is active when core is operating with MII, GMII
         * or RGMII.
@@ -1036,7 +970,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
 
                cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
                if (!cap)
-                       goto eee_exit;
+                       return -EPROTONOSUPPORT;
 
                /* Check which link settings negotiated and verify it in
                 * the EEE advertising registers.
@@ -1055,7 +989,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
                lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
                idx = phy_find_setting(phydev->speed, phydev->duplex);
                if (!(lp & adv & settings[idx].setting))
-                       goto eee_exit;
+                       return -EPROTONOSUPPORT;
 
                if (clk_stop_enable) {
                        /* Configure the PHY to stop receiving xMII
@@ -1072,11 +1006,10 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
                                               MDIO_MMD_PCS, phydev->addr, val);
                }
 
-               ret = 0; /* EEE supported */
+               return 0; /* EEE supported */
        }
 
-eee_exit:
-       return ret;
+       return -EPROTONOSUPPORT;
 }
 EXPORT_SYMBOL(phy_init_eee);
 
@@ -1091,7 +1024,6 @@ int phy_get_eee_err(struct phy_device *phydev)
 {
        return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR,
                                     MDIO_MMD_PCS, phydev->addr);
-
 }
 EXPORT_SYMBOL(phy_get_eee_err);
 
@@ -1141,9 +1073,8 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
  */
 int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
 {
-       int val;
+       int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
 
-       val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
        phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
                               phydev->addr, val);
 
index d53242449c90d256a6f2663bd8672f899fbe3007..39794c4d7b21b78cf21166d13f5d89133850d12e 100644 (file)
@@ -1,7 +1,4 @@
-/*
- * drivers/net/phy/phy_device.c
- *
- * Framework for finding and configuring PHYs.
+/* Framework for finding and configuring PHYs.
  * Also contains generic PHY driver
  *
  * Author: Andy Fleming
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/phy.h>
+#include <linux/mdio.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
 
-#include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
 
 MODULE_DESCRIPTION("PHY library");
 MODULE_AUTHOR("Andy Fleming");
@@ -53,31 +51,31 @@ static void phy_device_release(struct device *dev)
        kfree(to_phy_device(dev));
 }
 
-static struct phy_driver genphy_driver;
-extern int mdio_bus_init(void);
-extern void mdio_bus_exit(void);
+enum genphy_driver {
+       GENPHY_DRV_1G,
+       GENPHY_DRV_10G,
+       GENPHY_DRV_MAX
+};
+
+static struct phy_driver genphy_driver[GENPHY_DRV_MAX];
 
 static LIST_HEAD(phy_fixup_list);
 static DEFINE_MUTEX(phy_fixup_lock);
 
-static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
-                            u32 flags, phy_interface_t interface);
-
-/*
- * Creates a new phy_fixup and adds it to the list
+/**
+ * phy_register_fixup - creates a new phy_fixup and adds it to the list
  * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID)
  * @phy_uid: Used to match against phydev->phy_id (the UID of the PHY)
- *     It can also be PHY_ANY_UID
+ *     It can also be PHY_ANY_UID
  * @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before
- *     comparison
+ *     comparison
  * @run: The actual code to be run when a matching PHY is found
  */
 int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
-               int (*run)(struct phy_device *))
+                      int (*run)(struct phy_device *))
 {
-       struct phy_fixup *fixup;
+       struct phy_fixup *fixup = kzalloc(sizeof(*fixup), GFP_KERNEL);
 
-       fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL);
        if (!fixup)
                return -ENOMEM;
 
@@ -96,7 +94,7 @@ EXPORT_SYMBOL(phy_register_fixup);
 
 /* Registers a fixup to be run on any PHY with the UID in phy_uid */
 int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
-               int (*run)(struct phy_device *))
+                              int (*run)(struct phy_device *))
 {
        return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run);
 }
@@ -104,14 +102,13 @@ EXPORT_SYMBOL(phy_register_fixup_for_uid);
 
 /* Registers a fixup to be run on the PHY with id string bus_id */
 int phy_register_fixup_for_id(const char *bus_id,
-               int (*run)(struct phy_device *))
+                             int (*run)(struct phy_device *))
 {
        return phy_register_fixup(bus_id, PHY_ANY_UID, 0xffffffff, run);
 }
 EXPORT_SYMBOL(phy_register_fixup_for_id);
 
-/*
- * Returns 1 if fixup matches phydev in bus_id and phy_uid.
+/* Returns 1 if fixup matches phydev in bus_id and phy_uid.
  * Fixups can be set to match any in one or more fields.
  */
 static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
@@ -121,7 +118,7 @@ static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
                        return 0;
 
        if ((fixup->phy_uid & fixup->phy_uid_mask) !=
-                       (phydev->phy_id & fixup->phy_uid_mask))
+           (phydev->phy_id & fixup->phy_uid_mask))
                if (fixup->phy_uid != PHY_ANY_UID)
                        return 0;
 
@@ -129,16 +126,14 @@ static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
 }
 
 /* Runs any matching fixups for this phydev */
-int phy_scan_fixups(struct phy_device *phydev)
+static int phy_scan_fixups(struct phy_device *phydev)
 {
        struct phy_fixup *fixup;
 
        mutex_lock(&phy_fixup_lock);
        list_for_each_entry(fixup, &phy_fixup_list, list) {
                if (phy_needs_fixup(phydev, fixup)) {
-                       int err;
-
-                       err = fixup->run(phydev);
+                       int err = fixup->run(phydev);
 
                        if (err < 0) {
                                mutex_unlock(&phy_fixup_lock);
@@ -150,17 +145,15 @@ int phy_scan_fixups(struct phy_device *phydev)
 
        return 0;
 }
-EXPORT_SYMBOL(phy_scan_fixups);
 
 struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
-                       bool is_c45, struct phy_c45_device_ids *c45_ids)
+                                    bool is_c45,
+                                    struct phy_c45_device_ids *c45_ids)
 {
        struct phy_device *dev;
 
-       /* We allocate the device, and initialize the
-        * default values */
+       /* We allocate the device, and initialize the default values */
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-
        if (NULL == dev)
                return (struct phy_device *)PTR_ERR((void *)-ENOMEM);
 
@@ -168,7 +161,8 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
 
        dev->speed = 0;
        dev->duplex = -1;
-       dev->pause = dev->asym_pause = 0;
+       dev->pause = 0;
+       dev->asym_pause = 0;
        dev->link = 1;
        dev->interface = PHY_INTERFACE_MODE_GMII;
 
@@ -192,14 +186,15 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
        INIT_WORK(&dev->phy_queue, phy_change);
 
        /* Request the appropriate module unconditionally; don't
-          bother trying to do so only if it isn't already loaded,
-          because that gets complicated. A hotplug event would have
-          done an unconditional modprobe anyway.
-          We don't do normal hotplug because it won't work for MDIO
-          -- because it relies on the device staying around for long
-          enough for the driver to get loaded. With MDIO, the NIC
-          driver will get bored and give up as soon as it finds that
-          there's no driver _already_ loaded. */
+        * bother trying to do so only if it isn't already loaded,
+        * because that gets complicated. A hotplug event would have
+        * done an unconditional modprobe anyway.
+        * We don't do normal hotplug because it won't work for MDIO
+        * -- because it relies on the device staying around for long
+        * enough for the driver to get loaded. With MDIO, the NIC
+        * driver will get bored and give up as soon as it finds that
+        * there's no driver _already_ loaded.
+        */
        request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id));
 
        device_initialize(&dev->dev);
@@ -299,10 +294,8 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id,
        if (is_c45)
                return get_phy_c45_ids(bus, addr, phy_id, c45_ids);
 
-       /* Grab the bits from PHYIR1, and put them
-        * in the upper half */
+       /* Grab the bits from PHYIR1, and put them in the upper half */
        phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
-
        if (phy_reg < 0)
                return -EIO;
 
@@ -310,7 +303,6 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id,
 
        /* Grab the bits from PHYIR2, and put them in the lower half */
        phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
-
        if (phy_reg < 0)
                return -EIO;
 
@@ -320,7 +312,8 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id,
 }
 
 /**
- * get_phy_device - reads the specified PHY device and returns its @phy_device struct
+ * get_phy_device - reads the specified PHY device and returns its @phy_device
+ *                 struct
  * @bus: the target MII bus
  * @addr: PHY address on the MII bus
  * @is_c45: If true the PHY uses the 802.3 clause 45 protocol
@@ -331,7 +324,6 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id,
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
 {
        struct phy_c45_device_ids c45_ids = {0};
-       struct phy_device *dev = NULL;
        u32 phy_id = 0;
        int r;
 
@@ -343,9 +335,7 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
        if ((phy_id & 0x1fffffff) == 0x1fffffff)
                return NULL;
 
-       dev = phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);
-
-       return dev;
+       return phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);
 }
 EXPORT_SYMBOL(get_phy_device);
 
@@ -357,8 +347,7 @@ int phy_device_register(struct phy_device *phydev)
 {
        int err;
 
-       /* Don't register a phy if one is already registered at this
-        * address */
+       /* Don't register a phy if one is already registered at this address */
        if (phydev->bus->phy_map[phydev->addr])
                return -EINVAL;
        phydev->bus->phy_map[phydev->addr] = phydev;
@@ -413,7 +402,7 @@ EXPORT_SYMBOL(phy_find_first);
  *   this function.
  */
 static void phy_prepare_link(struct phy_device *phydev,
-               void (*handler)(struct net_device *))
+                            void (*handler)(struct net_device *))
 {
        phydev->adjust_link = handler;
 }
@@ -436,7 +425,7 @@ int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
                return rc;
 
        phy_prepare_link(phydev, handler);
-       phy_start_machine(phydev, NULL);
+       phy_start_machine(phydev);
        if (phydev->irq > 0)
                phy_start_interrupts(phydev);
 
@@ -460,15 +449,16 @@ EXPORT_SYMBOL(phy_connect_direct);
  *   the desired functionality.
  */
 struct phy_device *phy_connect(struct net_device *dev, const char *bus_id,
-               void (*handler)(struct net_device *),
-               phy_interface_t interface)
+                              void (*handler)(struct net_device *),
+                              phy_interface_t interface)
 {
        struct phy_device *phydev;
        struct device *d;
        int rc;
 
        /* Search the list of PHY devices on the mdio bus for the
-        * PHY with the requested name */
+        * PHY with the requested name
+        */
        d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id);
        if (!d) {
                pr_err("PHY %s not found\n", bus_id);
@@ -485,7 +475,8 @@ struct phy_device *phy_connect(struct net_device *dev, const char *bus_id,
 EXPORT_SYMBOL(phy_connect);
 
 /**
- * phy_disconnect - disable interrupts, stop state machine, and detach a PHY device
+ * phy_disconnect - disable interrupts, stop state machine, and detach a PHY
+ *                 device
  * @phydev: target phy_device struct
  */
 void phy_disconnect(struct phy_device *phydev)
@@ -534,8 +525,7 @@ static int phy_poll_reset(struct phy_device *phydev)
        if (ret & BMCR_RESET)
                return -ETIMEDOUT;
 
-       /*
-        * Some chips (smsc911x) may still need up to another 1ms after the
+       /* Some chips (smsc911x) may still need up to another 1ms after the
         * BMCR_RESET bit is cleared before they are usable.
         */
        msleep(1);
@@ -574,26 +564,25 @@ EXPORT_SYMBOL(phy_init_hw);
  *
  * Description: Called by drivers to attach to a particular PHY
  *     device. The phy_device is found, and properly hooked up
- *     to the phy_driver.  If no driver is attached, then the
- *     genphy_driver is used.  The phy_device is given a ptr to
+ *     to the phy_driver.  If no driver is attached, then a
+ *     generic driver is used.  The phy_device is given a ptr to
  *     the attaching device, and given a callback for link status
  *     change.  The phy_device is returned to the attaching driver.
  */
-static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
-                            u32 flags, phy_interface_t interface)
+int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
+                     u32 flags, phy_interface_t interface)
 {
        struct device *d = &phydev->dev;
        int err;
 
        /* Assume that if there is no driver, that it doesn't
-        * exist, and we should use the genphy driver. */
+        * exist, and we should use the genphy driver.
+        */
        if (NULL == d->driver) {
-               if (phydev->is_c45) {
-                       pr_err("No driver for phy %x\n", phydev->phy_id);
-                       return -ENODEV;
-               }
-
-               d->driver = &genphy_driver.driver;
+               if (phydev->is_c45)
+                       d->driver = &genphy_driver[GENPHY_DRV_10G].driver;
+               else
+                       d->driver = &genphy_driver[GENPHY_DRV_1G].driver;
 
                err = d->driver->probe(d);
                if (err >= 0)
@@ -619,7 +608,8 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
 
        /* Do initial configuration here, now that
         * we have certain key parameters
-        * (dev_flags and interface) */
+        * (dev_flags and interface)
+        */
        err = phy_init_hw(phydev);
        if (err)
                phy_detach(phydev);
@@ -628,6 +618,7 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
 
        return err;
 }
+EXPORT_SYMBOL(phy_attach_direct);
 
 /**
  * phy_attach - attach a network device to a particular PHY device
@@ -638,8 +629,8 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
  * Description: Same as phy_attach_direct() except that a PHY bus_id
  *     string is passed instead of a pointer to a struct phy_device.
  */
-struct phy_device *phy_attach(struct net_device *dev,
-               const char *bus_id, phy_interface_t interface)
+struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
+                             phy_interface_t interface)
 {
        struct bus_type *bus = &mdio_bus_type;
        struct phy_device *phydev;
@@ -647,7 +638,8 @@ struct phy_device *phy_attach(struct net_device *dev,
        int rc;
 
        /* Search the list of PHY devices on the mdio bus for the
-        * PHY with the requested name */
+        * PHY with the requested name
+        */
        d = bus_find_device_by_name(bus, NULL, bus_id);
        if (!d) {
                pr_err("PHY %s not found\n", bus_id);
@@ -669,6 +661,7 @@ EXPORT_SYMBOL(phy_attach);
  */
 void phy_detach(struct phy_device *phydev)
 {
+       int i;
        phydev->attached_dev->phydev = NULL;
        phydev->attached_dev = NULL;
        phy_suspend(phydev);
@@ -676,9 +669,14 @@ void phy_detach(struct phy_device *phydev)
        /* If the device had no specific driver before (i.e. - it
         * was using the generic driver), we unbind the device
         * from the generic driver so that there's a chance a
-        * real driver could be loaded */
-       if (phydev->dev.driver == &genphy_driver.driver)
-               device_release_driver(&phydev->dev);
+        * real driver could be loaded
+        */
+       for (i = 0; i < ARRAY_SIZE(genphy_driver); i++) {
+               if (phydev->dev.driver == &genphy_driver[i].driver) {
+                       device_release_driver(&phydev->dev);
+                       break;
+               }
+       }
 }
 EXPORT_SYMBOL(phy_detach);
 
@@ -724,17 +722,16 @@ static int genphy_config_advert(struct phy_device *phydev)
        int oldadv, adv;
        int err, changed = 0;
 
-       /* Only allow advertising what
-        * this PHY supports */
+       /* Only allow advertising what this PHY supports */
        phydev->advertising &= phydev->supported;
        advertise = phydev->advertising;
 
        /* Setup standard advertisement */
-       oldadv = adv = phy_read(phydev, MII_ADVERTISE);
-
+       adv = phy_read(phydev, MII_ADVERTISE);
        if (adv < 0)
                return adv;
 
+       oldadv = adv;
        adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
                 ADVERTISE_PAUSE_ASYM);
        adv |= ethtool_adv_to_mii_adv_t(advertise);
@@ -749,12 +746,12 @@ static int genphy_config_advert(struct phy_device *phydev)
 
        /* Configure gigabit if it's supported */
        if (phydev->supported & (SUPPORTED_1000baseT_Half |
-                               SUPPORTED_1000baseT_Full)) {
-               oldadv = adv = phy_read(phydev, MII_CTRL1000);
-
+                                SUPPORTED_1000baseT_Full)) {
+               adv = phy_read(phydev, MII_CTRL1000);
                if (adv < 0)
                        return adv;
 
+               oldadv = adv;
                adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
                adv |= ethtool_adv_to_mii_ctrl1000_t(advertise);
 
@@ -770,6 +767,12 @@ static int genphy_config_advert(struct phy_device *phydev)
        return changed;
 }
 
+int gen10g_config_advert(struct phy_device *dev)
+{
+       return 0;
+}
+EXPORT_SYMBOL(gen10g_config_advert);
+
 /**
  * genphy_setup_forced - configures/forces speed/duplex from @phydev
  * @phydev: target phy_device struct
@@ -780,10 +783,10 @@ static int genphy_config_advert(struct phy_device *phydev)
  */
 int genphy_setup_forced(struct phy_device *phydev)
 {
-       int err;
        int ctl = 0;
 
-       phydev->pause = phydev->asym_pause = 0;
+       phydev->pause = 0;
+       phydev->asym_pause = 0;
 
        if (SPEED_1000 == phydev->speed)
                ctl |= BMCR_SPEED1000;
@@ -793,9 +796,7 @@ int genphy_setup_forced(struct phy_device *phydev)
        if (DUPLEX_FULL == phydev->duplex)
                ctl |= BMCR_FULLDPLX;
 
-       err = phy_write(phydev, MII_BMCR, ctl);
-
-       return err;
+       return phy_write(phydev, MII_BMCR, ctl);
 }
 EXPORT_SYMBOL(genphy_setup_forced);
 
@@ -805,24 +806,25 @@ EXPORT_SYMBOL(genphy_setup_forced);
  */
 int genphy_restart_aneg(struct phy_device *phydev)
 {
-       int ctl;
-
-       ctl = phy_read(phydev, MII_BMCR);
+       int ctl = phy_read(phydev, MII_BMCR);
 
        if (ctl < 0)
                return ctl;
 
-       ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+       ctl |= BMCR_ANENABLE | BMCR_ANRESTART;
 
        /* Don't isolate the PHY if we're negotiating */
-       ctl &= ~(BMCR_ISOLATE);
-
-       ctl = phy_write(phydev, MII_BMCR, ctl);
+       ctl &= ~BMCR_ISOLATE;
 
-       return ctl;
+       return phy_write(phydev, MII_BMCR, ctl);
 }
 EXPORT_SYMBOL(genphy_restart_aneg);
 
+int gen10g_restart_aneg(struct phy_device *phydev)
+{
+       return 0;
+}
+EXPORT_SYMBOL(gen10g_restart_aneg);
 
 /**
  * genphy_config_aneg - restart auto-negotiation or write BMCR
@@ -840,13 +842,12 @@ int genphy_config_aneg(struct phy_device *phydev)
                return genphy_setup_forced(phydev);
 
        result = genphy_config_advert(phydev);
-
        if (result < 0) /* error */
                return result;
-
        if (result == 0) {
                /* Advertisement hasn't changed, but maybe aneg was never on to
-                * begin with?  Or maybe phy was isolated? */
+                * begin with?  Or maybe phy was isolated?
+                */
                int ctl = phy_read(phydev, MII_BMCR);
 
                if (ctl < 0)
@@ -857,7 +858,8 @@ int genphy_config_aneg(struct phy_device *phydev)
        }
 
        /* Only restart aneg if we are advertising something different
-        * than we were before.  */
+        * than we were before.
+        */
        if (result > 0)
                result = genphy_restart_aneg(phydev);
 
@@ -865,6 +867,12 @@ int genphy_config_aneg(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(genphy_config_aneg);
 
+int gen10g_config_aneg(struct phy_device *phydev)
+{
+       return 0;
+}
+EXPORT_SYMBOL(gen10g_config_aneg);
+
 /**
  * genphy_update_link - update link status in @phydev
  * @phydev: target phy_device struct
@@ -879,13 +887,11 @@ int genphy_update_link(struct phy_device *phydev)
 
        /* Do a fake read */
        status = phy_read(phydev, MII_BMSR);
-
        if (status < 0)
                return status;
 
        /* Read link and autonegotiation status */
        status = phy_read(phydev, MII_BMSR);
-
        if (status < 0)
                return status;
 
@@ -914,8 +920,7 @@ int genphy_read_status(struct phy_device *phydev)
        int lpa;
        int lpagb = 0;
 
-       /* Update the link, but return if there
-        * was an error */
+       /* Update the link, but return if there was an error */
        err = genphy_update_link(phydev);
        if (err)
                return err;
@@ -926,12 +931,10 @@ int genphy_read_status(struct phy_device *phydev)
                if (phydev->supported & (SUPPORTED_1000baseT_Half
                                        | SUPPORTED_1000baseT_Full)) {
                        lpagb = phy_read(phydev, MII_STAT1000);
-
                        if (lpagb < 0)
                                return lpagb;
 
                        adv = phy_read(phydev, MII_CTRL1000);
-
                        if (adv < 0)
                                return adv;
 
@@ -941,14 +944,12 @@ int genphy_read_status(struct phy_device *phydev)
                }
 
                lpa = phy_read(phydev, MII_LPA);
-
                if (lpa < 0)
                        return lpa;
 
                phydev->lp_advertising |= mii_lpa_to_ethtool_lpa_t(lpa);
 
                adv = phy_read(phydev, MII_ADVERTISE);
-
                if (adv < 0)
                        return adv;
 
@@ -956,7 +957,8 @@ int genphy_read_status(struct phy_device *phydev)
 
                phydev->speed = SPEED_10;
                phydev->duplex = DUPLEX_HALF;
-               phydev->pause = phydev->asym_pause = 0;
+               phydev->pause = 0;
+               phydev->asym_pause = 0;
 
                if (lpagb & (LPA_1000FULL | LPA_1000HALF)) {
                        phydev->speed = SPEED_1000;
@@ -978,6 +980,7 @@ int genphy_read_status(struct phy_device *phydev)
                }
        } else {
                int bmcr = phy_read(phydev, MII_BMCR);
+
                if (bmcr < 0)
                        return bmcr;
 
@@ -993,27 +996,56 @@ int genphy_read_status(struct phy_device *phydev)
                else
                        phydev->speed = SPEED_10;
 
-               phydev->pause = phydev->asym_pause = 0;
+               phydev->pause = 0;
+               phydev->asym_pause = 0;
        }
 
        return 0;
 }
 EXPORT_SYMBOL(genphy_read_status);
 
+int gen10g_read_status(struct phy_device *phydev)
+{
+       int devad, reg;
+       u32 mmd_mask = phydev->c45_ids.devices_in_package;
+
+       phydev->link = 1;
+
+       /* For now just lie and say it's 10G all the time */
+       phydev->speed = SPEED_10000;
+       phydev->duplex = DUPLEX_FULL;
+
+       for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) {
+               if (!(mmd_mask & 1))
+                       continue;
+
+               /* Read twice because link state is latched and a
+                * read moves the current state into the register
+                */
+               phy_read_mmd(phydev, devad, MDIO_STAT1);
+               reg = phy_read_mmd(phydev, devad, MDIO_STAT1);
+               if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
+                       phydev->link = 0;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(gen10g_read_status);
+
 static int genphy_config_init(struct phy_device *phydev)
 {
        int val;
        u32 features;
 
        /* For now, I'll claim that the generic driver supports
-        * all possible port types */
+        * all possible port types
+        */
        features = (SUPPORTED_TP | SUPPORTED_MII
                        | SUPPORTED_AUI | SUPPORTED_FIBRE |
                        SUPPORTED_BNC);
 
        /* Do we support autonegotiation? */
        val = phy_read(phydev, MII_BMSR);
-
        if (val < 0)
                return val;
 
@@ -1031,7 +1063,6 @@ static int genphy_config_init(struct phy_device *phydev)
 
        if (val & BMSR_ESTATEN) {
                val = phy_read(phydev, MII_ESTATUS);
-
                if (val < 0)
                        return val;
 
@@ -1046,6 +1077,16 @@ static int genphy_config_init(struct phy_device *phydev)
 
        return 0;
 }
+
+static int gen10g_config_init(struct phy_device *phydev)
+{
+       /* Temporarily just say we support everything */
+       phydev->supported = SUPPORTED_10000baseT_Full;
+       phydev->advertising = SUPPORTED_10000baseT_Full;
+
+       return 0;
+}
+
 int genphy_suspend(struct phy_device *phydev)
 {
        int value;
@@ -1053,7 +1094,7 @@ int genphy_suspend(struct phy_device *phydev)
        mutex_lock(&phydev->lock);
 
        value = phy_read(phydev, MII_BMCR);
-       phy_write(phydev, MII_BMCR, (value | BMCR_PDOWN));
+       phy_write(phydev, MII_BMCR, value | BMCR_PDOWN);
 
        mutex_unlock(&phydev->lock);
 
@@ -1061,6 +1102,12 @@ int genphy_suspend(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(genphy_suspend);
 
+int gen10g_suspend(struct phy_device *phydev)
+{
+       return 0;
+}
+EXPORT_SYMBOL(gen10g_suspend);
+
 int genphy_resume(struct phy_device *phydev)
 {
        int value;
@@ -1068,7 +1115,7 @@ int genphy_resume(struct phy_device *phydev)
        mutex_lock(&phydev->lock);
 
        value = phy_read(phydev, MII_BMCR);
-       phy_write(phydev, MII_BMCR, (value & ~BMCR_PDOWN));
+       phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN);
 
        mutex_unlock(&phydev->lock);
 
@@ -1076,6 +1123,12 @@ int genphy_resume(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(genphy_resume);
 
+int gen10g_resume(struct phy_device *phydev)
+{
+       return 0;
+}
+EXPORT_SYMBOL(gen10g_resume);
+
 /**
  * phy_probe - probe and init a PHY device
  * @dev: device to probe and init
@@ -1086,22 +1139,18 @@ EXPORT_SYMBOL(genphy_resume);
  */
 static int phy_probe(struct device *dev)
 {
-       struct phy_device *phydev;
-       struct phy_driver *phydrv;
-       struct device_driver *drv;
+       struct phy_device *phydev = to_phy_device(dev);
+       struct device_driver *drv = phydev->dev.driver;
+       struct phy_driver *phydrv = to_phy_driver(drv);
        int err = 0;
 
-       phydev = to_phy_device(dev);
-
-       drv = phydev->dev.driver;
-       phydrv = to_phy_driver(drv);
        phydev->drv = phydrv;
 
        /* Disable the interrupt if the PHY doesn't support it
         * but the interrupt is still a valid one
         */
        if (!(phydrv->flags & PHY_HAS_INTERRUPT) &&
-                       phy_interrupt_is_valid(phydev))
+           phy_interrupt_is_valid(phydev))
                phydev->irq = PHY_POLL;
 
        if (phydrv->flags & PHY_IS_INTERNAL)
@@ -1111,7 +1160,8 @@ static int phy_probe(struct device *dev)
 
        /* Start out supporting everything. Eventually,
         * a controller will attach, and may modify one
-        * or both of these values */
+        * or both of these values
+        */
        phydev->supported = phydrv->features;
        phydev->advertising = phydrv->features;
 
@@ -1124,14 +1174,11 @@ static int phy_probe(struct device *dev)
        mutex_unlock(&phydev->lock);
 
        return err;
-
 }
 
 static int phy_remove(struct device *dev)
 {
-       struct phy_device *phydev;
-
-       phydev = to_phy_device(dev);
+       struct phy_device *phydev = to_phy_device(dev);
 
        mutex_lock(&phydev->lock);
        phydev->state = PHY_DOWN;
@@ -1158,7 +1205,6 @@ int phy_driver_register(struct phy_driver *new_driver)
        new_driver->driver.remove = phy_remove;
 
        retval = driver_register(&new_driver->driver);
-
        if (retval) {
                pr_err("%s: Error %d in registering driver\n",
                       new_driver->name, retval);
@@ -1197,13 +1243,14 @@ EXPORT_SYMBOL(phy_driver_unregister);
 void phy_drivers_unregister(struct phy_driver *drv, int n)
 {
        int i;
-       for (i = 0; i < n; i++) {
+
+       for (i = 0; i < n; i++)
                phy_driver_unregister(drv + i);
-       }
 }
 EXPORT_SYMBOL(phy_drivers_unregister);
 
-static struct phy_driver genphy_driver = {
+static struct phy_driver genphy_driver[] = {
+{
        .phy_id         = 0xffffffff,
        .phy_id_mask    = 0xffffffff,
        .name           = "Generic PHY",
@@ -1214,7 +1261,18 @@ static struct phy_driver genphy_driver = {
        .suspend        = genphy_suspend,
        .resume         = genphy_resume,
        .driver         = { .owner = THIS_MODULE, },
-};
+}, {
+       .phy_id         = 0xffffffff,
+       .phy_id_mask    = 0xffffffff,
+       .name           = "Generic 10G PHY",
+       .config_init    = gen10g_config_init,
+       .features       = 0,
+       .config_aneg    = gen10g_config_aneg,
+       .read_status    = gen10g_read_status,
+       .suspend        = gen10g_suspend,
+       .resume         = gen10g_resume,
+       .driver         = {.owner = THIS_MODULE, },
+} };
 
 static int __init phy_init(void)
 {
@@ -1224,7 +1282,8 @@ static int __init phy_init(void)
        if (rc)
                return rc;
 
-       rc = phy_driver_register(&genphy_driver);
+       rc = phy_drivers_register(genphy_driver,
+                                 ARRAY_SIZE(genphy_driver));
        if (rc)
                mdio_bus_exit();
 
@@ -1233,7 +1292,8 @@ static int __init phy_init(void)
 
 static void __exit phy_exit(void)
 {
-       phy_driver_unregister(&genphy_driver);
+       phy_drivers_unregister(genphy_driver,
+                              ARRAY_SIZE(genphy_driver));
        mdio_bus_exit();
 }
 
index 7b4ff35c8bf7dcb28b455fb3a578eacddb298900..040b8978d6cac54812e8f253a23f498340bc2acd 100644 (file)
@@ -547,9 +547,9 @@ static __be16 plip_type_trans(struct sk_buff *skb, struct net_device *dev)
        skb_pull(skb,dev->hard_header_len);
        eth = eth_hdr(skb);
 
-       if(*eth->h_dest&1)
+       if(is_multicast_ether_addr(eth->h_dest))
        {
-               if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
+               if(ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
                        skb->pkt_type=PACKET_BROADCAST;
                else
                        skb->pkt_type=PACKET_MULTICAST;
index 82ee6ed954cb84272aa41be0fa3ad12eb6c64e2c..2ea7efd118577169f52c8b353148e53a8a00b8b1 100644 (file)
@@ -131,12 +131,12 @@ static inline struct pppoe_net *pppoe_pernet(struct net *net)
 
 static inline int cmp_2_addr(struct pppoe_addr *a, struct pppoe_addr *b)
 {
-       return a->sid == b->sid && !memcmp(a->remote, b->remote, ETH_ALEN);
+       return a->sid == b->sid && ether_addr_equal(a->remote, b->remote);
 }
 
 static inline int cmp_addr(struct pppoe_addr *a, __be16 sid, char *addr)
 {
-       return a->sid == sid && !memcmp(a->remote, addr, ETH_ALEN);
+       return a->sid == sid && ether_addr_equal(a->remote, addr);
 }
 
 #if 8 % PPPOE_HASH_BITS
index a17a7018db19a7870ef575e408b4dba0511f0f03..09f66624eaca1eea40793f4c6c5c057f837a2e20 100644 (file)
@@ -152,6 +152,7 @@ struct tun_flow_entry {
        struct tun_struct *tun;
 
        u32 rxhash;
+       u32 rps_rxhash;
        int queue_index;
        unsigned long updated;
 };
@@ -220,6 +221,7 @@ static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun,
                          rxhash, queue_index);
                e->updated = jiffies;
                e->rxhash = rxhash;
+               e->rps_rxhash = 0;
                e->queue_index = queue_index;
                e->tun = tun;
                hlist_add_head_rcu(&e->hash_link, head);
@@ -232,6 +234,7 @@ static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e)
 {
        tun_debug(KERN_INFO, tun, "delete flow: hash %u index %u\n",
                  e->rxhash, e->queue_index);
+       sock_rps_reset_flow_hash(e->rps_rxhash);
        hlist_del_rcu(&e->hash_link);
        kfree_rcu(e, rcu);
        --tun->flow_count;
@@ -325,6 +328,7 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
                /* TODO: keep queueing to old queue until it's empty? */
                e->queue_index = queue_index;
                e->updated = jiffies;
+               sock_rps_record_flow_hash(e->rps_rxhash);
        } else {
                spin_lock_bh(&tun->lock);
                if (!tun_flow_find(head, rxhash) &&
@@ -341,6 +345,18 @@ unlock:
        rcu_read_unlock();
 }
 
+/**
+ * Save the hash received in the stack receive path and update the
+ * flow_hash table accordingly.
+ */
+static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash)
+{
+       if (unlikely(e->rps_rxhash != hash)) {
+               sock_rps_reset_flow_hash(e->rps_rxhash);
+               e->rps_rxhash = hash;
+       }
+}
+
 /* We try to identify a flow through its rxhash first. The reason that
  * we do not check rxq no. is because some cards(e.g 82599), chooses
  * the rxq based on the txq where the last packet of the flow comes. As
@@ -361,9 +377,10 @@ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
        txq = skb_get_hash(skb);
        if (txq) {
                e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);
-               if (e)
+               if (e) {
+                       tun_flow_save_rps_rxhash(e, txq);
                        txq = e->queue_index;
-               else
+               else
                        /* use multiply and shift instead of expensive divide */
                        txq = ((u64)txq * numqueues) >> 32;
        } else if (likely(skb_rx_queue_recorded(skb))) {
@@ -728,6 +745,22 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
        if (txq >= tun->numqueues)
                goto drop;
 
+       if (tun->numqueues == 1) {
+               /* Select queue was not called for the skbuff, so we extract the
+                * RPS hash and save it into the flow_table here.
+                */
+               __u32 rxhash;
+
+               rxhash = skb_get_hash(skb);
+               if (rxhash) {
+                       struct tun_flow_entry *e;
+                       e = tun_flow_find(&tun->flows[tun_hashfn(rxhash)],
+                                       rxhash);
+                       if (e)
+                               tun_flow_save_rps_rxhash(e, rxhash);
+               }
+       }
+
        tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
 
        BUG_ON(!tfile);
index 85e4a01670f06e207609299ecacd035df3e098f3..47b0f732b0b10d21a07d4567e778efcbe4a7fddb 100644 (file)
@@ -276,12 +276,12 @@ config USB_NET_CDC_MBIM
          module will be called cdc_mbim.
 
 config USB_NET_DM9601
-       tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
+       tristate "Davicom DM96xx based USB 10/100 ethernet devices"
        depends on USB_USBNET
        select CRC32
        help
-         This option adds support for Davicom DM9601 based USB 1.1
-         10/100 Ethernet adapters.
+         This option adds support for Davicom DM9601/DM9620/DM9621A
+         based USB 10/100 Ethernet adapters.
 
 config USB_NET_SR9700
        tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices"
index 4b1c0f3f727da0d8061782dc1cf7d0c2caeeba6f..640406ac43585c3c253253bb992094aa4d93ee99 100644 (file)
@@ -486,6 +486,7 @@ static const struct driver_info wwan_info = {
 #define ZTE_VENDOR_ID          0x19D2
 #define DELL_VENDOR_ID         0x413C
 #define REALTEK_VENDOR_ID      0x0bda
+#define SAMSUNG_VENDOR_ID      0x04e8
 
 static const struct usb_device_id      products[] = {
 /* BLACKLIST !!
@@ -652,6 +653,15 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+#if defined(CONFIG_USB_RTL8152) || defined(CONFIG_USB_RTL8152_MODULE)
+/* Samsung USB Ethernet Adapters */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+#endif
+
 /* WHITELIST!!!
  *
  * CDC Ether uses two interfaces, not necessarily consecutive.
index c6867f926cffc18a981c7682e5493ae36924d988..14aa48fa8d7e5610087aee24b5eb0e493593cd83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices
+ * Davicom DM96xx USB 10/100Mbps ethernet devices
  *
  * Peter Korsgaard <jacmet@sunsite.dk>
  *
@@ -364,7 +364,12 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->ethtool_ops = &dm9601_ethtool_ops;
        dev->net->hard_header_len += DM_TX_OVERHEAD;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD;
+
+       /* dm9620/21a require room for 4 byte padding, even in dm9601
+        * mode, so we need +1 to be able to receive full size
+        * ethernet frames.
+        */
+       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1;
 
        dev->mii.dev = dev->net;
        dev->mii.mdio_read = dm9601_mdio_read;
@@ -468,7 +473,7 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
                                       gfp_t flags)
 {
-       int len;
+       int len, pad;
 
        /* format:
           b1: packet length low
@@ -476,12 +481,23 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
           b3..n: packet data
        */
 
-       len = skb->len;
+       len = skb->len + DM_TX_OVERHEAD;
+
+       /* workaround for dm962x errata with tx fifo getting out of
+        * sync if a USB bulk transfer retry happens right after a
+        * packet with odd / maxpacket length by adding up to 3 bytes
+        * padding.
+        */
+       while ((len & 1) || !(len % dev->maxpacket))
+               len++;
 
-       if (skb_headroom(skb) < DM_TX_OVERHEAD) {
+       len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */
+       pad = len - skb->len;
+
+       if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {
                struct sk_buff *skb2;
 
-               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags);
+               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);
                dev_kfree_skb_any(skb);
                skb = skb2;
                if (!skb)
@@ -490,10 +506,10 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 
        __skb_push(skb, DM_TX_OVERHEAD);
 
-       /* usbnet adds padding if length is a multiple of packet size
-          if so, adjust length value in header */
-       if ((skb->len % dev->maxpacket) == 0)
-               len++;
+       if (pad) {
+               memset(skb->data + skb->len, 0, pad);
+               __skb_put(skb, pad);
+       }
 
        skb->data[0] = len;
        skb->data[1] = len >> 8;
@@ -543,7 +559,7 @@ static int dm9601_link_reset(struct usbnet *dev)
 }
 
 static const struct driver_info dm9601_info = {
-       .description    = "Davicom DM9601 USB Ethernet",
+       .description    = "Davicom DM96xx USB 10/100 Ethernet",
        .flags          = FLAG_ETHER | FLAG_LINK_INTR,
        .bind           = dm9601_bind,
        .rx_fixup       = dm9601_rx_fixup,
@@ -594,6 +610,10 @@ static const struct usb_device_id products[] = {
         USB_DEVICE(0x0a46, 0x9620),    /* DM9620 USB to Fast Ethernet Adapter */
         .driver_info = (unsigned long)&dm9601_info,
         },
+       {
+        USB_DEVICE(0x0a46, 0x9621),    /* DM9621A USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
        {},                     // END
 };
 
@@ -612,5 +632,5 @@ static struct usb_driver dm9601_driver = {
 module_usb_driver(dm9601_driver);
 
 MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
-MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices");
+MODULE_DESCRIPTION("Davicom DM96xx USB 10/100 ethernet devices");
 MODULE_LICENSE("GPL");
index 86292e6aaf4955c4412ead6579f74e6848bcd089..1a482344b3f507e97486059d56280dfd3f23d37c 100644 (file)
@@ -185,7 +185,6 @@ enum rx_ctrl_state{
 #define BM_REQUEST_TYPE (0xa1)
 #define B_NOTIFICATION  (0x20)
 #define W_VALUE         (0x0)
-#define W_INDEX         (0x2)
 #define W_LENGTH        (0x2)
 
 #define B_OVERRUN       (0x1<<6)
@@ -1487,6 +1486,7 @@ static void tiocmget_intr_callback(struct urb *urb)
        struct uart_icount *icount;
        struct hso_serial_state_notification *serial_state_notification;
        struct usb_device *usb;
+       int if_num;
 
        /* Sanity checks */
        if (!serial)
@@ -1495,15 +1495,24 @@ static void tiocmget_intr_callback(struct urb *urb)
                handle_usb_error(status, __func__, serial->parent);
                return;
        }
+
+       /* tiocmget is only supported on HSO_PORT_MODEM */
        tiocmget = serial->tiocmget;
        if (!tiocmget)
                return;
+       BUG_ON((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM);
+
        usb = serial->parent->usb;
+       if_num = serial->parent->interface->altsetting->desc.bInterfaceNumber;
+
+       /* wIndex should be the USB interface number of the port to which the
+        * notification applies, which should always be the Modem port.
+        */
        serial_state_notification = &tiocmget->serial_state_notification;
        if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
            serial_state_notification->bNotification != B_NOTIFICATION ||
            le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
-           le16_to_cpu(serial_state_notification->wIndex) != W_INDEX ||
+           le16_to_cpu(serial_state_notification->wIndex) != if_num ||
            le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
                dev_warn(&usb->dev,
                         "hso received invalid serial state notification\n");
index aea68bc33583c88a32a42ee41fea24111b5e5a2a..36ff0019aa326ec675b7f7e580abd23d61ffbca1 100644 (file)
@@ -116,7 +116,6 @@ enum {
 struct mcs7830_data {
        u8 multi_filter[8];
        u8 config;
-       u8 link_counter;
 };
 
 static const char driver_name[] = "MOSCHIP usb-ethernet driver";
@@ -560,26 +559,16 @@ static void mcs7830_status(struct usbnet *dev, struct urb *urb)
 {
        u8 *buf = urb->transfer_buffer;
        bool link, link_changed;
-       struct mcs7830_data *data = mcs7830_get_data(dev);
 
        if (urb->actual_length < 16)
                return;
 
-       link = !(buf[1] & 0x20);
+       link = !(buf[1] == 0x20);
        link_changed = netif_carrier_ok(dev->net) != link;
        if (link_changed) {
-               data->link_counter++;
-               /*
-                  track link state 20 times to guard against erroneous
-                  link state changes reported sometimes by the chip
-                */
-               if (data->link_counter > 20) {
-                       data->link_counter = 0;
-                       usbnet_link_change(dev, link, 0);
-                       netdev_dbg(dev->net, "Link Status is: %d\n", link);
-               }
-       } else
-               data->link_counter = 0;
+               usbnet_link_change(dev, link, 0);
+               netdev_dbg(dev->net, "Link Status is: %d\n", link);
+       }
 }
 
 static const struct driver_info moschip_info = {
index 51073721e22400ef8a553ff153d240cf55789a68..bf7d549ab51114334edad8051d27b3e87381dca8 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/ipv6.h>
 
 /* Version Information */
-#define DRIVER_VERSION "v1.02.0 (2013/10/28)"
+#define DRIVER_VERSION "v1.03.0 (2013/12/26)"
 #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
 #define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters"
 #define MODULENAME "r8152"
 #define PLA_RXFIFO_CTRL2       0xc0a8
 #define PLA_FMC                        0xc0b4
 #define PLA_CFG_WOL            0xc0b6
+#define PLA_TEREDO_CFG         0xc0bc
 #define PLA_MAR                        0xcd00
+#define PLA_BACKUP             0xd000
 #define PAL_BDC_CR             0xd1a0
+#define PLA_TEREDO_TIMER       0xd2cc
+#define PLA_REALWOW_TIMER      0xd2e8
 #define PLA_LEDSEL             0xdd90
 #define PLA_LED_FEATURE                0xdd92
 #define PLA_PHYAR              0xde00
+#define PLA_BOOT_CTRL          0xe004
 #define PLA_GPHY_INTR_IMR      0xe022
 #define PLA_EEE_CR             0xe040
 #define PLA_EEEP_CR            0xe080
 #define PLA_MAC_PWR_CTRL       0xe0c0
+#define PLA_MAC_PWR_CTRL2      0xe0ca
+#define PLA_MAC_PWR_CTRL3      0xe0cc
+#define PLA_MAC_PWR_CTRL4      0xe0ce
+#define PLA_WDT6_CTRL          0xe428
 #define PLA_TCR0               0xe610
 #define PLA_TCR1               0xe612
 #define PLA_TXFIFO_CTRL                0xe618
 #define PLA_BP_5               0xfc32
 #define PLA_BP_6               0xfc34
 #define PLA_BP_7               0xfc36
+#define PLA_BP_EN              0xfc38
 
+#define USB_U2P3_CTRL          0xb460
 #define USB_DEV_STAT           0xb808
 #define USB_USB_CTRL           0xd406
 #define USB_PHY_CTRL           0xd408
 #define USB_TX_AGG             0xd40a
 #define USB_RX_BUF_TH          0xd40c
 #define USB_USB_TIMER          0xd428
+#define USB_RX_EARLY_AGG       0xd42c
 #define USB_PM_CTRL_STATUS     0xd432
 #define USB_TX_DMA             0xd434
+#define USB_TOLERANCE          0xd490
+#define USB_LPM_CTRL           0xd41a
 #define USB_UPS_CTRL           0xd800
+#define USB_MISC_0             0xd81a
+#define USB_POWER_CUT          0xd80a
+#define USB_AFE_CTRL2          0xd824
+#define USB_WDT11_CTRL         0xe43c
 #define USB_BP_BA              0xfc26
 #define USB_BP_0               0xfc28
 #define USB_BP_1               0xfc2a
 #define USB_BP_5               0xfc32
 #define USB_BP_6               0xfc34
 #define USB_BP_7               0xfc36
+#define USB_BP_EN              0xfc38
 
 /* OCP Registers */
 #define OCP_ALDPS_CONFIG       0x2010
 #define OCP_EEE_CONFIG1                0x2080
 #define OCP_EEE_CONFIG2                0x2092
 #define OCP_EEE_CONFIG3                0x2094
+#define OCP_BASE_MII           0xa400
 #define OCP_EEE_AR             0xa41a
 #define OCP_EEE_DATA           0xa41c
+#define OCP_PHY_STATUS         0xa420
+#define OCP_POWER_CFG          0xa430
+#define OCP_EEE_CFG            0xa432
+#define OCP_SRAM_ADDR          0xa436
+#define OCP_SRAM_DATA          0xa438
+#define OCP_DOWN_SPEED         0xa442
+#define OCP_EEE_CFG2           0xa5d0
+#define OCP_ADC_CFG            0xbc06
+
+/* SRAM Register */
+#define SRAM_LPF_CFG           0x8012
+#define SRAM_10M_AMP1          0x8080
+#define SRAM_10M_AMP2          0x8082
+#define SRAM_IMPEDANCE         0x8084
 
 /* PLA_RCR */
 #define RCR_AAP                        0x00000001
 #define RXFIFO_THR2_FULL       0x00000060
 #define RXFIFO_THR2_HIGH       0x00000038
 #define RXFIFO_THR2_OOB                0x0000004a
+#define RXFIFO_THR2_NORMAL     0x00a0
 
 /* PLA_RXFIFO_CTRL2 */
 #define RXFIFO_THR3_FULL       0x00000078
 #define RXFIFO_THR3_HIGH       0x00000048
 #define RXFIFO_THR3_OOB                0x0000005a
+#define RXFIFO_THR3_NORMAL     0x0110
 
 /* PLA_TXFIFO_CTRL */
 #define TXFIFO_THR_NORMAL      0x00400008
+#define TXFIFO_THR_NORMAL2     0x01000008
 
 /* PLA_FMC */
 #define FMC_FCR_MCU_EN         0x0001
 /* PLA_EEEP_CR */
 #define EEEP_CR_EEEP_TX                0x0002
 
+/* PLA_WDT6_CTRL */
+#define WDT6_SET_MODE          0x0010
+
 /* PLA_TCR0 */
 #define TCR0_TX_EMPTY          0x0800
 #define TCR0_AUTO_FIFO         0x0080
 /* PLA_CFG_WOL */
 #define MAGIC_EN               0x0001
 
+/* PLA_TEREDO_CFG */
+#define TEREDO_SEL             0x8000
+#define TEREDO_WAKE_MASK       0x7f00
+#define TEREDO_RS_EVENT_MASK   0x00fe
+#define OOB_TEREDO_EN          0x0001
+
 /* PAL_BDC_CR */
 #define ALDPS_PROXY_MODE       0x0001
 
 #define D3_CLK_GATED_EN                0x00004000
 #define MCU_CLK_RATIO          0x07010f07
 #define MCU_CLK_RATIO_MASK     0x0f0f0f0f
+#define ALDPS_SPDWN_RATIO      0x0f87
+
+/* PLA_MAC_PWR_CTRL2 */
+#define EEE_SPDWN_RATIO                0x8007
+
+/* PLA_MAC_PWR_CTRL3 */
+#define PKT_AVAIL_SPDWN_EN     0x0100
+#define SUSPEND_SPDWN_EN       0x0004
+#define U1U2_SPDWN_EN          0x0002
+#define L1_SPDWN_EN            0x0001
+
+/* PLA_MAC_PWR_CTRL4 */
+#define PWRSAVE_SPDWN_EN       0x1000
+#define RXDV_SPDWN_EN          0x0800
+#define TX10MIDLE_EN           0x0100
+#define TP100_SPDWN_EN         0x0020
+#define TP500_SPDWN_EN         0x0010
+#define TP1000_SPDWN_EN                0x0008
+#define EEE_SPDWN_EN           0x0001
 
 /* PLA_GPHY_INTR_IMR */
 #define GPHY_STS_MSK           0x0001
 #define EEE_RX_EN              0x0001
 #define EEE_TX_EN              0x0002
 
+/* PLA_BOOT_CTRL */
+#define AUTOLOAD_DONE          0x0002
+
 /* USB_DEV_STAT */
 #define STAT_SPEED_MASK                0x0006
 #define STAT_SPEED_HIGH                0x0000
 #define TX_AGG_MAX_THRESHOLD   0x03
 
 /* USB_RX_BUF_TH */
-#define RX_BUF_THR             0x7a120180
+#define RX_THR_SUPPER          0x0c350180
+#define RX_THR_HIGH            0x7a120180
+#define RX_THR_SLOW            0xffff0180
 
 /* USB_TX_DMA */
 #define TEST_MODE_DISABLE      0x00000001
 #define POWER_CUT              0x0100
 
 /* USB_PM_CTRL_STATUS */
-#define RWSUME_INDICATE                0x0001
+#define RESUME_INDICATE                0x0001
 
 /* USB_USB_CTRL */
 #define RX_AGG_DISABLE         0x0010
 
+/* USB_U2P3_CTRL */
+#define U2P3_ENABLE            0x0001
+
+/* USB_POWER_CUT */
+#define PWR_EN                 0x0001
+#define PHASE2_EN              0x0008
+
+/* USB_MISC_0 */
+#define PCUT_STATUS            0x0001
+
+/* USB_RX_EARLY_AGG */
+#define EARLY_AGG_SUPPER       0x0e832981
+#define EARLY_AGG_HIGH         0x0e837a12
+#define EARLY_AGG_SLOW         0x0e83ffff
+
+/* USB_WDT11_CTRL */
+#define TIMER11_EN             0x0001
+
+/* USB_LPM_CTRL */
+#define LPM_TIMER_MASK         0x0c
+#define LPM_TIMER_500MS                0x04    /* 500 ms */
+#define LPM_TIMER_500US                0x0c    /* 500 us */
+
+/* USB_AFE_CTRL2 */
+#define SEN_VAL_MASK           0xf800
+#define SEN_VAL_NORMAL         0xa000
+#define SEL_RXIDLE             0x0100
+
 /* OCP_ALDPS_CONFIG */
 #define ENPWRSAVE              0x8000
 #define ENPDNPS                        0x0200
 #define LINKENA                        0x0100
 #define DIS_SDSAVE             0x0010
 
+/* OCP_PHY_STATUS */
+#define PHY_STAT_MASK          0x0007
+#define PHY_STAT_LAN_ON                3
+#define PHY_STAT_PWRDN         5
+
+/* OCP_POWER_CFG */
+#define EEE_CLKDIV_EN          0x8000
+#define EN_ALDPS               0x0004
+#define EN_10M_PLLOFF          0x0001
+
 /* OCP_EEE_CONFIG1 */
 #define RG_TXLPI_MSK_HFDUP     0x8000
 #define RG_MATCLR_EN           0x4000
 #define EEE_ADDR               0x003C
 #define EEE_DATA               0x0002
 
+/* OCP_EEE_CFG */
+#define CTAP_SHORT_EN          0x0040
+#define EEE10_EN               0x0010
+
+/* OCP_DOWN_SPEED */
+#define EN_10M_BGOFF           0x0080
+
+/* OCP_EEE_CFG2 */
+#define MY1000_EEE             0x0004
+#define MY100_EEE              0x0002
+
+/* OCP_ADC_CFG */
+#define CKADSEL_L              0x0100
+#define ADC_EN                 0x0080
+#define EN_EMI_L               0x0040
+
+/* SRAM_LPF_CFG */
+#define LPF_AUTO_TUNE          0x8000
+
+/* SRAM_10M_AMP1 */
+#define GDAC_IB_UPALL          0x0008
+
+/* SRAM_10M_AMP2 */
+#define AMP_DN                 0x0200
+
+/* SRAM_IMPEDANCE */
+#define RX_DRIVING_MASK                0x6000
+
 enum rtl_register_content {
+       _1000bps        = 0x10,
        _100bps         = 0x08,
        _10bps          = 0x04,
        LINK_STATUS     = 0x02,
@@ -273,6 +410,9 @@ enum rtl_register_content {
 #define RTL8152_MAX_TX         10
 #define RTL8152_MAX_RX         10
 #define INTBUFSIZE             2
+#define CRC_SIZE               4
+#define TX_ALIGN               4
+#define RX_ALIGN               8
 
 #define INTR_LINK              0x0004
 
@@ -302,6 +442,10 @@ enum rtl8152_flags {
 /* Define these values to match your device */
 #define VENDOR_ID_REALTEK              0x0bda
 #define PRODUCT_ID_RTL8152             0x8152
+#define PRODUCT_ID_RTL8153             0x8153
+
+#define VENDOR_ID_SAMSUNG              0x04e8
+#define PRODUCT_ID_SAMSUNG             0xa101
 
 #define MCU_TYPE_PLA                   0x0100
 #define MCU_TYPE_USB                   0x0000
@@ -363,6 +507,15 @@ struct r8152 {
        spinlock_t rx_lock, tx_lock;
        struct delayed_work schedule;
        struct mii_if_info mii;
+
+       struct rtl_ops {
+               void (*init)(struct r8152 *);
+               int (*enable)(struct r8152 *);
+               void (*disable)(struct r8152 *);
+               void (*down)(struct r8152 *);
+               void (*unload)(struct r8152 *);
+       } rtl_ops;
+
        int intr_interval;
        u32 msg_enable;
        u32 tx_qlen;
@@ -375,7 +528,11 @@ struct r8152 {
 enum rtl_version {
        RTL_VER_UNKNOWN = 0,
        RTL_VER_01,
-       RTL_VER_02
+       RTL_VER_02,
+       RTL_VER_03,
+       RTL_VER_04,
+       RTL_VER_05,
+       RTL_VER_MAX
 };
 
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
@@ -427,8 +584,8 @@ int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
 static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
                                void *data, u16 type)
 {
-       u16     limit = 64;
-       int     ret = 0;
+       u16 limit = 64;
+       int ret = 0;
 
        if (test_bit(RTL8152_UNPLUG, &tp->flags))
                return -ENODEV;
@@ -467,9 +624,9 @@ static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
 static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
                                u16 size, void *data, u16 type)
 {
-       int     ret;
-       u16     byteen_start, byteen_end, byen;
-       u16     limit = 512;
+       int ret;
+       u16 byteen_start, byteen_end, byen;
+       u16 limit = 512;
 
        if (test_bit(RTL8152_UNPLUG, &tp->flags))
                return -ENODEV;
@@ -653,45 +810,54 @@ static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data)
        generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
 }
 
-static void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
+static u16 ocp_reg_read(struct r8152 *tp, u16 addr)
 {
-       u32     ocp_data;
-       int     i;
+       u16 ocp_base, ocp_index;
 
-       ocp_data = PHYAR_FLAG | ((reg_addr & 0x1f) << 16) |
-                  (value & 0xffff);
+       ocp_base = addr & 0xf000;
+       if (ocp_base != tp->ocp_base) {
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
+               tp->ocp_base = ocp_base;
+       }
 
-       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_PHYAR, ocp_data);
+       ocp_index = (addr & 0x0fff) | 0xb000;
+       return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);
+}
 
-       for (i = 20; i > 0; i--) {
-               udelay(25);
-               ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_PHYAR);
-               if (!(ocp_data & PHYAR_FLAG))
-                       break;
+static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
+{
+       u16 ocp_base, ocp_index;
+
+       ocp_base = addr & 0xf000;
+       if (ocp_base != tp->ocp_base) {
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
+               tp->ocp_base = ocp_base;
        }
-       udelay(20);
+
+       ocp_index = (addr & 0x0fff) | 0xb000;
+       ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
 }
 
-static int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
+static inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
 {
-       u32     ocp_data;
-       int     i;
-
-       ocp_data = (reg_addr & 0x1f) << 16;
-       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_PHYAR, ocp_data);
+       ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
+}
 
-       for (i = 20; i > 0; i--) {
-               udelay(25);
-               ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_PHYAR);
-               if (ocp_data & PHYAR_FLAG)
-                       break;
-       }
-       udelay(20);
+static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
+{
+       return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
+}
 
-       if (!(ocp_data & PHYAR_FLAG))
-               return -EAGAIN;
+static void sram_write(struct r8152 *tp, u16 addr, u16 data)
+{
+       ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
+       ocp_reg_write(tp, OCP_SRAM_DATA, data);
+}
 
-       return (u16)(ocp_data & 0xffff);
+static u16 sram_read(struct r8152 *tp, u16 addr)
+{
+       ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
+       return ocp_reg_read(tp, OCP_SRAM_DATA);
 }
 
 static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
@@ -715,20 +881,6 @@ void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val)
        r8152_mdio_write(tp, reg, val);
 }
 
-static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
-{
-       u16 ocp_base, ocp_index;
-
-       ocp_base = addr & 0xf000;
-       if (ocp_base != tp->ocp_base) {
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
-               tp->ocp_base = ocp_base;
-       }
-
-       ocp_index = (addr & 0x0fff) | 0xb000;
-       ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
-}
-
 static
 int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags);
 
@@ -814,10 +966,12 @@ static void read_bulk_callback(struct urb *urb)
        case -ENOENT:
                return; /* the urb is in unlink state */
        case -ETIME:
-               pr_warn_ratelimited("may be reset is needed?..\n");
+               if (net_ratelimit())
+                       netdev_warn(netdev, "maybe reset is needed?\n");
                break;
        default:
-               pr_warn_ratelimited("Rx status %d\n", status);
+               if (net_ratelimit())
+                       netdev_warn(netdev, "Rx status %d\n", status);
                break;
        }
 
@@ -850,7 +1004,8 @@ static void write_bulk_callback(struct urb *urb)
 
        stats = rtl8152_get_stats(tp->netdev);
        if (status) {
-               pr_warn_ratelimited("Tx status %d\n", status);
+               if (net_ratelimit())
+                       netdev_warn(tp->netdev, "Tx status %d\n", status);
                stats->tx_errors += agg->skb_num;
        } else {
                stats->tx_packets += agg->skb_num;
@@ -927,17 +1082,17 @@ resubmit:
                netif_device_detach(tp->netdev);
        else if (res)
                netif_err(tp, intr, tp->netdev,
-                       "can't resubmit intr, status %d\n", res);
+                         "can't resubmit intr, status %d\n", res);
 }
 
 static inline void *rx_agg_align(void *data)
 {
-       return (void *)ALIGN((uintptr_t)data, 8);
+       return (void *)ALIGN((uintptr_t)data, RX_ALIGN);
 }
 
 static inline void *tx_agg_align(void *data)
 {
-       return (void *)ALIGN((uintptr_t)data, 4);
+       return (void *)ALIGN((uintptr_t)data, TX_ALIGN);
 }
 
 static void free_all_mem(struct r8152 *tp)
@@ -1006,7 +1161,8 @@ static int alloc_all_mem(struct r8152 *tp)
 
                if (buf != rx_agg_align(buf)) {
                        kfree(buf);
-                       buf = kmalloc_node(rx_buf_sz + 8, GFP_KERNEL, node);
+                       buf = kmalloc_node(rx_buf_sz + RX_ALIGN, GFP_KERNEL,
+                                          node);
                        if (!buf)
                                goto err1;
                }
@@ -1031,7 +1187,8 @@ static int alloc_all_mem(struct r8152 *tp)
 
                if (buf != tx_agg_align(buf)) {
                        kfree(buf);
-                       buf = kmalloc_node(rx_buf_sz + 4, GFP_KERNEL, node);
+                       buf = kmalloc_node(rx_buf_sz + TX_ALIGN, GFP_KERNEL,
+                                          node);
                        if (!buf)
                                goto err1;
                }
@@ -1231,7 +1388,7 @@ static void rx_bottom(struct r8152 *tp)
 
                        stats = rtl8152_get_stats(netdev);
 
-                       pkt_len -= 4; /* CRC */
+                       pkt_len -= CRC_SIZE;
                        rx_data += sizeof(struct rx_desc);
 
                        skb = netdev_alloc_skb_ip_align(netdev, pkt_len);
@@ -1246,7 +1403,7 @@ static void rx_bottom(struct r8152 *tp)
                        stats->rx_packets++;
                        stats->rx_bytes += pkt_len;
 
-                       rx_data = rx_agg_align(rx_data + pkt_len + 4);
+                       rx_data = rx_agg_align(rx_data + pkt_len + CRC_SIZE);
                        rx_desc = (struct rx_desc *)rx_data;
                        len_used = (int)(rx_data - (u8 *)agg->head);
                        len_used += sizeof(struct rx_desc);
@@ -1336,7 +1493,7 @@ static void rtl8152_tx_timeout(struct net_device *netdev)
        struct r8152 *tp = netdev_priv(netdev);
        int i;
 
-       netif_warn(tp, tx_err, netdev, "Tx timeout.\n");
+       netif_warn(tp, tx_err, netdev, "Tx timeout\n");
        for (i = 0; i < RTL8152_MAX_TX; i++)
                usb_unlink_urb(tp->tx_info[i].urb);
 }
@@ -1449,13 +1606,11 @@ static inline u8 rtl8152_get_speed(struct r8152 *tp)
        return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS);
 }
 
-static int rtl8152_enable(struct r8152 *tp)
+static void rtl_set_eee_plus(struct r8152 *tp)
 {
        u32 ocp_data;
-       int i, ret;
        u8 speed;
 
-       set_tx_qlen(tp);
        speed = rtl8152_get_speed(tp);
        if (speed & _10bps) {
                ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
@@ -1466,6 +1621,12 @@ static int rtl8152_enable(struct r8152 *tp)
                ocp_data &= ~EEEP_CR_EEEP_TX;
                ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
        }
+}
+
+static int rtl_enable(struct r8152 *tp)
+{
+       u32 ocp_data;
+       int i, ret;
 
        r8152b_reset_packet_filter(tp);
 
@@ -1487,6 +1648,47 @@ static int rtl8152_enable(struct r8152 *tp)
        return ret;
 }
 
+static int rtl8152_enable(struct r8152 *tp)
+{
+       set_tx_qlen(tp);
+       rtl_set_eee_plus(tp);
+
+       return rtl_enable(tp);
+}
+
+static void r8153_set_rx_agg(struct r8152 *tp)
+{
+       u8 speed;
+
+       speed = rtl8152_get_speed(tp);
+       if (speed & _1000bps) {
+               if (tp->udev->speed == USB_SPEED_SUPER) {
+                       ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH,
+                                       RX_THR_SUPPER);
+                       ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_EARLY_AGG,
+                                       EARLY_AGG_SUPPER);
+               } else {
+                       ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH,
+                                       RX_THR_HIGH);
+                       ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_EARLY_AGG,
+                                       EARLY_AGG_HIGH);
+               }
+       } else {
+               ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_SLOW);
+               ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_EARLY_AGG,
+                               EARLY_AGG_SLOW);
+       }
+}
+
+static int rtl8153_enable(struct r8152 *tp)
+{
+       set_tx_qlen(tp);
+       rtl_set_eee_plus(tp);
+       r8153_set_rx_agg(tp);
+
+       return rtl_enable(tp);
+}
+
 static void rtl8152_disable(struct r8152 *tp)
 {
        struct net_device_stats *stats = rtl8152_get_stats(tp->netdev);
@@ -1596,7 +1798,7 @@ static void r8152b_exit_oob(struct r8152 *tp)
        ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL);
 
        ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD);
-       ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_BUF_THR);
+       ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH);
        ocp_write_dword(tp, MCU_TYPE_USB, USB_TX_DMA,
                        TEST_MODE_DISABLE | TX_SIZE_ADJUST1);
 
@@ -1613,8 +1815,8 @@ static void r8152b_exit_oob(struct r8152 *tp)
 
 static void r8152b_enter_oob(struct r8152 *tp)
 {
-       u32     ocp_data;
-       int     i;
+       u32 ocp_data;
+       int i;
 
        ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
        ocp_data &= ~NOW_IS_OOB;
@@ -1685,15 +1887,269 @@ static inline void r8152b_enable_aldps(struct r8152 *tp)
                                            LINKENA | DIS_SDSAVE);
 }
 
+static void r8153_hw_phy_cfg(struct r8152 *tp)
+{
+       u32 ocp_data;
+       u16 data;
+
+       ocp_reg_write(tp, OCP_ADC_CFG, CKADSEL_L | ADC_EN | EN_EMI_L);
+       r8152_mdio_write(tp, MII_BMCR, BMCR_ANENABLE);
+
+       if (tp->version == RTL_VER_03) {
+               data = ocp_reg_read(tp, OCP_EEE_CFG);
+               data &= ~CTAP_SHORT_EN;
+               ocp_reg_write(tp, OCP_EEE_CFG, data);
+       }
+
+       data = ocp_reg_read(tp, OCP_POWER_CFG);
+       data |= EEE_CLKDIV_EN;
+       ocp_reg_write(tp, OCP_POWER_CFG, data);
+
+       data = ocp_reg_read(tp, OCP_DOWN_SPEED);
+       data |= EN_10M_BGOFF;
+       ocp_reg_write(tp, OCP_DOWN_SPEED, data);
+       data = ocp_reg_read(tp, OCP_POWER_CFG);
+       data |= EN_10M_PLLOFF;
+       ocp_reg_write(tp, OCP_POWER_CFG, data);
+       data = sram_read(tp, SRAM_IMPEDANCE);
+       data &= ~RX_DRIVING_MASK;
+       sram_write(tp, SRAM_IMPEDANCE, data);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
+       ocp_data |= PFM_PWM_SWITCH;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
+
+       data = sram_read(tp, SRAM_LPF_CFG);
+       data |= LPF_AUTO_TUNE;
+       sram_write(tp, SRAM_LPF_CFG, data);
+
+       data = sram_read(tp, SRAM_10M_AMP1);
+       data |= GDAC_IB_UPALL;
+       sram_write(tp, SRAM_10M_AMP1, data);
+       data = sram_read(tp, SRAM_10M_AMP2);
+       data |= AMP_DN;
+       sram_write(tp, SRAM_10M_AMP2, data);
+}
+
+static void r8153_u1u2en(struct r8152 *tp, int enable)
+{
+       u8 u1u2[8];
+
+       if (enable)
+               memset(u1u2, 0xff, sizeof(u1u2));
+       else
+               memset(u1u2, 0x00, sizeof(u1u2));
+
+       usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2);
+}
+
+static void r8153_u2p3en(struct r8152 *tp, int enable)
+{
+       u32 ocp_data;
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL);
+       if (enable)
+               ocp_data |= U2P3_ENABLE;
+       else
+               ocp_data &= ~U2P3_ENABLE;
+       ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
+}
+
+static void r8153_power_cut_en(struct r8152 *tp, int enable)
+{
+       u32 ocp_data;
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT);
+       if (enable)
+               ocp_data |= PWR_EN | PHASE2_EN;
+       else
+               ocp_data &= ~(PWR_EN | PHASE2_EN);
+       ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
+       ocp_data &= ~PCUT_STATUS;
+       ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
+}
+
+static void r8153_teredo_off(struct r8152 *tp)
+{
+       u32 ocp_data;
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
+       ocp_data &= ~(TEREDO_SEL | TEREDO_RS_EVENT_MASK | OOB_TEREDO_EN);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
+
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_REALWOW_TIMER, 0);
+       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TEREDO_TIMER, 0);
+}
+
+static void r8153_first_init(struct r8152 *tp)
+{
+       u32 ocp_data;
+       int i;
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
+       ocp_data |= RXDY_GATED_EN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
+
+       r8153_teredo_off(tp);
+
+       ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
+       ocp_data &= ~RCR_ACPT_ALL;
+       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
+
+       r8153_hw_phy_cfg(tp);
+
+       rtl8152_nic_reset(tp);
+
+       ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+       ocp_data &= ~NOW_IS_OOB;
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
+       ocp_data &= ~MCU_BORW_EN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
+
+       for (i = 0; i < 1000; i++) {
+               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+               if (ocp_data & LINK_LIST_READY)
+                       break;
+               mdelay(1);
+       }
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
+       ocp_data |= RE_INIT_LL;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
+
+       for (i = 0; i < 1000; i++) {
+               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+               if (ocp_data & LINK_LIST_READY)
+                       break;
+               mdelay(1);
+       }
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
+       ocp_data &= ~CPCR_RX_VLAN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
+
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
+       ocp_data |= TCR0_AUTO_FIFO;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
+
+       rtl8152_nic_reset(tp);
+
+       /* rx share fifo credit full threshold */
+       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_NORMAL);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL);
+       /* TX share fifo free credit full threshold */
+       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2);
+
+       // rx aggregation
+       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
+       ocp_data &= ~RX_AGG_DISABLE;
+       ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
+}
+
+static void r8153_enter_oob(struct r8152 *tp)
+{
+       u32 ocp_data;
+       int i;
+
+       ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+       ocp_data &= ~NOW_IS_OOB;
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
+
+       rtl8152_disable(tp);
+
+       for (i = 0; i < 1000; i++) {
+               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+               if (ocp_data & LINK_LIST_READY)
+                       break;
+               mdelay(1);
+       }
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
+       ocp_data |= RE_INIT_LL;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
+
+       for (i = 0; i < 1000; i++) {
+               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+               if (ocp_data & LINK_LIST_READY)
+                       break;
+               mdelay(1);
+       }
+
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
+       ocp_data |= MAGIC_EN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
+       ocp_data &= ~TEREDO_WAKE_MASK;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
+       ocp_data |= CPCR_RX_VLAN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
+       ocp_data |= ALDPS_PROXY_MODE;
+       ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
+
+       ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+       ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
+
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5, LAN_WAKE_EN);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
+       ocp_data &= ~RXDY_GATED_EN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
+
+       ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
+       ocp_data |= RCR_APM | RCR_AM | RCR_AB;
+       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
+}
+
+static void r8153_disable_aldps(struct r8152 *tp)
+{
+       u16 data;
+
+       data = ocp_reg_read(tp, OCP_POWER_CFG);
+       data &= ~EN_ALDPS;
+       ocp_reg_write(tp, OCP_POWER_CFG, data);
+       msleep(20);
+}
+
+static void r8153_enable_aldps(struct r8152 *tp)
+{
+       u16 data;
+
+       data = ocp_reg_read(tp, OCP_POWER_CFG);
+       data |= EN_ALDPS;
+       ocp_reg_write(tp, OCP_POWER_CFG, data);
+}
+
 static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
 {
-       u16 bmcr, anar;
+       u16 bmcr, anar, gbcr;
        int ret = 0;
 
        cancel_delayed_work_sync(&tp->schedule);
        anar = r8152_mdio_read(tp, MII_ADVERTISE);
        anar &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
                  ADVERTISE_100HALF | ADVERTISE_100FULL);
+       if (tp->mii.supports_gmii) {
+               gbcr = r8152_mdio_read(tp, MII_CTRL1000);
+               gbcr &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+       } else {
+               gbcr = 0;
+       }
 
        if (autoneg == AUTONEG_DISABLE) {
                if (speed == SPEED_10) {
@@ -1702,6 +2158,9 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
                } else if (speed == SPEED_100) {
                        bmcr = BMCR_SPEED100;
                        anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
+               } else if (speed == SPEED_1000 && tp->mii.supports_gmii) {
+                       bmcr = BMCR_SPEED1000;
+                       gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
                } else {
                        ret = -EINVAL;
                        goto out;
@@ -1723,6 +2182,16 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
                                anar |= ADVERTISE_10HALF;
                                anar |= ADVERTISE_100HALF;
                        }
+               } else if (speed == SPEED_1000 && tp->mii.supports_gmii) {
+                       if (duplex == DUPLEX_FULL) {
+                               anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
+                               anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
+                               gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
+                       } else {
+                               anar |= ADVERTISE_10HALF;
+                               anar |= ADVERTISE_100HALF;
+                               gbcr |= ADVERTISE_1000HALF;
+                       }
                } else {
                        ret = -EINVAL;
                        goto out;
@@ -1731,6 +2200,9 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
                bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
        }
 
+       if (tp->mii.supports_gmii)
+               r8152_mdio_write(tp, MII_CTRL1000, gbcr);
+
        r8152_mdio_write(tp, MII_ADVERTISE, anar);
        r8152_mdio_write(tp, MII_BMCR, bmcr);
 
@@ -1752,6 +2224,15 @@ static void rtl8152_down(struct r8152 *tp)
        r8152b_enable_aldps(tp);
 }
 
+static void rtl8153_down(struct r8152 *tp)
+{
+       r8153_u1u2en(tp, 0);
+       r8153_power_cut_en(tp, 0);
+       r8153_disable_aldps(tp);
+       r8153_enter_oob(tp);
+       r8153_enable_aldps(tp);
+}
+
 static void set_carrier(struct r8152 *tp)
 {
        struct net_device *netdev = tp->netdev;
@@ -1762,7 +2243,7 @@ static void set_carrier(struct r8152 *tp)
 
        if (speed & LINK_STATUS) {
                if (!(tp->speed & LINK_STATUS)) {
-                       rtl8152_enable(tp);
+                       tp->rtl_ops.enable(tp);
                        set_bit(RTL8152_SET_RX_MODE, &tp->flags);
                        netif_carrier_on(netdev);
                }
@@ -1770,7 +2251,7 @@ static void set_carrier(struct r8152 *tp)
                if (tp->speed & LINK_STATUS) {
                        netif_carrier_off(netdev);
                        tasklet_disable(&tp->tl);
-                       rtl8152_disable(tp);
+                       tp->rtl_ops.disable(tp);
                        tasklet_enable(&tp->tl);
                }
        }
@@ -1806,12 +2287,14 @@ static int rtl8152_open(struct net_device *netdev)
        if (res) {
                if (res == -ENODEV)
                        netif_device_detach(tp->netdev);
-               netif_warn(tp, ifup, netdev,
-                       "intr_urb submit failed: %d\n", res);
+               netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n",
+                          res);
                return res;
        }
 
-       rtl8152_set_speed(tp, AUTONEG_ENABLE, SPEED_100, DUPLEX_FULL);
+       rtl8152_set_speed(tp, AUTONEG_ENABLE,
+                         tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
+                         DUPLEX_FULL);
        tp->speed = 0;
        netif_carrier_off(netdev);
        netif_start_queue(netdev);
@@ -1830,7 +2313,7 @@ static int rtl8152_close(struct net_device *netdev)
        cancel_delayed_work_sync(&tp->schedule);
        netif_stop_queue(netdev);
        tasklet_disable(&tp->tl);
-       rtl8152_disable(tp);
+       tp->rtl_ops.disable(tp);
        tasklet_enable(&tp->tl);
 
        return res;
@@ -1851,9 +2334,16 @@ static void rtl_clear_bp(struct r8152 *tp)
        ocp_write_word(tp, MCU_TYPE_USB, USB_BP_BA, 0);
 }
 
+static void r8153_clear_bp(struct r8152 *tp)
+{
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0);
+       ocp_write_byte(tp, MCU_TYPE_USB, USB_BP_EN, 0);
+       rtl_clear_bp(tp);
+}
+
 static void r8152b_enable_eee(struct r8152 *tp)
 {
-       u32     ocp_data;
+       u32 ocp_data;
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
        ocp_data |= EEE_RX_EN | EEE_TX_EN;
@@ -1874,6 +2364,22 @@ static void r8152b_enable_eee(struct r8152 *tp)
        ocp_reg_write(tp, OCP_EEE_AR, 0x0000);
 }
 
+static void r8153_enable_eee(struct r8152 *tp)
+{
+       u32 ocp_data;
+       u16 data;
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
+       ocp_data |= EEE_RX_EN | EEE_TX_EN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data);
+       data = ocp_reg_read(tp, OCP_EEE_CFG);
+       data |= EEE10_EN;
+       ocp_reg_write(tp, OCP_EEE_CFG, data);
+       data = ocp_reg_read(tp, OCP_EEE_CFG2);
+       data |= MY1000_EEE | MY100_EEE;
+       ocp_reg_write(tp, OCP_EEE_CFG2, data);
+}
+
 static void r8152b_enable_fc(struct r8152 *tp)
 {
        u16 anar;
@@ -1909,7 +2415,7 @@ static void r8152b_init(struct r8152 *tp)
        ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
-       ocp_data &= ~RWSUME_INDICATE;
+       ocp_data &= ~RESUME_INDICATE;
        ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
 
        r8152b_exit_oob(tp);
@@ -1943,6 +2449,75 @@ static void r8152b_init(struct r8152 *tp)
        ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
 }
 
+static void r8153_init(struct r8152 *tp)
+{
+       u32 ocp_data;
+       int i;
+
+       r8153_u1u2en(tp, 0);
+
+       for (i = 0; i < 500; i++) {
+               if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
+                   AUTOLOAD_DONE)
+                       break;
+               msleep(20);
+       }
+
+       for (i = 0; i < 500; i++) {
+               ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK;
+               if (ocp_data == PHY_STAT_LAN_ON || ocp_data == PHY_STAT_PWRDN)
+                       break;
+               msleep(20);
+       }
+
+       r8153_u2p3en(tp, 0);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL);
+       ocp_data &= ~TIMER11_EN;
+       ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data);
+
+       r8153_clear_bp(tp);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
+       ocp_data &= ~LED_MODE_MASK;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
+
+       ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL);
+       ocp_data &= ~LPM_TIMER_MASK;
+       if (tp->udev->speed == USB_SPEED_SUPER)
+               ocp_data |= LPM_TIMER_500US;
+       else
+               ocp_data |= LPM_TIMER_500MS;
+       ocp_write_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL, ocp_data);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2);
+       ocp_data &= ~SEN_VAL_MASK;
+       ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE;
+       ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data);
+
+       r8153_power_cut_en(tp, 0);
+       r8153_u1u2en(tp, 1);
+
+       r8153_first_init(tp);
+
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ALDPS_SPDWN_RATIO);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, EEE_SPDWN_RATIO);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
+                      PKT_AVAIL_SPDWN_EN | SUSPEND_SPDWN_EN |
+                      U1U2_SPDWN_EN | L1_SPDWN_EN);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
+                      PWRSAVE_SPDWN_EN | RXDV_SPDWN_EN | TX10MIDLE_EN |
+                      TP100_SPDWN_EN | TP500_SPDWN_EN | TP1000_SPDWN_EN |
+                      EEE_SPDWN_EN);
+
+       r8153_enable_eee(tp);
+       r8153_enable_aldps(tp);
+       r8152b_enable_fc(tp);
+
+       r8152_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE |
+                                      BMCR_ANRESTART);
+}
+
 static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct r8152 *tp = usb_get_intfdata(intf);
@@ -1956,7 +2531,7 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
                tasklet_disable(&tp->tl);
        }
 
-       rtl8152_down(tp);
+       tp->rtl_ops.down(tp);
 
        return 0;
 }
@@ -1965,10 +2540,12 @@ static int rtl8152_resume(struct usb_interface *intf)
 {
        struct r8152 *tp = usb_get_intfdata(intf);
 
-       r8152b_init(tp);
+       tp->rtl_ops.init(tp);
        netif_device_attach(tp->netdev);
        if (netif_running(tp->netdev)) {
-               rtl8152_set_speed(tp, AUTONEG_ENABLE, SPEED_100, DUPLEX_FULL);
+               rtl8152_set_speed(tp, AUTONEG_ENABLE,
+                               tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
+                               DUPLEX_FULL);
                tp->speed = 0;
                netif_carrier_off(tp->netdev);
                set_bit(WORK_ENABLE, &tp->flags);
@@ -2072,6 +2649,18 @@ static void r8152b_get_version(struct r8152 *tp)
        case 0x4c10:
                tp->version = RTL_VER_02;
                break;
+       case 0x5c00:
+               tp->version = RTL_VER_03;
+               tp->mii.supports_gmii = 1;
+               break;
+       case 0x5c10:
+               tp->version = RTL_VER_04;
+               tp->mii.supports_gmii = 1;
+               break;
+       case 0x5c20:
+               tp->version = RTL_VER_05;
+               tp->mii.supports_gmii = 1;
+               break;
        default:
                netif_info(tp, probe, tp->netdev,
                           "Unknown version 0x%04x\n", version);
@@ -2079,6 +2668,80 @@ static void r8152b_get_version(struct r8152 *tp)
        }
 }
 
+static void rtl8152_unload(struct r8152 *tp)
+{
+       u32     ocp_data;
+
+       if (tp->version != RTL_VER_01) {
+               ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
+               ocp_data |= POWER_CUT;
+               ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
+       }
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
+       ocp_data &= ~RESUME_INDICATE;
+       ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
+}
+
+static void rtl8153_unload(struct r8152 *tp)
+{
+       r8153_power_cut_en(tp, 1);
+}
+
+static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
+{
+       struct rtl_ops *ops = &tp->rtl_ops;
+       int ret = -ENODEV;
+
+       switch (id->idVendor) {
+       case VENDOR_ID_REALTEK:
+               switch (id->idProduct) {
+               case PRODUCT_ID_RTL8152:
+                       ops->init               = r8152b_init;
+                       ops->enable             = rtl8152_enable;
+                       ops->disable            = rtl8152_disable;
+                       ops->down               = rtl8152_down;
+                       ops->unload             = rtl8152_unload;
+                       ret = 0;
+                       break;
+               case PRODUCT_ID_RTL8153:
+                       ops->init               = r8153_init;
+                       ops->enable             = rtl8153_enable;
+                       ops->disable            = rtl8152_disable;
+                       ops->down               = rtl8153_down;
+                       ops->unload             = rtl8153_unload;
+                       ret = 0;
+                       break;
+               default:
+                       break;
+               }
+               break;
+
+       case VENDOR_ID_SAMSUNG:
+               switch (id->idProduct) {
+               case PRODUCT_ID_SAMSUNG:
+                       ops->init               = r8153_init;
+                       ops->enable             = rtl8153_enable;
+                       ops->disable            = rtl8152_disable;
+                       ops->down               = rtl8153_down;
+                       ops->unload             = rtl8153_unload;
+                       ret = 0;
+                       break;
+               default:
+                       break;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       if (ret)
+               netif_err(tp, probe, tp->netdev, "Unknown Device\n");
+
+       return ret;
+}
+
 static int rtl8152_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
 {
@@ -2094,7 +2757,7 @@ static int rtl8152_probe(struct usb_interface *intf,
 
        netdev = alloc_etherdev(sizeof(struct r8152));
        if (!netdev) {
-               dev_err(&intf->dev, "Out of memory");
+               dev_err(&intf->dev, "Out of memory\n");
                return -ENOMEM;
        }
 
@@ -2102,12 +2765,17 @@ static int rtl8152_probe(struct usb_interface *intf,
        tp = netdev_priv(netdev);
        tp->msg_enable = 0x7FFF;
 
-       tasklet_init(&tp->tl, bottom_half, (unsigned long)tp);
-       INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t);
-
        tp->udev = udev;
        tp->netdev = netdev;
        tp->intf = intf;
+
+       ret = rtl_ops_init(tp, id);
+       if (ret)
+               goto out;
+
+       tasklet_init(&tp->tl, bottom_half, (unsigned long)tp);
+       INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t);
+
        netdev->netdev_ops = &rtl8152_netdev_ops;
        netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
 
@@ -2124,7 +2792,7 @@ static int rtl8152_probe(struct usb_interface *intf,
        tp->mii.supports_gmii = 0;
 
        r8152b_get_version(tp);
-       r8152b_init(tp);
+       tp->rtl_ops.init(tp);
        set_ethernet_addr(tp);
 
        ret = alloc_all_mem(tp);
@@ -2135,11 +2803,11 @@ static int rtl8152_probe(struct usb_interface *intf,
 
        ret = register_netdev(netdev);
        if (ret != 0) {
-               netif_err(tp, probe, netdev, "couldn't register the device");
+               netif_err(tp, probe, netdev, "couldn't register the device\n");
                goto out1;
        }
 
-       netif_info(tp, probe, netdev, "%s", DRIVER_VERSION);
+       netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION);
 
        return 0;
 
@@ -2150,21 +2818,6 @@ out:
        return ret;
 }
 
-static void rtl8152_unload(struct r8152 *tp)
-{
-       u32     ocp_data;
-
-       if (tp->version != RTL_VER_01) {
-               ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
-               ocp_data |= POWER_CUT;
-               ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
-       }
-
-       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
-       ocp_data &= ~RWSUME_INDICATE;
-       ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
-}
-
 static void rtl8152_disconnect(struct usb_interface *intf)
 {
        struct r8152 *tp = usb_get_intfdata(intf);
@@ -2174,7 +2827,7 @@ static void rtl8152_disconnect(struct usb_interface *intf)
                set_bit(RTL8152_UNPLUG, &tp->flags);
                tasklet_kill(&tp->tl);
                unregister_netdev(tp->netdev);
-               rtl8152_unload(tp);
+               tp->rtl_ops.unload(tp);
                free_all_mem(tp);
                free_netdev(tp->netdev);
        }
@@ -2183,6 +2836,8 @@ static void rtl8152_disconnect(struct usb_interface *intf)
 /* table of devices that work with this driver */
 static struct usb_device_id rtl8152_table[] = {
        {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)},
+       {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8153)},
+       {USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG)},
        {}
 };
 
index 2df2f4fb42a7c381fb68275bfab10052b7a71363..5fd2ca61d1e21ddc4e88727192de2ab3d37a816e 100644 (file)
@@ -226,7 +226,7 @@ static const struct usb_device_id products[] = {
 {
        USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM,
                        USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
-#if defined(CONFIG_USB_RTL8153) || defined(CONFIG_USB_RTL8153_MODULE)
+#if defined(CONFIG_USB_RTL8152) || defined(CONFIG_USB_RTL8152_MODULE)
        .driver_info = 0,
 #else
        .driver_info = (unsigned long) &r8153_info,
index c51a98867a40bead7fd137a51f2f398d7336825d..7b172408cff02b72b8c5eb90307b63dec164f8c2 100644 (file)
@@ -1788,16 +1788,17 @@ static int virtnet_restore(struct virtio_device *vdev)
        if (err)
                return err;
 
-       if (netif_running(vi->dev))
+       if (netif_running(vi->dev)) {
+               for (i = 0; i < vi->curr_queue_pairs; i++)
+                       if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+                               schedule_delayed_work(&vi->refill, 0);
+
                for (i = 0; i < vi->max_queue_pairs; i++)
                        virtnet_napi_enable(&vi->rq[i]);
+       }
 
        netif_device_attach(vi->dev);
 
-       for (i = 0; i < vi->curr_queue_pairs; i++)
-               if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
-                       schedule_delayed_work(&vi->refill, 0);
-
        mutex_lock(&vi->config_lock);
        vi->config_enable = true;
        mutex_unlock(&vi->config_lock);
index c0eab72cc79f5a2d8a86f28b454b14e819c31e6f..3be786faaaec222f0226b8285dde01e88b147e59 100644 (file)
@@ -1235,7 +1235,8 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 #ifdef VMXNET3_RSS
                        if (rcd->rssType != VMXNET3_RCD_RSS_TYPE_NONE &&
                            (adapter->netdev->features & NETIF_F_RXHASH))
-                               skb_set_hash(skb, le32_to_cpu(rcd->rssHash),
+                               skb_set_hash(ctx->skb,
+                                            le32_to_cpu(rcd->rssHash),
                                             PKT_HASH_TYPE_L3);
 #endif
                        skb_put(ctx->skb, rcd->len);
index ea203c1aaa241693dd9ed64d4092f4e42e252d57..481f85d604a4881d25cb0125a284b34820f2a076 100644 (file)
@@ -1081,7 +1081,7 @@ static void vxlan_rcv(struct vxlan_sock *vs,
        struct iphdr *oip = NULL;
        struct ipv6hdr *oip6 = NULL;
        struct vxlan_dev *vxlan;
-       struct pcpu_tstats *stats;
+       struct pcpu_sw_netstats *stats;
        union vxlan_addr saddr;
        __u32 vni;
        int err = 0;
@@ -1381,20 +1381,6 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
        return false;
 }
 
-static void vxlan_sock_put(struct sk_buff *skb)
-{
-       sock_put(skb->sk);
-}
-
-/* On transmit, associate with the tunnel socket */
-static void vxlan_set_owner(struct sock *sk, struct sk_buff *skb)
-{
-       skb_orphan(skb);
-       sock_hold(sk);
-       skb->sk = sk;
-       skb->destructor = vxlan_sock_put;
-}
-
 /* Compute source port for outgoing packet
  *   first choice to use L4 flow hash since it will spread
  *     better and maybe available from hardware
@@ -1514,8 +1500,6 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs,
        ip6h->daddr       = *daddr;
        ip6h->saddr       = *saddr;
 
-       vxlan_set_owner(vs->sock->sk, skb);
-
        err = handle_offloads(skb);
        if (err)
                return err;
@@ -1572,8 +1556,6 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
        uh->len = htons(skb->len);
        uh->check = 0;
 
-       vxlan_set_owner(vs->sock->sk, skb);
-
        err = handle_offloads(skb);
        if (err)
                return err;
@@ -1587,11 +1569,12 @@ EXPORT_SYMBOL_GPL(vxlan_xmit_skb);
 static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
                               struct vxlan_dev *dst_vxlan)
 {
-       struct pcpu_tstats *tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
-       struct pcpu_tstats *rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats);
+       struct pcpu_sw_netstats *tx_stats, *rx_stats;
        union vxlan_addr loopback;
        union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip;
 
+       tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
+       rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats);
        skb->pkt_type = PACKET_HOST;
        skb->encapsulation = 0;
        skb->dev = dst_vxlan->dev;
@@ -1785,7 +1768,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct ethhdr *eth;
        bool did_rsc = false;
-       struct vxlan_rdst *rdst;
+       struct vxlan_rdst *rdst, *fdst = NULL;
        struct vxlan_fdb *f;
 
        skb_reset_mac_header(skb);
@@ -1827,7 +1810,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
                                vxlan_fdb_miss(vxlan, eth->h_dest);
 
                        dev->stats.tx_dropped++;
-                       dev_kfree_skb(skb);
+                       kfree_skb(skb);
                        return NETDEV_TX_OK;
                }
        }
@@ -1835,12 +1818,19 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        list_for_each_entry_rcu(rdst, &f->remotes, list) {
                struct sk_buff *skb1;
 
+               if (!fdst) {
+                       fdst = rdst;
+                       continue;
+               }
                skb1 = skb_clone(skb, GFP_ATOMIC);
                if (skb1)
                        vxlan_xmit_one(skb1, dev, rdst, did_rsc);
        }
 
-       dev_kfree_skb(skb);
+       if (fdst)
+               vxlan_xmit_one(skb, dev, fdst, did_rsc);
+       else
+               kfree_skb(skb);
        return NETDEV_TX_OK;
 }
 
@@ -1897,12 +1887,12 @@ static int vxlan_init(struct net_device *dev)
        struct vxlan_sock *vs;
        int i;
 
-       dev->tstats = alloc_percpu(struct pcpu_tstats);
+       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
        for_each_possible_cpu(i) {
-               struct pcpu_tstats *vxlan_stats;
+               struct pcpu_sw_netstats *vxlan_stats;
                vxlan_stats = per_cpu_ptr(dev->tstats, i);
                u64_stats_init(&vxlan_stats->syncp);
        }
@@ -2014,6 +2004,29 @@ static void vxlan_set_multicast_list(struct net_device *dev)
 {
 }
 
+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;
+       int max_mtu;
+
+       lowerdev = __dev_get_by_index(dev_net(dev), dst->remote_ifindex);
+       if (lowerdev == NULL)
+               return eth_change_mtu(dev, new_mtu);
+
+       if (dst->remote_ip.sa.sa_family == AF_INET6)
+               max_mtu = lowerdev->mtu - VXLAN6_HEADROOM;
+       else
+               max_mtu = lowerdev->mtu - VXLAN_HEADROOM;
+
+       if (new_mtu < 68 || new_mtu > max_mtu)
+               return -EINVAL;
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+
 static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_init               = vxlan_init,
        .ndo_uninit             = vxlan_uninit,
@@ -2022,7 +2035,7 @@ static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_start_xmit         = vxlan_xmit,
        .ndo_get_stats64        = ip_tunnel_get_stats64,
        .ndo_set_rx_mode        = vxlan_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_change_mtu         = vxlan_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_fdb_add            = vxlan_fdb_add,
@@ -2453,7 +2466,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
                /* update header length based on lower device */
                dev->hard_header_len = lowerdev->hard_header_len +
                                       (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
-       }
+       } else if (use_ipv6)
+               vxlan->flags |= VXLAN_F_IPV6;
 
        if (data[IFLA_VXLAN_TOS])
                vxlan->tos  = nla_get_u8(data[IFLA_VXLAN_TOS]);
index cfce83e1f273f0259ee07d072fd8c8f59df8e99a..55eda7afc041e792abcf265e6d39615b4695fc24 100644 (file)
@@ -15,7 +15,6 @@
  * more details.
  */
 
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/if.h>
 #include <linux/skbuff.h>
@@ -1314,7 +1313,7 @@ static void adm8211_bss_info_changed(struct ieee80211_hw *dev,
        if (!(changes & BSS_CHANGED_BSSID))
                return;
 
-       if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
+       if (!ether_addr_equal(conf->bssid, priv->bssid)) {
                adm8211_set_bssid(dev, conf->bssid);
                memcpy(priv->bssid, conf->bssid, ETH_ALEN);
        }
index 14128fd265acd50cbf87b8d348cf014ce316a760..7e9ede6c5798a83c20c82a0e3ca087f74d80442b 100644 (file)
@@ -23,7 +23,6 @@
 #ifdef __IN_PCMCIA_PACKAGE__
 #include <pcmcia/k_compat.h>
 #endif
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/ptrace.h>
index 34c8a33cac06f67dfb5e4dc718767d6457449d86..031d4ec647792840ad5238993ac79491eb79b7ec 100644 (file)
@@ -1721,7 +1721,7 @@ static void at76_mac80211_tx(struct ieee80211_hw *hw,
         * following workaround is necessary. If the TX frame is an
         * authentication frame extract the bssid and send the CMD_JOIN. */
        if (mgmt->frame_control & cpu_to_le16(IEEE80211_STYPE_AUTH)) {
-               if (!ether_addr_equal(priv->bssid, mgmt->bssid)) {
+               if (!ether_addr_equal_64bits(priv->bssid, mgmt->bssid)) {
                        memcpy(priv->bssid, mgmt->bssid, ETH_ALEN);
                        ieee80211_queue_work(hw, &priv->work_join_bssid);
                        dev_kfree_skb_any(skb);
index 280fc3d53a36466ca8a3f4ff7fd73074efc86b75..8aa20df55e50d854407d7c84faf28ac11b1576e4 100644 (file)
@@ -25,7 +25,6 @@
  * that and only has minimal functionality.
  */
 #include <linux/compiler.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/list.h>
index 69f58b073e85ff1a183ec1f06e803ff9da00806c..6396ad4bce67c8f005ec5373bd214e0d7c30712b 100644 (file)
@@ -1245,7 +1245,7 @@ ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb,
 
        if (ieee80211_is_beacon(mgmt->frame_control) &&
            le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
-           ether_addr_equal(mgmt->bssid, common->curbssid)) {
+           ether_addr_equal_64bits(mgmt->bssid, common->curbssid)) {
                /*
                 * Received an IBSS beacon with the same BSSID. Hardware *must*
                 * have updated the local TSF. We have to work around various
@@ -1309,7 +1309,7 @@ ath5k_update_beacon_rssi(struct ath5k_hw *ah, struct sk_buff *skb, int rssi)
 
        /* only beacons from our BSSID */
        if (!ieee80211_is_beacon(mgmt->frame_control) ||
-           !ether_addr_equal(mgmt->bssid, common->curbssid))
+           !ether_addr_equal_64bits(mgmt->bssid, common->curbssid))
                return;
 
        ewma_add(&ah->ah_beacon_rssi_avg, rssi);
index 546d5da0b8947a2f8522c5f7b8893ee0a6f537d5..4f16d79c9eb187566ff878e9ac42c163cd58312a 100644 (file)
@@ -2754,9 +2754,9 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
                                mask->control[band].legacy << 4;
 
                /* copy mcs rate mask */
-               mcsrate = mask->control[band].mcs[1];
+               mcsrate = mask->control[band].ht_mcs[1];
                mcsrate <<= 8;
-               mcsrate |= mask->control[band].mcs[0];
+               mcsrate |= mask->control[band].ht_mcs[0];
                ratemask[band] |= mcsrate << 12;
                ratemask[band] |= mcsrate << 28;
        }
@@ -2806,7 +2806,7 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
                                mask->control[band].legacy << 4;
 
                /* copy mcs rate mask */
-               mcsrate = mask->control[band].mcs[0];
+               mcsrate = mask->control[band].ht_mcs[0];
                ratemask[band] |= mcsrate << 12;
                ratemask[band] |= mcsrate << 20;
        }
index 337c459eda284770c61dbb654b1762aac3965e9b..e9904e5ccd81007f543b4e12a185be1a43542085 100644 (file)
@@ -11,12 +11,14 @@ ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
 ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
 ath9k-$(CONFIG_ATH9K_PCI) += pci.o
 ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
-ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
 ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
 ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o
 ath9k-$(CONFIG_ATH9K_TX99) += tx99.o
 ath9k-$(CONFIG_ATH9K_WOW) += wow.o
 
+ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o \
+                                spectral.o
+
 obj-$(CONFIG_ATH9K) += ath9k.o
 
 ath9k_hw-y:=   \
index bd048cc69a334d6234b6967ecff5e1aec8b75fbe..a3668433dc02b6c35df882367e6f441a811ce6f8 100644 (file)
@@ -724,14 +724,14 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
        struct ath_ant_comb *antcomb = &sc->ant_comb;
        int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
        int curr_main_set;
-       int main_rssi = rs->rs_rssi_ctl0;
-       int alt_rssi = rs->rs_rssi_ctl1;
+       int main_rssi = rs->rs_rssi_ctl[0];
+       int alt_rssi = rs->rs_rssi_ctl[1];
        int rx_ant_conf,  main_ant_conf;
        bool short_scan = false, ret;
 
-       rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
+       rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
                       ATH_ANT_RX_MASK;
-       main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
+       main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
                         ATH_ANT_RX_MASK;
 
        if (alt_rssi >= antcomb->low_rssi_thresh) {
index 5c95fd9e9c9e9c861edb283a2a8cfbf4a9b5e3b9..d480d2f3e18588843696bc3801d6a821ffbefee4 100644 (file)
@@ -32,12 +32,8 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
                return 0;
        }
 
-       if (ah->config.pcie_clock_req)
-               INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                          ar9280PciePhy_clkreq_off_L1_9280);
-       else
-               INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                          ar9280PciePhy_clkreq_always_on_L1_9280);
+       INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                      ar9280PciePhy_clkreq_always_on_L1_9280);
 
        if (AR_SREV_9287_11_OR_LATER(ah)) {
                INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
@@ -387,6 +383,20 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
        }
 }
 
+static void ar9002_hw_init_hang_checks(struct ath_hw *ah)
+{
+       if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
+               ah->config.hw_hang_checks |= HW_BB_RIFS_HANG;
+               ah->config.hw_hang_checks |= HW_BB_DFS_HANG;
+       }
+
+       if (AR_SREV_9280(ah))
+               ah->config.hw_hang_checks |= HW_BB_RX_CLEAR_STUCK_HANG;
+
+       if (AR_SREV_5416(ah) || AR_SREV_9100(ah) || AR_SREV_9160(ah))
+               ah->config.hw_hang_checks |= HW_MAC_HANG;
+}
+
 /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
 int ar9002_hw_attach_ops(struct ath_hw *ah)
 {
@@ -399,6 +409,7 @@ int ar9002_hw_attach_ops(struct ath_hw *ah)
                return ret;
 
        priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
+       priv_ops->init_hang_checks = ar9002_hw_init_hang_checks;
 
        ops->config_pci_powersave = ar9002_hw_configpcipowersave;
 
index 8d78253c26cee6f459121e7e8ef5c3e0e44b8b2a..741b38ddcb378e8cb17dbfe0f79f33516be75527 100644 (file)
@@ -29,7 +29,8 @@ static void ar9002_hw_set_desc_link(void *ds, u32 ds_link)
        ((struct ath_desc*) ds)->ds_link = ds_link;
 }
 
-static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked,
+                             u32 *sync_cause_p)
 {
        u32 isr = 0;
        u32 mask2 = 0;
@@ -76,9 +77,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                                mask2 |= ATH9K_INT_CST;
                        if (isr2 & AR_ISR_S2_TSFOOR)
                                mask2 |= ATH9K_INT_TSFOOR;
+
+                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                               REG_WRITE(ah, AR_ISR_S2, isr2);
+                               isr &= ~AR_ISR_BCNMISC;
+                       }
                }
 
-               isr = REG_READ(ah, AR_ISR_RAC);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
+                       isr = REG_READ(ah, AR_ISR_RAC);
+
                if (isr == 0xffffffff) {
                        *masked = 0;
                        return false;
@@ -97,11 +105,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 
                        *masked |= ATH9K_INT_TX;
 
-                       s0_s = REG_READ(ah, AR_ISR_S0_S);
+                       if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                               s0_s = REG_READ(ah, AR_ISR_S0_S);
+                               s1_s = REG_READ(ah, AR_ISR_S1_S);
+                       } else {
+                               s0_s = REG_READ(ah, AR_ISR_S0);
+                               REG_WRITE(ah, AR_ISR_S0, s0_s);
+                               s1_s = REG_READ(ah, AR_ISR_S1);
+                               REG_WRITE(ah, AR_ISR_S1, s1_s);
+
+                               isr &= ~(AR_ISR_TXOK |
+                                        AR_ISR_TXDESC |
+                                        AR_ISR_TXERR |
+                                        AR_ISR_TXEOL);
+                       }
+
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-
-                       s1_s = REG_READ(ah, AR_ISR_S1_S);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
                }
@@ -114,13 +134,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                *masked |= mask2;
        }
 
-       if (AR_SREV_9100(ah))
-               return true;
-
-       if (isr & AR_ISR_GENTMR) {
+       if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) {
                u32 s5_s;
 
-               s5_s = REG_READ(ah, AR_ISR_S5_S);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                       s5_s = REG_READ(ah, AR_ISR_S5_S);
+               } else {
+                       s5_s = REG_READ(ah, AR_ISR_S5);
+               }
+
                ah->intr_gen_timer_trigger =
                                MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
 
@@ -133,10 +155,24 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
                    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
                        *masked |= ATH9K_INT_TIM_TIMER;
+
+               if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                       REG_WRITE(ah, AR_ISR_S5, s5_s);
+                       isr &= ~AR_ISR_GENTMR;
+               }
        }
 
+       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+               REG_WRITE(ah, AR_ISR, isr);
+               REG_READ(ah, AR_ISR);
+       }
+
+       if (AR_SREV_9100(ah))
+               return true;
+
        if (sync_cause) {
-               ath9k_debug_sync_cause(common, sync_cause);
+               if (sync_cause_p)
+                       *sync_cause_p = sync_cause;
                fatal_int =
                        (sync_cause &
                         (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
index f087117b2e6b6b2592ae8eb7a2270314cffb7325..9a2afa2c690b761bef1e9203c60b2a3bb0e9e86f 100644 (file)
@@ -201,7 +201,6 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
        ath9k_hw_get_channel_centers(ah, chan, &centers);
        freq = centers.synth_center;
 
-       ah->config.spurmode = SPUR_ENABLE_EEPROM;
        for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
                cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
 
index 97e09d5f3a427eade9008c33959a8e7f29836951..8c145cd98c1c50505f15d8616002fa472733e1b1 100644 (file)
@@ -326,6 +326,224 @@ static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
        ah->supp_cals = IQ_MISMATCH_CAL;
 }
 
+#define OFF_UPPER_LT 24
+#define OFF_LOWER_LT 7
+
+static bool ar9003_hw_dynamic_osdac_selection(struct ath_hw *ah,
+                                             bool txiqcal_done)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       int ch0_done, osdac_ch0, dc_off_ch0_i1, dc_off_ch0_q1, dc_off_ch0_i2,
+               dc_off_ch0_q2, dc_off_ch0_i3, dc_off_ch0_q3;
+       int ch1_done, osdac_ch1, dc_off_ch1_i1, dc_off_ch1_q1, dc_off_ch1_i2,
+               dc_off_ch1_q2, dc_off_ch1_i3, dc_off_ch1_q3;
+       int ch2_done, osdac_ch2, dc_off_ch2_i1, dc_off_ch2_q1, dc_off_ch2_i2,
+               dc_off_ch2_q2, dc_off_ch2_i3, dc_off_ch2_q3;
+       bool status;
+       u32 temp, val;
+
+       /*
+        * Clear offset and IQ calibration, run AGC cal.
+        */
+       REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_OFFSET_CAL);
+       REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+                   AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
+       REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+                 REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
+
+       status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+                              AR_PHY_AGC_CONTROL_CAL,
+                              0, AH_WAIT_TIMEOUT);
+       if (!status) {
+               ath_dbg(common, CALIBRATE,
+                       "AGC cal without offset cal failed to complete in 1ms");
+               return false;
+       }
+
+       /*
+        * Allow only offset calibration and disable the others
+        * (Carrier Leak calibration, TX Filter calibration and
+        *  Peak Detector offset calibration).
+        */
+       REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_OFFSET_CAL);
+       REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
+                   AR_PHY_CL_CAL_ENABLE);
+       REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_FLTR_CAL);
+       REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_PKDET_CAL);
+
+       ch0_done = 0;
+       ch1_done = 0;
+       ch2_done = 0;
+
+       while ((ch0_done == 0) || (ch1_done == 0) || (ch2_done == 0)) {
+               osdac_ch0 = (REG_READ(ah, AR_PHY_65NM_CH0_BB1) >> 30) & 0x3;
+               osdac_ch1 = (REG_READ(ah, AR_PHY_65NM_CH1_BB1) >> 30) & 0x3;
+               osdac_ch2 = (REG_READ(ah, AR_PHY_65NM_CH2_BB1) >> 30) & 0x3;
+
+               REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+               REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+                         REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
+
+               status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+                                      AR_PHY_AGC_CONTROL_CAL,
+                                      0, AH_WAIT_TIMEOUT);
+               if (!status) {
+                       ath_dbg(common, CALIBRATE,
+                               "DC offset cal failed to complete in 1ms");
+                       return false;
+               }
+
+               REG_CLR_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+               /*
+                * High gain.
+                */
+               REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
+                         ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (1 << 8)));
+               REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
+                         ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (1 << 8)));
+               REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
+                         ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (1 << 8)));
+
+               temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
+               dc_off_ch0_i1 = (temp >> 26) & 0x1f;
+               dc_off_ch0_q1 = (temp >> 21) & 0x1f;
+
+               temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
+               dc_off_ch1_i1 = (temp >> 26) & 0x1f;
+               dc_off_ch1_q1 = (temp >> 21) & 0x1f;
+
+               temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
+               dc_off_ch2_i1 = (temp >> 26) & 0x1f;
+               dc_off_ch2_q1 = (temp >> 21) & 0x1f;
+
+               /*
+                * Low gain.
+                */
+               REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
+                         ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (2 << 8)));
+               REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
+                         ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (2 << 8)));
+               REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
+                         ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (2 << 8)));
+
+               temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
+               dc_off_ch0_i2 = (temp >> 26) & 0x1f;
+               dc_off_ch0_q2 = (temp >> 21) & 0x1f;
+
+               temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
+               dc_off_ch1_i2 = (temp >> 26) & 0x1f;
+               dc_off_ch1_q2 = (temp >> 21) & 0x1f;
+
+               temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
+               dc_off_ch2_i2 = (temp >> 26) & 0x1f;
+               dc_off_ch2_q2 = (temp >> 21) & 0x1f;
+
+               /*
+                * Loopback.
+                */
+               REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
+                         ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (3 << 8)));
+               REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
+                         ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (3 << 8)));
+               REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
+                         ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (3 << 8)));
+
+               temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
+               dc_off_ch0_i3 = (temp >> 26) & 0x1f;
+               dc_off_ch0_q3 = (temp >> 21) & 0x1f;
+
+               temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
+               dc_off_ch1_i3 = (temp >> 26) & 0x1f;
+               dc_off_ch1_q3 = (temp >> 21) & 0x1f;
+
+               temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
+               dc_off_ch2_i3 = (temp >> 26) & 0x1f;
+               dc_off_ch2_q3 = (temp >> 21) & 0x1f;
+
+               if ((dc_off_ch0_i1 > OFF_UPPER_LT) || (dc_off_ch0_i1 < OFF_LOWER_LT) ||
+                   (dc_off_ch0_i2 > OFF_UPPER_LT) || (dc_off_ch0_i2 < OFF_LOWER_LT) ||
+                   (dc_off_ch0_i3 > OFF_UPPER_LT) || (dc_off_ch0_i3 < OFF_LOWER_LT) ||
+                   (dc_off_ch0_q1 > OFF_UPPER_LT) || (dc_off_ch0_q1 < OFF_LOWER_LT) ||
+                   (dc_off_ch0_q2 > OFF_UPPER_LT) || (dc_off_ch0_q2 < OFF_LOWER_LT) ||
+                   (dc_off_ch0_q3 > OFF_UPPER_LT) || (dc_off_ch0_q3 < OFF_LOWER_LT)) {
+                       if (osdac_ch0 == 3) {
+                               ch0_done = 1;
+                       } else {
+                               osdac_ch0++;
+
+                               val = REG_READ(ah, AR_PHY_65NM_CH0_BB1) & 0x3fffffff;
+                               val |= (osdac_ch0 << 30);
+                               REG_WRITE(ah, AR_PHY_65NM_CH0_BB1, val);
+
+                               ch0_done = 0;
+                       }
+               } else {
+                       ch0_done = 1;
+               }
+
+               if ((dc_off_ch1_i1 > OFF_UPPER_LT) || (dc_off_ch1_i1 < OFF_LOWER_LT) ||
+                   (dc_off_ch1_i2 > OFF_UPPER_LT) || (dc_off_ch1_i2 < OFF_LOWER_LT) ||
+                   (dc_off_ch1_i3 > OFF_UPPER_LT) || (dc_off_ch1_i3 < OFF_LOWER_LT) ||
+                   (dc_off_ch1_q1 > OFF_UPPER_LT) || (dc_off_ch1_q1 < OFF_LOWER_LT) ||
+                   (dc_off_ch1_q2 > OFF_UPPER_LT) || (dc_off_ch1_q2 < OFF_LOWER_LT) ||
+                   (dc_off_ch1_q3 > OFF_UPPER_LT) || (dc_off_ch1_q3 < OFF_LOWER_LT)) {
+                       if (osdac_ch1 == 3) {
+                               ch1_done = 1;
+                       } else {
+                               osdac_ch1++;
+
+                               val = REG_READ(ah, AR_PHY_65NM_CH1_BB1) & 0x3fffffff;
+                               val |= (osdac_ch1 << 30);
+                               REG_WRITE(ah, AR_PHY_65NM_CH1_BB1, val);
+
+                               ch1_done = 0;
+                       }
+               } else {
+                       ch1_done = 1;
+               }
+
+               if ((dc_off_ch2_i1 > OFF_UPPER_LT) || (dc_off_ch2_i1 < OFF_LOWER_LT) ||
+                   (dc_off_ch2_i2 > OFF_UPPER_LT) || (dc_off_ch2_i2 < OFF_LOWER_LT) ||
+                   (dc_off_ch2_i3 > OFF_UPPER_LT) || (dc_off_ch2_i3 < OFF_LOWER_LT) ||
+                   (dc_off_ch2_q1 > OFF_UPPER_LT) || (dc_off_ch2_q1 < OFF_LOWER_LT) ||
+                   (dc_off_ch2_q2 > OFF_UPPER_LT) || (dc_off_ch2_q2 < OFF_LOWER_LT) ||
+                   (dc_off_ch2_q3 > OFF_UPPER_LT) || (dc_off_ch2_q3 < OFF_LOWER_LT)) {
+                       if (osdac_ch2 == 3) {
+                               ch2_done = 1;
+                       } else {
+                               osdac_ch2++;
+
+                               val = REG_READ(ah, AR_PHY_65NM_CH2_BB1) & 0x3fffffff;
+                               val |= (osdac_ch2 << 30);
+                               REG_WRITE(ah, AR_PHY_65NM_CH2_BB1, val);
+
+                               ch2_done = 0;
+                       }
+               } else {
+                       ch2_done = 1;
+               }
+       }
+
+       REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_OFFSET_CAL);
+       REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+       /*
+        * We don't need to check txiqcal_done here since it is always
+        * set for AR9550.
+        */
+       REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+                   AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
+
+       return true;
+}
+
 /*
  * solve 4x4 linear equation used in loopback iq cal.
  */
@@ -1271,6 +1489,11 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
                REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
        }
 
+       if (AR_SREV_9550(ah) && IS_CHAN_2GHZ(chan)) {
+               if (!ar9003_hw_dynamic_osdac_selection(ah, txiqcal_done))
+                       return false;
+       }
+
 skip_tx_iqcal:
        if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
                if (AR_SREV_9330_11(ah))
index ec317d6937d646e8cb9269675649d284789f5399..25243cbc07f0ba4ed9c27a6779ff2ea3be7be77d 100644 (file)
@@ -131,6 +131,7 @@ static const struct ar9300_eeprom ar9300_default = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -138,7 +139,7 @@ static const struct ar9300_eeprom ar9300_default = {
         },
        .base_ext1 = {
                .ant_div_control = 0,
-               .future = {0, 0, 0},
+               .future = {0, 0},
                .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
        },
        .calFreqPier2G = {
@@ -333,6 +334,7 @@ static const struct ar9300_eeprom ar9300_default = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0c80c080),
                .papdRateMaskHt40 = LE32(0x0080c080),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -707,6 +709,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0c80c080),
                .papdRateMaskHt40 = LE32(0x0080c080),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -714,7 +717,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
         },
         .base_ext1 = {
                .ant_div_control = 0,
-               .future = {0, 0, 0},
+               .future = {0, 0},
                .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
         },
        .calFreqPier2G = {
@@ -909,6 +912,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -1284,6 +1288,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0c80c080),
                .papdRateMaskHt40 = LE32(0x0080c080),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -1291,7 +1296,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
        },
        .base_ext1 = {
                .ant_div_control = 0,
-               .future = {0, 0, 0},
+               .future = {0, 0},
                .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
        },
        .calFreqPier2G = {
@@ -1486,6 +1491,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -1861,6 +1867,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0c80c080),
                .papdRateMaskHt40 = LE32(0x0080c080),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -1868,7 +1875,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
        },
        .base_ext1 = {
                .ant_div_control = 0,
-               .future = {0, 0, 0},
+               .future = {0, 0},
                .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
        },
        .calFreqPier2G = {
@@ -2063,6 +2070,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -2437,6 +2445,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0c80C080),
                .papdRateMaskHt40 = LE32(0x0080C080),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -2444,7 +2453,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
         },
         .base_ext1 = {
                .ant_div_control = 0,
-               .future = {0, 0, 0},
+               .future = {0, 0},
                .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
         },
        .calFreqPier2G = {
@@ -2639,6 +2648,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
                .thresh62 = 28,
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+               .switchcomspdt = 0,
                .xlna_bias_strength = 0,
                .futureModal = {
                        0, 0, 0, 0, 0, 0, 0,
@@ -3588,7 +3598,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
        if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
                REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
                                AR_SWITCH_TABLE_COM_AR9462_ALL, value);
-       } else if (AR_SREV_9550(ah)) {
+       } else if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
                REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
                                AR_SWITCH_TABLE_COM_AR9550_ALL, value);
        } else
@@ -3965,7 +3975,7 @@ static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah)
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0];
 
-       if (AR_SREV_9340(ah))
+       if (AR_SREV_9340(ah) || AR_SREV_9531(ah))
                return;
 
        if (eep->baseEepHeader.featureEnable & 0x40) {
@@ -4020,7 +4030,10 @@ static void ar9003_hw_xpa_timing_control_apply(struct ath_hw *ah, bool is2ghz)
        if (!(eep->baseEepHeader.featureEnable & 0x80))
                return;
 
-       if (!AR_SREV_9300(ah) && !AR_SREV_9340(ah) && !AR_SREV_9580(ah))
+       if (!AR_SREV_9300(ah) &&
+           !AR_SREV_9340(ah) &&
+           !AR_SREV_9580(ah) &&
+           !AR_SREV_9531(ah))
                return;
 
        xpa_ctl = ar9003_modal_header(ah, is2ghz)->txFrameToXpaOn;
@@ -4111,6 +4124,37 @@ static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah)
        }
 }
 
+static void ar9003_hw_apply_minccapwr_thresh(struct ath_hw *ah,
+                                            bool is2ghz)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       const u_int32_t cca_ctrl[AR9300_MAX_CHAINS] = {
+               AR_PHY_CCA_CTRL_0,
+               AR_PHY_CCA_CTRL_1,
+               AR_PHY_CCA_CTRL_2,
+       };
+       int chain;
+       u32 val;
+
+       if (is2ghz) {
+               if (!(eep->base_ext1.misc_enable & BIT(2)))
+                       return;
+       } else {
+               if (!(eep->base_ext1.misc_enable & BIT(3)))
+                       return;
+       }
+
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+               if (!(ah->caps.tx_chainmask & BIT(chain)))
+                       continue;
+
+               val = ar9003_modal_header(ah, is2ghz)->noiseFloorThreshCh[chain];
+               REG_RMW_FIELD(ah, cca_ctrl[chain],
+                             AR_PHY_EXT_CCA0_THRESH62_1, val);
+       }
+
+}
+
 static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
                                             struct ath9k_channel *chan)
 {
@@ -4122,9 +4166,10 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
        ar9003_hw_xlna_bias_strength_apply(ah, is2ghz);
        ar9003_hw_atten_apply(ah, chan);
        ar9003_hw_quick_drop_apply(ah, chan->channel);
-       if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
+       if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9531(ah))
                ar9003_hw_internal_regulator_apply(ah);
        ar9003_hw_apply_tuning_caps(ah);
+       ar9003_hw_apply_minccapwr_thresh(ah, chan);
        ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
        ar9003_hw_thermometer_apply(ah);
        ar9003_hw_thermo_cal_apply(ah);
@@ -4746,7 +4791,7 @@ static void ar9003_hw_power_control_override(struct ath_hw *ah,
        }
 
 tempslope:
-       if (AR_SREV_9550(ah)) {
+       if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
                /*
                 * AR955x has tempSlope register for each chain.
                 * Check whether temp_compensation feature is enabled or not.
index 0e5daa58a4fc14371d360bdc5aa22937902bc824..694ca2e680e5d5a7d45eba015216c395026ef94a 100644 (file)
@@ -270,10 +270,20 @@ struct cal_ctl_data_5g {
        u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
 } __packed;
 
+#define MAX_BASE_EXTENSION_FUTURE 2
+
 struct ar9300_BaseExtension_1 {
        u8 ant_div_control;
-       u8 future[3];
-       u8 tempslopextension[8];
+       u8 future[MAX_BASE_EXTENSION_FUTURE];
+       /*
+        * misc_enable:
+        *
+        * BIT 0   - TX Gain Cap enable.
+        * BIT 1   - Uncompressed Checksum enable.
+        * BIT 2/3 - MinCCApwr enable 2g/5g.
+        */
+       u8 misc_enable;
+       int8_t tempslopextension[8];
        int8_t quick_drop_low;
        int8_t quick_drop_high;
 } __packed;
index 29613ebbc5d730832b06bbfdf3fb11df32c858d8..ec1da0cc25f53b14412414f2d3aebef7eb1224cc 100644 (file)
@@ -28,6 +28,7 @@
 #include "ar9462_2p1_initvals.h"
 #include "ar9565_1p0_initvals.h"
 #include "ar9565_1p1_initvals.h"
+#include "ar953x_initvals.h"
 
 /* General hardware code for the AR9003 hadware family */
 
@@ -308,6 +309,31 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
                /* Fast clock modal settings */
                INIT_INI_ARRAY(&ah->iniModesFastClock,
                                ar955x_1p0_modes_fast_clock);
+       } else if (AR_SREV_9531(ah)) {
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                              qca953x_1p0_mac_core);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                              qca953x_1p0_mac_postamble);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                              qca953x_1p0_baseband_core);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                              qca953x_1p0_baseband_postamble);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                              qca953x_1p0_radio_core);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+                              qca953x_1p0_radio_postamble);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                              qca953x_1p0_soc_preamble);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                              qca953x_1p0_soc_postamble);
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                              qca953x_1p0_common_wo_xlna_rx_gain_table);
+               INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
+                              qca953x_1p0_common_wo_xlna_rx_gain_bounds);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                              qca953x_1p0_modes_no_xpa_tx_gain_table);
+               INIT_INI_ARRAY(&ah->iniModesFastClock,
+                              qca953x_1p0_modes_fast_clock);
        } else if (AR_SREV_9580(ah)) {
                /* mac */
                INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -485,6 +511,9 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
        else if (AR_SREV_9550(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                        ar955x_1p0_modes_xpa_tx_gain_table);
+       else if (AR_SREV_9531(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       qca953x_1p0_modes_xpa_tx_gain_table);
        else if (AR_SREV_9580(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                        ar9580_1p0_lowest_ob_db_tx_gain_table);
@@ -525,7 +554,14 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
        else if (AR_SREV_9550(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                        ar955x_1p0_modes_no_xpa_tx_gain_table);
-       else if (AR_SREV_9462_21(ah))
+       else if (AR_SREV_9531(ah)) {
+               if (AR_SREV_9531_11(ah))
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                                      qca953x_1p1_modes_no_xpa_tx_gain_table);
+               else
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                                      qca953x_1p0_modes_no_xpa_tx_gain_table);
+       } else if (AR_SREV_9462_21(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                        ar9462_2p1_modes_high_ob_db_tx_gain);
        else if (AR_SREV_9462_20(ah))
@@ -699,6 +735,11 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
                                ar955x_1p0_common_rx_gain_table);
                INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
                                ar955x_1p0_common_rx_gain_bounds);
+       } else if (AR_SREV_9531(ah)) {
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                              qca953x_1p0_common_rx_gain_table);
+               INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
+                              qca953x_1p0_common_rx_gain_bounds);
        } else if (AR_SREV_9580(ah))
                INIT_INI_ARRAY(&ah->iniModesRxGain,
                                ar9580_1p0_rx_gain_table);
@@ -744,6 +785,11 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
                        ar955x_1p0_common_wo_xlna_rx_gain_table);
                INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
                        ar955x_1p0_common_wo_xlna_rx_gain_bounds);
+       } else if (AR_SREV_9531(ah)) {
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                              qca953x_1p0_common_wo_xlna_rx_gain_table);
+               INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
+                              qca953x_1p0_common_wo_xlna_rx_gain_bounds);
        } else if (AR_SREV_9580(ah))
                INIT_INI_ARRAY(&ah->iniModesRxGain,
                        ar9580_1p0_wo_xlna_rx_gain_table);
@@ -872,6 +918,117 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
        }
 }
 
+static void ar9003_hw_init_hang_checks(struct ath_hw *ah)
+{
+       /*
+        * All chips support detection of BB/MAC hangs.
+        */
+       ah->config.hw_hang_checks |= HW_BB_WATCHDOG;
+       ah->config.hw_hang_checks |= HW_MAC_HANG;
+
+       /*
+        * This is not required for AR9580 1.0
+        */
+       if (AR_SREV_9300_22(ah))
+               ah->config.hw_hang_checks |= HW_PHYRESTART_CLC_WAR;
+
+       if (AR_SREV_9330(ah))
+               ah->bb_watchdog_timeout_ms = 85;
+       else
+               ah->bb_watchdog_timeout_ms = 25;
+}
+
+/*
+ * MAC HW hang check
+ * =================
+ *
+ * Signature: dcu_chain_state is 0x6 and dcu_complete_state is 0x1.
+ *
+ * The state of each DCU chain (mapped to TX queues) is available from these
+ * DMA debug registers:
+ *
+ * Chain 0 state : Bits 4:0   of AR_DMADBG_4
+ * Chain 1 state : Bits 9:5   of AR_DMADBG_4
+ * Chain 2 state : Bits 14:10 of AR_DMADBG_4
+ * Chain 3 state : Bits 19:15 of AR_DMADBG_4
+ * Chain 4 state : Bits 24:20 of AR_DMADBG_4
+ * Chain 5 state : Bits 29:25 of AR_DMADBG_4
+ * Chain 6 state : Bits 4:0   of AR_DMADBG_5
+ * Chain 7 state : Bits 9:5   of AR_DMADBG_5
+ * Chain 8 state : Bits 14:10 of AR_DMADBG_5
+ * Chain 9 state : Bits 19:15 of AR_DMADBG_5
+ *
+ * The DCU chain state "0x6" means "WAIT_FRDONE" - wait for TX frame to be done.
+ */
+
+#define NUM_STATUS_READS 50
+
+static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue)
+{
+       u32 dma_dbg_chain, dma_dbg_complete;
+       u8 dcu_chain_state, dcu_complete_state;
+       int i;
+
+       for (i = 0; i < NUM_STATUS_READS; i++) {
+               if (queue < 6)
+                       dma_dbg_chain = REG_READ(ah, AR_DMADBG_4);
+               else
+                       dma_dbg_chain = REG_READ(ah, AR_DMADBG_5);
+
+               dma_dbg_complete = REG_READ(ah, AR_DMADBG_6);
+
+               dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f;
+               dcu_complete_state = dma_dbg_complete & 0x3;
+
+               if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1))
+                       return false;
+       }
+
+       ath_dbg(ath9k_hw_common(ah), RESET,
+               "MAC Hang signature found for queue: %d\n", queue);
+
+       return true;
+}
+
+static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
+{
+       u32 dma_dbg_4, dma_dbg_5, dma_dbg_6, chk_dbg;
+       u8 dcu_chain_state, dcu_complete_state;
+       bool dcu_wait_frdone = false;
+       unsigned long chk_dcu = 0;
+       unsigned int i = 0;
+
+       dma_dbg_4 = REG_READ(ah, AR_DMADBG_4);
+       dma_dbg_5 = REG_READ(ah, AR_DMADBG_5);
+       dma_dbg_6 = REG_READ(ah, AR_DMADBG_6);
+
+       dcu_complete_state = dma_dbg_6 & 0x3;
+       if (dcu_complete_state != 0x1)
+               goto exit;
+
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (i < 6)
+                       chk_dbg = dma_dbg_4;
+               else
+                       chk_dbg = dma_dbg_5;
+
+               dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f;
+               if (dcu_chain_state == 0x6) {
+                       dcu_wait_frdone = true;
+                       chk_dcu |= BIT(i);
+               }
+       }
+
+       if ((dcu_complete_state == 0x1) && dcu_wait_frdone) {
+               for_each_set_bit(i, &chk_dcu, ATH9K_NUM_TX_QUEUES) {
+                       if (ath9k_hw_verify_hang(ah, i))
+                               return true;
+               }
+       }
+exit:
+       return false;
+}
+
 /* Sets up the AR9003 hardware familiy callbacks */
 void ar9003_hw_attach_ops(struct ath_hw *ah)
 {
@@ -880,6 +1037,8 @@ void ar9003_hw_attach_ops(struct ath_hw *ah)
 
        ar9003_hw_init_mode_regs(ah);
        priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
+       priv_ops->init_hang_checks = ar9003_hw_init_hang_checks;
+       priv_ops->detect_mac_hang = ar9003_hw_detect_mac_hang;
 
        ops->config_pci_powersave = ar9003_hw_configpcipowersave;
 
index f6c5c1b50471ee2f876d24238b6912182c449f13..729ffbf07343bb72c9313f037cc5965e58d8366f 100644 (file)
@@ -175,7 +175,8 @@ static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
        ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
 }
 
-static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked,
+                             u32 *sync_cause_p)
 {
        u32 isr = 0;
        u32 mask2 = 0;
@@ -310,7 +311,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                ar9003_mci_get_isr(ah, masked);
 
        if (sync_cause) {
-               ath9k_debug_sync_cause(common, sync_cause);
+               if (sync_cause_p)
+                       *sync_cause_p = sync_cause;
                fatal_int =
                        (sync_cause &
                         (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
@@ -476,12 +478,12 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
 
        /* XXX: Keycache */
        rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
-       rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
-       rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
-       rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
-       rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
-       rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
-       rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
+       rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
+       rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
+       rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
+       rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
+       rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
+       rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
 
        if (rxsp->status11 & AR_RxKeyIdxValid)
                rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
index 9f051a08e1431e4696d52536197752fd4d305918..09facba1dc6d8069583f0eb0fdf41e59d96a15f8 100644 (file)
@@ -103,7 +103,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
                        } else {
                                channelSel = CHANSEL_2G(freq) >> 1;
                        }
-               } else if (AR_SREV_9550(ah)) {
+               } else if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
                        if (ah->is_clk_25mhz)
                                div = 75;
                        else
@@ -118,7 +118,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
                /* Set to 2G mode */
                bMode = 1;
        } else {
-               if ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) &&
+               if ((AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) &&
                    ah->is_clk_25mhz) {
                        channelSel = freq / 75;
                        chan_frac = ((freq % 75) * 0x20000) / 75;
@@ -810,10 +810,12 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
        /*
         * TXGAIN initvals.
         */
-       if (AR_SREV_9550(ah)) {
-               int modes_txgain_index;
+       if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
+               int modes_txgain_index = 1;
+
+               if (AR_SREV_9550(ah))
+                       modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan);
 
-               modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan);
                if (modes_txgain_index < 0)
                        return -EINVAL;
 
@@ -1814,6 +1816,68 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
        memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs));
 }
 
+/*
+ * Baseband Watchdog signatures:
+ *
+ * 0x04000539: BB hang when operating in HT40 DFS Channel.
+ *             Full chip reset is not required, but a recovery
+ *             mechanism is needed.
+ *
+ * 0x1300000a: Related to CAC deafness.
+ *             Chip reset is not required.
+ *
+ * 0x0400000a: Related to CAC deafness.
+ *             Full chip reset is required.
+ *
+ * 0x04000b09: RX state machine gets into an illegal state
+ *             when a packet with unsupported rate is received.
+ *             Full chip reset is required and PHY_RESTART has
+ *             to be disabled.
+ *
+ * 0x04000409: Packet stuck on receive.
+ *             Full chip reset is required for all chips except AR9340.
+ */
+
+/*
+ * ar9003_hw_bb_watchdog_check(): Returns true if a chip reset is required.
+ */
+bool ar9003_hw_bb_watchdog_check(struct ath_hw *ah)
+{
+       u32 val;
+
+       switch(ah->bb_watchdog_last_status) {
+       case 0x04000539:
+               val = REG_READ(ah, AR_PHY_RADAR_0);
+               val &= (~AR_PHY_RADAR_0_FIRPWR);
+               val |= SM(0x7f, AR_PHY_RADAR_0_FIRPWR);
+               REG_WRITE(ah, AR_PHY_RADAR_0, val);
+               udelay(1);
+               val = REG_READ(ah, AR_PHY_RADAR_0);
+               val &= ~AR_PHY_RADAR_0_FIRPWR;
+               val |= SM(AR9300_DFS_FIRPWR, AR_PHY_RADAR_0_FIRPWR);
+               REG_WRITE(ah, AR_PHY_RADAR_0, val);
+
+               return false;
+       case 0x1300000a:
+               return false;
+       case 0x0400000a:
+       case 0x04000b09:
+               return true;
+       case 0x04000409:
+               if (AR_SREV_9340(ah) || AR_SREV_9531(ah))
+                       return false;
+               else
+                       return true;
+       default:
+               /*
+                * For any other unknown signatures, do a
+                * full chip reset.
+                */
+               return true;
+       }
+}
+EXPORT_SYMBOL(ar9003_hw_bb_watchdog_check);
+
 void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
@@ -1930,6 +1994,7 @@ EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info);
 
 void ar9003_hw_disable_phy_restart(struct ath_hw *ah)
 {
+       u8 result;
        u32 val;
 
        /* While receiving unsupported rate frame rx state machine
@@ -1937,15 +2002,13 @@ void ar9003_hw_disable_phy_restart(struct ath_hw *ah)
         * state, BB would go hang. If RXSM is in 0xb state after
         * first bb panic, ensure to disable the phy_restart.
         */
-       if (!((MS(ah->bb_watchdog_last_status,
-                 AR_PHY_WATCHDOG_RX_OFDM_SM) == 0xb) ||
-           ah->bb_hang_rx_ofdm))
-               return;
-
-       ah->bb_hang_rx_ofdm = true;
-       val = REG_READ(ah, AR_PHY_RESTART);
-       val &= ~AR_PHY_RESTART_ENA;
+       result = MS(ah->bb_watchdog_last_status, AR_PHY_WATCHDOG_RX_OFDM_SM);
 
-       REG_WRITE(ah, AR_PHY_RESTART, val);
+       if ((result == 0xb) || ah->bb_hang_rx_ofdm) {
+               ah->bb_hang_rx_ofdm = true;
+               val = REG_READ(ah, AR_PHY_RESTART);
+               val &= ~AR_PHY_RESTART_ENA;
+               REG_WRITE(ah, AR_PHY_RESTART, val);
+       }
 }
 EXPORT_SYMBOL(ar9003_hw_disable_phy_restart);
index bbbfc4dc59eb1e14f69fbd1e4c78eee38c3ad215..fd090b1f2d0ffd9ded907c412ae78abcac10dc87 100644 (file)
 #define AR_PHY_AGC              (AR_AGC_BASE + 0x14)
 #define AR_PHY_EXT_ATTEN_CTL_0  (AR_AGC_BASE + 0x18)
 #define AR_PHY_CCA_0            (AR_AGC_BASE + 0x1c)
-#define AR_PHY_EXT_CCA0         (AR_AGC_BASE + 0x20)
+#define AR_PHY_CCA_CTRL_0       (AR_AGC_BASE + 0x20)
 #define AR_PHY_RESTART          (AR_AGC_BASE + 0x24)
 
 /*
 #define AR_PHY_CCA_NOM_VAL_9300_5GHZ          -115
 #define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ     -125
 #define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ     -125
-#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95
-#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100
-
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -60
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -60
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ -95
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ -100
 
 #define AR9280_PHY_CCA_THRESH62_S   12
 #define AR_PHY_EXT_CCA0_THRESH62    0x000000FF
 #define AR_PHY_EXT_CCA0_THRESH62_S  0
+#define AR_PHY_EXT_CCA0_THRESH62_1    0x000001FF
+#define AR_PHY_EXT_CCA0_THRESH62_1_S  0
 #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK          0x0000003F
 #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S        0
 #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME           0x00001FC0
 #define AR_PHY_65NM_CH1_RXTX4       0x1650c
 #define AR_PHY_65NM_CH2_RXTX4       0x1690c
 
+#define AR_PHY_65NM_CH0_BB1         0x16140
+#define AR_PHY_65NM_CH0_BB2         0x16144
+#define AR_PHY_65NM_CH0_BB3         0x16148
+#define AR_PHY_65NM_CH1_BB1         0x16540
+#define AR_PHY_65NM_CH1_BB2         0x16544
+#define AR_PHY_65NM_CH1_BB3         0x16548
+#define AR_PHY_65NM_CH2_BB1         0x16940
+#define AR_PHY_65NM_CH2_BB2         0x16944
+#define AR_PHY_65NM_CH2_BB3         0x16948
+
 #define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3           0x00780000
 #define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3_S         19
 #define AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK         0x00000004
 #define AR_PHY_65NM_RXRF_AGC_AGC_OUT                   0x00000004
 #define AR_PHY_65NM_RXRF_AGC_AGC_OUT_S                 2
 
+#define AR9300_DFS_FIRPWR -28
+
 #endif  /* AR9003_PHY_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
new file mode 100644 (file)
index 0000000..3c9113d
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_953X_H
+#define INITVALS_953X_H
+
+#define qca953x_1p0_mac_postamble ar9300_2p2_mac_postamble
+
+#define qca953x_1p0_soc_postamble ar9300_2p2_soc_postamble
+
+#define qca953x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2
+
+#define qca953x_1p0_common_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2
+
+#define qca953x_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2
+
+static const u32 qca953x_1p0_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x00020085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c22},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00a00000},
+       {0x000080d8, 0x00400000},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008140, 0x000000fe},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x000081c0, 0x00000000},
+       {0x000081c4, 0x33332210},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f3d7},
+       {0x00008248, 0x00000852},
+       {0x0000824c, 0x0001e7ae},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x9d400010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00001d40},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x0000001f},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0xffff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48107b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a0, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x8c7901ff},
+};
+
+static const u32 qca953x_1p0_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a9f6b},
+       {0x0000980c, 0x04900000},
+       {0x00009814, 0x0280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x6400a190},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x14000600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098bc, 0x00000002},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0xff55ff55},
+       {0x00009c08, 0x0320ff55},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x9883800a},
+       {0x00009d10, 0x01884061},
+       {0x00009d14, 0x00c0040b},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038230c},
+       {0x00009e24, 0x990bb515},
+       {0x00009e28, 0x0c6f0000},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009fc0, 0x813e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x00009fd0, 0x01193b91},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a248, 0x00000140},
+       {0x0000a2a0, 0x00000007},
+       {0x0000a2c0, 0x00000007},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x1f020503},
+       {0x0000a39c, 0x29180c03},
+       {0x0000a3a0, 0x9a8b6844},
+       {0x0000a3a4, 0x000000ff},
+       {0x0000a3a8, 0x6a6a6a6a},
+       {0x0000a3ac, 0x6a6a6a6a},
+       {0x0000a3b0, 0x00c8641a},
+       {0x0000a3b4, 0x0000001a},
+       {0x0000a3b8, 0x0088642a},
+       {0x0000a3bc, 0x000001fa},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000000},
+       {0x0000a3f8, 0x0c9bd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce42108},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce73908},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce738e7},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00100000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x05000080},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a644, 0xbfad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x08000838},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000000},
+       {0x0000a8d0, 0x004b6a8e},
+       {0x0000a8d4, 0x00000820},
+       {0x0000a8dc, 0x00000000},
+       {0x0000a8f0, 0x00000000},
+       {0x0000a8f4, 0x00000000},
+       {0x0000b2d0, 0x00000080},
+       {0x0000b2d4, 0x00000000},
+       {0x0000b2ec, 0x00000000},
+       {0x0000b2f0, 0x00000000},
+       {0x0000b2f4, 0x00000000},
+       {0x0000b2f8, 0x00000000},
+       {0x0000b408, 0x0e79e5c0},
+       {0x0000b40c, 0x00820820},
+       {0x0000b420, 0x00000000},
+};
+
+static const u32 qca953x_1p0_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+       {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+       {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+       {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+       {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+       {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822},
+       {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01010e0e, 0x01010e0e},
+       {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+       {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+       {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
+       {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
+       {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+};
+
+static const u32 qca953x_1p0_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73f00000},
+       {0x0001600c, 0x00000000},
+       {0x00016040, 0x3f80fff8},
+       {0x0001604c, 0x000f0278},
+       {0x00016050, 0x8036db6c},
+       {0x00016054, 0x6db60000},
+       {0x00016080, 0x00080000},
+       {0x00016084, 0x0e48048c},
+       {0x00016088, 0x14214514},
+       {0x0001608c, 0x119f080a},
+       {0x00016090, 0x24926490},
+       {0x00016094, 0x00000000},
+       {0x000160a0, 0xc2108ffe},
+       {0x000160a4, 0x812fc370},
+       {0x000160a8, 0x423c8000},
+       {0x000160b4, 0x92480080},
+       {0x000160c0, 0x006db6d8},
+       {0x000160c4, 0x24b6db6c},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x6db6fb7c},
+       {0x000160d0, 0x6db6da44},
+       {0x00016100, 0x07ff8001},
+       {0x00016108, 0x00080010},
+       {0x00016144, 0x01884080},
+       {0x00016148, 0x000080d8},
+       {0x00016280, 0x01000901},
+       {0x00016284, 0x15d30000},
+       {0x00016288, 0x00318000},
+       {0x0001628c, 0x50000000},
+       {0x00016380, 0x00000000},
+       {0x00016384, 0x00000000},
+       {0x00016388, 0x00800700},
+       {0x0001638c, 0x00800700},
+       {0x00016390, 0x00800700},
+       {0x00016394, 0x00000000},
+       {0x00016398, 0x00000000},
+       {0x0001639c, 0x00000000},
+       {0x000163a0, 0x00000001},
+       {0x000163a4, 0x00000001},
+       {0x000163a8, 0x00000000},
+       {0x000163ac, 0x00000000},
+       {0x000163b0, 0x00000000},
+       {0x000163b4, 0x00000000},
+       {0x000163b8, 0x00000000},
+       {0x000163bc, 0x00000000},
+       {0x000163c0, 0x000000a0},
+       {0x000163c4, 0x000c0000},
+       {0x000163c8, 0x14021402},
+       {0x000163cc, 0x00001402},
+       {0x000163d0, 0x00000000},
+       {0x000163d4, 0x00000000},
+       {0x00016400, 0x36db6db6},
+       {0x00016404, 0x6db6db40},
+       {0x00016408, 0x73f00000},
+       {0x0001640c, 0x00000000},
+       {0x00016440, 0x3f80fff8},
+       {0x0001644c, 0x000f0278},
+       {0x00016450, 0x8036db6c},
+       {0x00016454, 0x6db60000},
+       {0x00016500, 0x07ff8001},
+       {0x00016508, 0x00080010},
+       {0x00016544, 0x01884080},
+       {0x00016548, 0x000080d8},
+       {0x00016780, 0x00000000},
+       {0x00016784, 0x00000000},
+       {0x00016788, 0x00800700},
+       {0x0001678c, 0x00800700},
+       {0x00016790, 0x00800700},
+       {0x00016794, 0x00000000},
+       {0x00016798, 0x00000000},
+       {0x0001679c, 0x00000000},
+       {0x000167a0, 0x00000001},
+       {0x000167a4, 0x00000001},
+       {0x000167a8, 0x00000000},
+       {0x000167ac, 0x00000000},
+       {0x000167b0, 0x00000000},
+       {0x000167b4, 0x00000000},
+       {0x000167b8, 0x00000000},
+       {0x000167bc, 0x00000000},
+       {0x000167c0, 0x000000a0},
+       {0x000167c4, 0x000c0000},
+       {0x000167c8, 0x14021402},
+       {0x000167cc, 0x00001402},
+       {0x000167d0, 0x00000000},
+       {0x000167d4, 0x00000000},
+};
+
+static const u32 qca953x_1p0_radio_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xc4128f5c, 0xc4128f5c},
+       {0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x0fd08f25, 0x0fd08f25},
+       {0x000160ac, 0xa4647c00, 0xa4647c00, 0x24646800, 0x24646800},
+       {0x000160b0, 0x01885f52, 0x01885f52, 0x00fe7f46, 0x00fe7f46},
+       {0x00016104, 0xb7a00001, 0xb7a00001, 0xfff80005, 0xfff80005},
+       {0x0001610c, 0xc0000000, 0xc0000000, 0x00000000, 0x00000000},
+       {0x00016140, 0x10804008, 0x10804008, 0x50804000, 0x50804000},
+       {0x00016504, 0xb7a00001, 0xb7a00001, 0xfff80001, 0xfff80001},
+       {0x0001650c, 0xc0000000, 0xc0000000, 0x00000000, 0x00000000},
+       {0x00016540, 0x10804008, 0x10804008, 0x50804000, 0x50804000},
+};
+
+static const u32 qca953x_1p0_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x00007000, 0x00000000},
+       {0x00007004, 0x00000000},
+       {0x00007008, 0x00000000},
+       {0x0000700c, 0x00000000},
+       {0x0000701c, 0x00000000},
+       {0x00007020, 0x00000000},
+       {0x00007024, 0x00000000},
+       {0x00007028, 0x00000000},
+       {0x0000702c, 0x00000000},
+       {0x00007030, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+       {0x00007048, 0x00000000},
+};
+
+static const u32 qca953x_1p0_common_rx_gain_bounds[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018},
+};
+
+static const u32 qca953x_1p0_common_wo_xlna_rx_gain_bounds[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+};
+
+static const u32 qca953x_1p0_modes_xpa_tx_gain_table[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a2dc, 0xfffd5aaa},
+       {0x0000a2e0, 0xfffe9ccc},
+       {0x0000a2e4, 0xffffe0f0},
+       {0x0000a2e8, 0xfffcff00},
+       {0x0000a410, 0x000050da},
+       {0x0000a500, 0x00000000},
+       {0x0000a504, 0x04000002},
+       {0x0000a508, 0x08000004},
+       {0x0000a50c, 0x0c000006},
+       {0x0000a510, 0x0f00000a},
+       {0x0000a514, 0x1300000c},
+       {0x0000a518, 0x1700000e},
+       {0x0000a51c, 0x1b000064},
+       {0x0000a520, 0x1f000242},
+       {0x0000a524, 0x23000229},
+       {0x0000a528, 0x270002a2},
+       {0x0000a52c, 0x2c001203},
+       {0x0000a530, 0x30001803},
+       {0x0000a534, 0x33000881},
+       {0x0000a538, 0x38001809},
+       {0x0000a53c, 0x3a000814},
+       {0x0000a540, 0x3f001a0c},
+       {0x0000a544, 0x43001a0e},
+       {0x0000a548, 0x46001812},
+       {0x0000a54c, 0x49001884},
+       {0x0000a550, 0x4d001e84},
+       {0x0000a554, 0x50001e69},
+       {0x0000a558, 0x550006f4},
+       {0x0000a55c, 0x59000ad3},
+       {0x0000a560, 0x5e000ad5},
+       {0x0000a564, 0x61001ced},
+       {0x0000a568, 0x660018d4},
+       {0x0000a56c, 0x660018d4},
+       {0x0000a570, 0x660018d4},
+       {0x0000a574, 0x660018d4},
+       {0x0000a578, 0x660018d4},
+       {0x0000a57c, 0x660018d4},
+       {0x0000a600, 0x00000000},
+       {0x0000a604, 0x00000000},
+       {0x0000a608, 0x00000000},
+       {0x0000a60c, 0x03804000},
+       {0x0000a610, 0x0300ca02},
+       {0x0000a614, 0x00000e04},
+       {0x0000a618, 0x03014000},
+       {0x0000a61c, 0x00000000},
+       {0x0000a620, 0x00000000},
+       {0x0000a624, 0x03014000},
+       {0x0000a628, 0x03804c05},
+       {0x0000a62c, 0x0701de06},
+       {0x0000a630, 0x07819c07},
+       {0x0000a634, 0x0701dc07},
+       {0x0000a638, 0x0701dc07},
+       {0x0000a63c, 0x0701dc07},
+       {0x0000b2dc, 0xfffd5aaa},
+       {0x0000b2e0, 0xfffe9ccc},
+       {0x0000b2e4, 0xffffe0f0},
+       {0x0000b2e8, 0xfffcff00},
+       {0x00016044, 0x010002d4},
+       {0x00016048, 0x66482400},
+       {0x00016280, 0x01000015},
+       {0x00016444, 0x010002d4},
+       {0x00016448, 0x66482400},
+};
+
+static const u32 qca953x_1p0_modes_no_xpa_tx_gain_table[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a2dc, 0xffd5f552},
+       {0x0000a2e0, 0xffe60664},
+       {0x0000a2e4, 0xfff80780},
+       {0x0000a2e8, 0xfffff800},
+       {0x0000a410, 0x000050d6},
+       {0x0000a500, 0x00060020},
+       {0x0000a504, 0x04060060},
+       {0x0000a508, 0x080600a0},
+       {0x0000a50c, 0x0c068020},
+       {0x0000a510, 0x10068060},
+       {0x0000a514, 0x140680a0},
+       {0x0000a518, 0x18090040},
+       {0x0000a51c, 0x1b090080},
+       {0x0000a520, 0x1f0900c0},
+       {0x0000a524, 0x240c0041},
+       {0x0000a528, 0x280d0021},
+       {0x0000a52c, 0x2d0f0061},
+       {0x0000a530, 0x310f00a1},
+       {0x0000a534, 0x350e00a2},
+       {0x0000a538, 0x360e80a2},
+       {0x0000a53c, 0x380f00a2},
+       {0x0000a540, 0x3b0e00a3},
+       {0x0000a544, 0x3d110083},
+       {0x0000a548, 0x3e1100a3},
+       {0x0000a54c, 0x401100e3},
+       {0x0000a550, 0x421380e3},
+       {0x0000a554, 0x431780e3},
+       {0x0000a558, 0x461f80e3},
+       {0x0000a55c, 0x461f80e3},
+       {0x0000a560, 0x461f80e3},
+       {0x0000a564, 0x461f80e3},
+       {0x0000a568, 0x461f80e3},
+       {0x0000a56c, 0x461f80e3},
+       {0x0000a570, 0x461f80e3},
+       {0x0000a574, 0x461f80e3},
+       {0x0000a578, 0x461f80e3},
+       {0x0000a57c, 0x461f80e3},
+       {0x0000a600, 0x00000000},
+       {0x0000a604, 0x00000000},
+       {0x0000a608, 0x00000000},
+       {0x0000a60c, 0x00804201},
+       {0x0000a610, 0x01008201},
+       {0x0000a614, 0x0180c402},
+       {0x0000a618, 0x0180c603},
+       {0x0000a61c, 0x0180c603},
+       {0x0000a620, 0x01c10603},
+       {0x0000a624, 0x01c10704},
+       {0x0000a628, 0x02c18b05},
+       {0x0000a62c, 0x0301cc07},
+       {0x0000a630, 0x0301cc07},
+       {0x0000a634, 0x0301cc07},
+       {0x0000a638, 0x0301cc07},
+       {0x0000a63c, 0x0301cc07},
+       {0x0000b2dc, 0xffd5f552},
+       {0x0000b2e0, 0xffe60664},
+       {0x0000b2e4, 0xfff80780},
+       {0x0000b2e8, 0xfffff800},
+       {0x00016044, 0x049242db},
+       {0x00016048, 0x6c927a70},
+       {0x00016444, 0x049242db},
+       {0x00016448, 0x6c927a70},
+};
+
+static const u32 qca953x_1p1_modes_no_xpa_tx_gain_table[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a2dc, 0xffd5f552},
+       {0x0000a2e0, 0xffe60664},
+       {0x0000a2e4, 0xfff80780},
+       {0x0000a2e8, 0xfffff800},
+       {0x0000a410, 0x000050de},
+       {0x0000a500, 0x00000061},
+       {0x0000a504, 0x04000063},
+       {0x0000a508, 0x08000065},
+       {0x0000a50c, 0x0c000261},
+       {0x0000a510, 0x10000263},
+       {0x0000a514, 0x14000265},
+       {0x0000a518, 0x18000482},
+       {0x0000a51c, 0x1b000484},
+       {0x0000a520, 0x1f000486},
+       {0x0000a524, 0x240008c2},
+       {0x0000a528, 0x28000cc1},
+       {0x0000a52c, 0x2d000ce3},
+       {0x0000a530, 0x31000ce5},
+       {0x0000a534, 0x350010e5},
+       {0x0000a538, 0x360012e5},
+       {0x0000a53c, 0x380014e5},
+       {0x0000a540, 0x3b0018e5},
+       {0x0000a544, 0x3d001d04},
+       {0x0000a548, 0x3e001d05},
+       {0x0000a54c, 0x40001d07},
+       {0x0000a550, 0x42001f27},
+       {0x0000a554, 0x43001f67},
+       {0x0000a558, 0x46001fe7},
+       {0x0000a55c, 0x47001f2b},
+       {0x0000a560, 0x49001f0d},
+       {0x0000a564, 0x4b001ed2},
+       {0x0000a568, 0x4c001ed4},
+       {0x0000a56c, 0x4e001f15},
+       {0x0000a570, 0x4f001ff6},
+       {0x0000a574, 0x4f001ff6},
+       {0x0000a578, 0x4f001ff6},
+       {0x0000a57c, 0x4f001ff6},
+       {0x0000a600, 0x00000000},
+       {0x0000a604, 0x00000000},
+       {0x0000a608, 0x00000000},
+       {0x0000a60c, 0x00804201},
+       {0x0000a610, 0x01008201},
+       {0x0000a614, 0x0180c402},
+       {0x0000a618, 0x0180c603},
+       {0x0000a61c, 0x0180c603},
+       {0x0000a620, 0x01c10603},
+       {0x0000a624, 0x01c10704},
+       {0x0000a628, 0x02c18b05},
+       {0x0000a62c, 0x02c14c07},
+       {0x0000a630, 0x01008704},
+       {0x0000a634, 0x01c10402},
+       {0x0000a638, 0x0301cc07},
+       {0x0000a63c, 0x0301cc07},
+       {0x0000b2dc, 0xffd5f552},
+       {0x0000b2e0, 0xffe60664},
+       {0x0000b2e4, 0xfff80780},
+       {0x0000b2e8, 0xfffff800},
+       {0x00016044, 0x049242db},
+       {0x00016048, 0x6c927a70},
+       {0x00016444, 0x049242db},
+       {0x00016448, 0x6c927a70},
+};
+
+#endif /* INITVALS_953X_H */
index 5e5d5cb2458c0a9c492b8ea74aaf83bcc91a4568..f622a986c8cc8f0df8a98b12ea4f05580faa27ec 100644 (file)
 #include "common.h"
 #include "mci.h"
 #include "dfs.h"
-
-/*
- * Header for the ath9k.ko driver core *only* -- hw code nor any other driver
- * should rely on this file or its contents.
- */
+#include "spectral.h"
 
 struct ath_node;
+struct ath_rate_table;
 
-/* Macro to expand scalars to 64-bit objects */
-
-#define        ito64(x) (sizeof(x) == 1) ?                     \
-       (((unsigned long long int)(x)) & (0xff)) :      \
-       (sizeof(x) == 2) ?                              \
-       (((unsigned long long int)(x)) & 0xffff) :      \
-       ((sizeof(x) == 4) ?                             \
-        (((unsigned long long int)(x)) & 0xffffffff) : \
-        (unsigned long long int)(x))
-
-/* increment with wrap-around */
-#define INCR(_l, _sz)   do {                   \
-               (_l)++;                         \
-               (_l) &= ((_sz) - 1);            \
-       } while (0)
-
-/* decrement with wrap-around */
-#define DECR(_l,  _sz)  do {                   \
-               (_l)--;                         \
-               (_l) &= ((_sz) - 1);            \
-       } while (0)
-
-#define TSF_TO_TU(_h,_l) \
-       ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
-
-#define        ATH_TXQ_SETUP(sc, i)        ((sc)->tx.txqsetup & (1<<i))
+extern struct ieee80211_ops ath9k_ops;
+extern int ath9k_modparam_nohwcrypt;
+extern int led_blink;
+extern bool is_ath9k_unloaded;
 
 struct ath_config {
        u16 txpowlimit;
@@ -70,6 +45,17 @@ struct ath_config {
 /* Descriptor Management */
 /*************************/
 
+#define ATH_TXSTATUS_RING_SIZE 512
+
+/* Macro to expand scalars to 64-bit objects */
+#define        ito64(x) (sizeof(x) == 1) ?                     \
+       (((unsigned long long int)(x)) & (0xff)) :      \
+       (sizeof(x) == 2) ?                              \
+       (((unsigned long long int)(x)) & 0xffff) :      \
+       ((sizeof(x) == 4) ?                             \
+        (((unsigned long long int)(x)) & 0xffffffff) : \
+        (unsigned long long int)(x))
+
 #define ATH_TXBUF_RESET(_bf) do {                              \
                (_bf)->bf_lastbf = NULL;                        \
                (_bf)->bf_next = NULL;                          \
@@ -77,23 +63,6 @@ struct ath_config {
                       sizeof(struct ath_buf_state));           \
        } while (0)
 
-/**
- * enum buffer_type - Buffer type flags
- *
- * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
- * @BUF_AGGR: Indicates whether the buffer can be aggregated
- *     (used in aggregation scheduling)
- */
-enum buffer_type {
-       BUF_AMPDU               = BIT(0),
-       BUF_AGGR                = BIT(1),
-};
-
-#define bf_isampdu(bf)         (bf->bf_state.bf_type & BUF_AMPDU)
-#define bf_isaggr(bf)          (bf->bf_state.bf_type & BUF_AGGR)
-
-#define ATH_TXSTATUS_RING_SIZE 512
-
 #define        DS2PHYS(_dd, _ds)                                               \
        ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
 #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
@@ -113,11 +82,20 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 /* RX / TX */
 /***********/
 
+#define        ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
+
+/* increment with wrap-around */
+#define INCR(_l, _sz)   do {                   \
+               (_l)++;                         \
+               (_l) &= ((_sz) - 1);            \
+       } while (0)
+
 #define ATH_RXBUF               512
 #define ATH_TXBUF               512
 #define ATH_TXBUF_RESERVE       5
 #define ATH_MAX_QDEPTH          (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
 #define ATH_TXMAXTRY            13
+#define ATH_MAX_SW_RETRIES      30
 
 #define TID_TO_WME_AC(_tid)                            \
        ((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE :   \
@@ -133,6 +111,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 #define ATH_AGGR_MIN_QDEPTH        2
 /* minimum h/w qdepth for non-aggregated traffic */
 #define ATH_NON_AGGR_MIN_QDEPTH    8
+#define ATH_TX_COMPLETE_POLL_INT   1000
+#define ATH_TXFIFO_DEPTH           8
+#define ATH_TX_ERROR               0x01
 
 #define IEEE80211_SEQ_SEQ_SHIFT    4
 #define IEEE80211_SEQ_MAX          4096
@@ -167,9 +148,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 
 #define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e))
 
-#define ATH_TX_COMPLETE_POLL_INT       1000
-
-#define ATH_TXFIFO_DEPTH 8
 struct ath_txq {
        int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
        u32 axq_qnum; /* ath9k hardware queue number */
@@ -214,6 +192,21 @@ struct ath_rxbuf {
        dma_addr_t bf_buf_addr;
 };
 
+/**
+ * enum buffer_type - Buffer type flags
+ *
+ * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
+ * @BUF_AGGR: Indicates whether the buffer can be aggregated
+ *     (used in aggregation scheduling)
+ */
+enum buffer_type {
+       BUF_AMPDU               = BIT(0),
+       BUF_AGGR                = BIT(1),
+};
+
+#define bf_isampdu(bf)         (bf->bf_state.bf_type & BUF_AMPDU)
+#define bf_isaggr(bf)          (bf->bf_state.bf_type & BUF_AGGR)
+
 struct ath_buf_state {
        u8 bf_type;
        u8 bfs_paprd;
@@ -278,7 +271,6 @@ struct ath_tx_control {
        struct ieee80211_sta *sta;
 };
 
-#define ATH_TX_ERROR        0x01
 
 /**
  * @txq_map:  Index is mac80211 queue number.  This is
@@ -372,6 +364,22 @@ struct ath_vif {
        struct ath_buf *av_bcbuf;
 };
 
+struct ath9k_vif_iter_data {
+       u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
+       u8 mask[ETH_ALEN]; /* bssid mask */
+       bool has_hw_macaddr;
+
+       int naps;      /* number of AP vifs */
+       int nmeshes;   /* number of mesh vifs */
+       int nstations; /* number of station vifs */
+       int nwds;      /* number of WDS vifs */
+       int nadhocs;   /* number of adhoc vifs */
+};
+
+void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+                              struct ieee80211_vif *vif,
+                              struct ath9k_vif_iter_data *iter_data);
+
 /*******************/
 /* Beacon Handling */
 /*******************/
@@ -387,6 +395,9 @@ struct ath_vif {
 #define ATH_DEFAULT_BMISS_LIMIT        10
 #define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
 
+#define TSF_TO_TU(_h,_l) \
+       ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
+
 struct ath_beacon_config {
        int beacon_interval;
        u16 listen_interval;
@@ -420,12 +431,10 @@ struct ath_beacon {
 };
 
 void ath9k_beacon_tasklet(unsigned long data);
-bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
 void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
                         u32 changed);
 void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
 void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
-void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif);
 void ath9k_set_beacon(struct ath_softc *sc);
 bool ath9k_csa_is_finished(struct ath_softc *sc);
 
@@ -440,17 +449,14 @@ bool ath9k_csa_is_finished(struct ath_softc *sc);
 #define ATH_LONG_CALINTERVAL_INT  1000    /* 1000 ms */
 #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
 #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
-#define ATH_ANI_MAX_SKIP_COUNT  10
-
-#define ATH_PAPRD_TIMEOUT      100 /* msecs */
-#define ATH_PLL_WORK_INTERVAL   100
+#define ATH_ANI_MAX_SKIP_COUNT    10
+#define ATH_PAPRD_TIMEOUT         100 /* msecs */
+#define ATH_PLL_WORK_INTERVAL     100
 
 void ath_tx_complete_poll_work(struct work_struct *work);
 void ath_reset_work(struct work_struct *work);
-void ath_hw_check(struct work_struct *work);
+bool ath_hw_check(struct ath_softc *sc);
 void ath_hw_pll_work(struct work_struct *work);
-void ath_rx_poll(unsigned long data);
-void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon);
 void ath_paprd_calibrate(struct work_struct *work);
 void ath_ani_calibrate(unsigned long data);
 void ath_start_ani(struct ath_softc *sc);
@@ -477,20 +483,19 @@ enum bt_op_flags {
 };
 
 struct ath_btcoex {
-       bool hw_timer_enabled;
        spinlock_t btcoex_lock;
        struct timer_list period_timer; /* Timer for BT period */
+       struct timer_list no_stomp_timer;
        u32 bt_priority_cnt;
        unsigned long bt_priority_time;
        unsigned long op_flags;
        int bt_stomp_type; /* Types of BT stomping */
-       u32 btcoex_no_stomp; /* in usec */
+       u32 btcoex_no_stomp; /* in msec */
        u32 btcoex_period; /* in msec */
-       u32 btscan_no_stomp; /* in usec */
+       u32 btscan_no_stomp; /* in msec */
        u32 duty_cycle;
        u32 bt_wait_time;
        int rssi_count;
-       struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
        struct ath_mci_profile mci;
        u8 stomp_audio;
 };
@@ -538,12 +543,6 @@ static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
 }
 #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
 
-struct ath9k_wow_pattern {
-       u8 pattern_bytes[MAX_PATTERN_SIZE];
-       u8 mask_bytes[MAX_PATTERN_SIZE];
-       u32 pattern_len;
-};
-
 /********************/
 /*   LED Control    */
 /********************/
@@ -575,6 +574,12 @@ static inline void ath_fill_led_pin(struct ath_softc *sc)
 /* Wake on Wireless LAN */
 /************************/
 
+struct ath9k_wow_pattern {
+       u8 pattern_bytes[MAX_PATTERN_SIZE];
+       u8 mask_bytes[MAX_PATTERN_SIZE];
+       u32 pattern_len;
+};
+
 #ifdef CONFIG_ATH9K_WOW
 void ath9k_init_wow(struct ieee80211_hw *hw);
 int ath9k_suspend(struct ieee80211_hw *hw,
@@ -678,13 +683,8 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
  * Used when PCI device not fully initialized by bootrom/BIOS
 */
 #define DEFAULT_CACHELINE       32
-#define ATH_REGCLASSIDS_MAX     10
 #define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
-#define ATH_MAX_SW_RETRIES      30
-#define ATH_CHAN_MAX            255
-
 #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
-#define ATH_RATE_DUMMY_MARKER   0
 
 enum sc_op_flags {
        SC_OP_INVALID,
@@ -703,37 +703,6 @@ enum sc_op_flags {
 #define PS_BEACON_SYNC            BIT(4)
 #define PS_WAIT_FOR_ANI           BIT(5)
 
-struct ath_rate_table;
-
-struct ath9k_vif_iter_data {
-       u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
-       u8 mask[ETH_ALEN]; /* bssid mask */
-       bool has_hw_macaddr;
-
-       int naps;      /* number of AP vifs */
-       int nmeshes;   /* number of mesh vifs */
-       int nstations; /* number of station vifs */
-       int nwds;      /* number of WDS vifs */
-       int nadhocs;   /* number of adhoc vifs */
-};
-
-/* enum spectral_mode:
- *
- * @SPECTRAL_DISABLED: spectral mode is disabled
- * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
- *     something else.
- * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
- *     is performed manually.
- * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels
- *     during a channel scan.
- */
-enum spectral_mode {
-       SPECTRAL_DISABLED = 0,
-       SPECTRAL_BACKGROUND,
-       SPECTRAL_MANUAL,
-       SPECTRAL_CHANSCAN,
-};
-
 struct ath_softc {
        struct ieee80211_hw *hw;
        struct device *dev;
@@ -751,12 +720,10 @@ struct ath_softc {
        spinlock_t sc_pcu_lock;
        struct mutex mutex;
        struct work_struct paprd_work;
-       struct work_struct hw_check_work;
        struct work_struct hw_reset_work;
        struct completion paprd_complete;
        wait_queue_head_t tx_wait;
 
-       unsigned int hw_busy_count;
        unsigned long sc_flags;
        unsigned long driver_data;
 
@@ -790,7 +757,6 @@ struct ath_softc {
        struct ath_beacon_config cur_beacon_conf;
        struct delayed_work tx_complete_work;
        struct delayed_work hw_pll_work;
-       struct timer_list rx_poll_timer;
        struct timer_list sleep_timer;
 
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
@@ -823,162 +789,6 @@ struct ath_softc {
 #endif
 };
 
-#define SPECTRAL_SCAN_BITMASK          0x10
-/* Radar info packet format, used for DFS and spectral formats. */
-struct ath_radar_info {
-       u8 pulse_length_pri;
-       u8 pulse_length_ext;
-       u8 pulse_bw_info;
-} __packed;
-
-/* The HT20 spectral data has 4 bytes of additional information at it's end.
- *
- * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]}
- * [7:0]: all bins  max_magnitude[9:2]
- * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]}
- * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
- */
-struct ath_ht20_mag_info {
-       u8 all_bins[3];
-       u8 max_exp;
-} __packed;
-
-#define SPECTRAL_HT20_NUM_BINS         56
-
-/* WARNING: don't actually use this struct! MAC may vary the amount of
- * data by -1/+2. This struct is for reference only.
- */
-struct ath_ht20_fft_packet {
-       u8 data[SPECTRAL_HT20_NUM_BINS];
-       struct ath_ht20_mag_info mag_info;
-       struct ath_radar_info radar_info;
-} __packed;
-
-#define SPECTRAL_HT20_TOTAL_DATA_LEN   (sizeof(struct ath_ht20_fft_packet))
-
-/* Dynamic 20/40 mode:
- *
- * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]}
- * [7:0]: lower bins  max_magnitude[9:2]
- * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]}
- * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]}
- * [7:0]: upper bins  max_magnitude[9:2]
- * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]}
- * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
- */
-struct ath_ht20_40_mag_info {
-       u8 lower_bins[3];
-       u8 upper_bins[3];
-       u8 max_exp;
-} __packed;
-
-#define SPECTRAL_HT20_40_NUM_BINS              128
-
-/* WARNING: don't actually use this struct! MAC may vary the amount of
- * data. This struct is for reference only.
- */
-struct ath_ht20_40_fft_packet {
-       u8 data[SPECTRAL_HT20_40_NUM_BINS];
-       struct ath_ht20_40_mag_info mag_info;
-       struct ath_radar_info radar_info;
-} __packed;
-
-
-#define SPECTRAL_HT20_40_TOTAL_DATA_LEN        (sizeof(struct ath_ht20_40_fft_packet))
-
-/* grabs the max magnitude from the all/upper/lower bins */
-static inline u16 spectral_max_magnitude(u8 *bins)
-{
-       return (bins[0] & 0xc0) >> 6 |
-              (bins[1] & 0xff) << 2 |
-              (bins[2] & 0x03) << 10;
-}
-
-/* return the max magnitude from the all/upper/lower bins */
-static inline u8 spectral_max_index(u8 *bins)
-{
-       s8 m = (bins[2] & 0xfc) >> 2;
-
-       /* TODO: this still doesn't always report the right values ... */
-       if (m > 32)
-               m |= 0xe0;
-       else
-               m &= ~0xe0;
-
-       return m + 29;
-}
-
-/* return the bitmap weight from the all/upper/lower bins */
-static inline u8 spectral_bitmap_weight(u8 *bins)
-{
-       return bins[0] & 0x3f;
-}
-
-/* FFT sample format given to userspace via debugfs.
- *
- * Please keep the type/length at the front position and change
- * other fields after adding another sample type
- *
- * TODO: this might need rework when switching to nl80211-based
- * interface.
- */
-enum ath_fft_sample_type {
-       ATH_FFT_SAMPLE_HT20 = 1,
-       ATH_FFT_SAMPLE_HT20_40,
-};
-
-struct fft_sample_tlv {
-       u8 type;        /* see ath_fft_sample */
-       __be16 length;
-       /* type dependent data follows */
-} __packed;
-
-struct fft_sample_ht20 {
-       struct fft_sample_tlv tlv;
-
-       u8 max_exp;
-
-       __be16 freq;
-       s8 rssi;
-       s8 noise;
-
-       __be16 max_magnitude;
-       u8 max_index;
-       u8 bitmap_weight;
-
-       __be64 tsf;
-
-       u8 data[SPECTRAL_HT20_NUM_BINS];
-} __packed;
-
-struct fft_sample_ht20_40 {
-       struct fft_sample_tlv tlv;
-
-       u8 channel_type;
-       __be16 freq;
-
-       s8 lower_rssi;
-       s8 upper_rssi;
-
-       __be64 tsf;
-
-       s8 lower_noise;
-       s8 upper_noise;
-
-       __be16 lower_max_magnitude;
-       __be16 upper_max_magnitude;
-
-       u8 lower_max_index;
-       u8 upper_max_index;
-
-       u8 lower_bitmap_weight;
-       u8 upper_bitmap_weight;
-
-       u8 max_exp;
-
-       u8 data[SPECTRAL_HT20_40_NUM_BINS];
-} __packed;
-
 /********/
 /* TX99 */
 /********/
@@ -999,19 +809,13 @@ static inline int ath9k_tx99_send(struct ath_softc *sc,
 }
 #endif /* CONFIG_ATH9K_TX99 */
 
-void ath9k_tasklet(unsigned long data);
-int ath_cabq_update(struct ath_softc *);
-
 static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 {
        common->bus_ops->read_cachesize(common, csz);
 }
 
-extern struct ieee80211_ops ath9k_ops;
-extern int ath9k_modparam_nohwcrypt;
-extern int led_blink;
-extern bool is_ath9k_unloaded;
-
+void ath9k_tasklet(unsigned long data);
+int ath_cabq_update(struct ath_softc *);
 u8 ath9k_parse_mpdudensity(u8 mpdudensity);
 irqreturn_t ath_isr(int irq, void *dev);
 int ath_reset(struct ath_softc *sc);
@@ -1020,13 +824,12 @@ void ath_restart_work(struct ath_softc *sc);
 int ath9k_init_device(u16 devid, struct ath_softc *sc,
                    const struct ath_bus_ops *bus_ops);
 void ath9k_deinit_device(struct ath_softc *sc);
-void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
 void ath9k_reload_chainmask_settings(struct ath_softc *sc);
-
-void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw);
-int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
-                              enum spectral_mode spectral_mode);
-
+u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
+void ath_start_rfkill_poll(struct ath_softc *sc);
+void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
+void ath9k_ps_wakeup(struct ath_softc *sc);
+void ath9k_ps_restore(struct ath_softc *sc);
 
 #ifdef CONFIG_ATH9K_PCI
 int ath_pci_init(void);
@@ -1044,15 +847,4 @@ static inline int ath_ahb_init(void) { return 0; };
 static inline void ath_ahb_exit(void) {};
 #endif
 
-void ath9k_ps_wakeup(struct ath_softc *sc);
-void ath9k_ps_restore(struct ath_softc *sc);
-
-u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
-
-void ath_start_rfkill_poll(struct ath_softc *sc);
-void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
-void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
-                              struct ieee80211_vif *vif,
-                              struct ath9k_vif_iter_data *iter_data);
-
 #endif /* ATH9K_H */
index 17be35392bb4f5134996a6e14b6bdc2547d40de9..2e8bba0eb361b5846af5666a87854e002f24b20f 100644 (file)
@@ -274,18 +274,19 @@ static int ath9k_beacon_choose_slot(struct ath_softc *sc)
        return slot;
 }
 
-void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
+static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
        struct ath_vif *avp = (void *)vif->drv_priv;
-       u64 tsfadjust;
+       u32 tsfadjust;
 
        if (avp->av_bslot == 0)
                return;
 
-       tsfadjust = cur_conf->beacon_interval * avp->av_bslot / ATH_BCBUF;
-       avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
+       tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
+       tsfadjust = TU_TO_USEC(tsfadjust) / ATH_BCBUF;
+       avp->tsf_adjust = cpu_to_le64(tsfadjust);
 
        ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
                (unsigned long long)tsfadjust, avp->av_bslot);
@@ -336,8 +337,14 @@ void ath9k_beacon_tasklet(unsigned long data)
 
                ath9k_hw_check_nav(ah);
 
-               if (!ath9k_hw_check_alive(ah))
-                       ieee80211_queue_work(sc->hw, &sc->hw_check_work);
+               /*
+                * If the previous beacon has not been transmitted
+                * and a MAC/BB hang has been identified, return
+                * here because a chip reset would have been
+                * initiated.
+                */
+               if (!ath_hw_check(sc))
+                       return;
 
                if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
                        ath_dbg(common, BSTUCK,
@@ -431,6 +438,33 @@ static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt,
        ath9k_hw_enable_interrupts(ah);
 }
 
+/* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */
+static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu)
+{
+       u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo;
+
+       tsf_mod = tsf & (BIT(10) - 1);
+       tsf_hi = tsf >> 32;
+       tsf_lo = ((u32) tsf) >> 10;
+
+       mod_hi = tsf_hi % div_tu;
+       mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu;
+
+       return (mod_lo << 10) | tsf_mod;
+}
+
+static u32 ath9k_get_next_tbtt(struct ath_softc *sc, u64 tsf,
+                              unsigned int interval)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       unsigned int offset;
+
+       tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time);
+       offset = ath9k_mod_tsf64_tu(tsf, interval);
+
+       return (u32) tsf + TU_TO_USEC(interval) - offset;
+}
+
 /*
  * For multi-bss ap support beacons are either staggered evenly over N slots or
  * burst together.  For the former arrange for the SWBA to be delivered for each
@@ -446,7 +480,8 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc,
        /* NB: the beacon interval is kept internally in TU's */
        intval = TU_TO_USEC(conf->beacon_interval);
        intval /= ATH_BCBUF;
-       nexttbtt = intval;
+       nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah),
+                                      conf->beacon_interval);
 
        if (conf->enable_beacon)
                ah->imask |= ATH9K_INT_SWBA;
@@ -458,7 +493,7 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc,
                (conf->enable_beacon) ? "Enable" : "Disable",
                nexttbtt, intval, conf->beacon_interval);
 
-       ath9k_beacon_init(sc, nexttbtt, intval, true);
+       ath9k_beacon_init(sc, nexttbtt, intval, false);
 }
 
 /*
@@ -475,11 +510,9 @@ static void ath9k_beacon_config_sta(struct ath_softc *sc,
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_beacon_state bs;
-       int dtimperiod, dtimcount, sleepduration;
-       int cfpperiod, cfpcount;
-       u32 nexttbtt = 0, intval, tsftu;
+       int dtim_intval, sleepduration;
+       u32 nexttbtt = 0, intval;
        u64 tsf;
-       int num_beacons, offset, dtim_dec_count, cfp_dec_count;
 
        /* No need to configure beacon if we are not associated */
        if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
@@ -492,53 +525,25 @@ static void ath9k_beacon_config_sta(struct ath_softc *sc,
        intval = conf->beacon_interval;
 
        /*
-        * Setup dtim and cfp parameters according to
+        * Setup dtim parameters according to
         * last beacon we received (which may be none).
         */
-       dtimperiod = conf->dtim_period;
-       dtimcount = conf->dtim_count;
-       if (dtimcount >= dtimperiod)    /* NB: sanity check */
-               dtimcount = 0;
-       cfpperiod = 1;                  /* NB: no PCF support yet */
-       cfpcount = 0;
-
+       dtim_intval = intval * conf->dtim_period;
        sleepduration = conf->listen_interval * intval;
 
        /*
         * Pull nexttbtt forward to reflect the current
-        * TSF and calculate dtim+cfp state for the result.
+        * TSF and calculate dtim state for the result.
         */
        tsf = ath9k_hw_gettsf64(ah);
-       tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
-
-       num_beacons = tsftu / intval + 1;
-       offset = tsftu % intval;
-       nexttbtt = tsftu - offset;
-       if (offset)
-               nexttbtt += intval;
-
-       /* DTIM Beacon every dtimperiod Beacon */
-       dtim_dec_count = num_beacons % dtimperiod;
-       /* CFP every cfpperiod DTIM Beacon */
-       cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
-       if (dtim_dec_count)
-               cfp_dec_count++;
-
-       dtimcount -= dtim_dec_count;
-       if (dtimcount < 0)
-               dtimcount += dtimperiod;
-
-       cfpcount -= cfp_dec_count;
-       if (cfpcount < 0)
-               cfpcount += cfpperiod;
-
-       bs.bs_intval = intval;
+       nexttbtt = ath9k_get_next_tbtt(sc, tsf, intval);
+
+       bs.bs_intval = TU_TO_USEC(intval);
+       bs.bs_dtimperiod = conf->dtim_period * bs.bs_intval;
        bs.bs_nexttbtt = nexttbtt;
-       bs.bs_dtimperiod = dtimperiod*intval;
-       bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
-       bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
-       bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
-       bs.bs_cfpmaxduration = 0;
+       bs.bs_nextdtim = nexttbtt;
+       if (conf->dtim_period > 1)
+               bs.bs_nextdtim = ath9k_get_next_tbtt(sc, tsf, dtim_intval);
 
        /*
         * Calculate the number of consecutive beacons to miss* before taking
@@ -566,18 +571,16 @@ static void ath9k_beacon_config_sta(struct ath_softc *sc,
         * XXX fixed at 100ms
         */
 
-       bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
+       bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
+                                                sleepduration));
        if (bs.bs_sleepduration > bs.bs_dtimperiod)
                bs.bs_sleepduration = bs.bs_dtimperiod;
 
        /* TSF out of range threshold fixed at 1 second */
        bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
 
-       ath_dbg(common, BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
-       ath_dbg(common, BEACON,
-               "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
-               bs.bs_bmissthreshold, bs.bs_sleepduration,
-               bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
+       ath_dbg(common, BEACON, "bmiss: %u sleep: %u\n",
+               bs.bs_bmissthreshold, bs.bs_sleepduration);
 
        /* Set the computed STA beacon timers */
 
@@ -600,25 +603,11 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
 
        intval = TU_TO_USEC(conf->beacon_interval);
 
-       if (conf->ibss_creator) {
+       if (conf->ibss_creator)
                nexttbtt = intval;
-       } else {
-               u32 tbtt, offset, tsftu;
-               u64 tsf;
-
-               /*
-                * Pull nexttbtt forward to reflect the current
-                * sync'd TSF.
-                */
-               tsf = ath9k_hw_gettsf64(ah);
-               tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
-               offset = tsftu % conf->beacon_interval;
-               tbtt = tsftu - offset;
-               if (offset)
-                       tbtt += conf->beacon_interval;
-
-               nexttbtt = TU_TO_USEC(tbtt);
-       }
+       else
+               nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah),
+                                              conf->beacon_interval);
 
        if (conf->enable_beacon)
                ah->imask |= ATH9K_INT_SWBA;
@@ -640,7 +629,8 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
                set_bit(SC_OP_BEACONS, &sc->sc_flags);
 }
 
-bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
+static bool ath9k_allow_beacon_config(struct ath_softc *sc,
+                                     struct ieee80211_vif *vif)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
@@ -711,12 +701,17 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
        unsigned long flags;
        bool skip_beacon = false;
 
+       if (vif->type == NL80211_IFTYPE_AP)
+               ath9k_set_tsfadjust(sc, vif);
+
+       if (!ath9k_allow_beacon_config(sc, vif))
+               return;
+
        if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
                ath9k_cache_beacon_config(sc, bss_conf);
                ath9k_set_beacon(sc);
                set_bit(SC_OP_BEACONS, &sc->sc_flags);
                return;
-
        }
 
        /*
index 9963b0bf9f72694630cab058621547f53eeeb237..3dfc2c7f1f07862ce81238aa297b4a45cb944fd8 100644 (file)
@@ -66,7 +66,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
                .bt_first_slot_time = 5,
                .bt_hold_rx_clear = true,
        };
-       u32 i, idx;
        bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
 
        if (AR_SREV_9300_20_OR_LATER(ah))
@@ -88,11 +87,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
                SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
                SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
                AR_BT_DISABLE_BT_ANT;
-
-       for (i = 0; i < 32; i++) {
-               idx = (debruijn32 << i) >> 27;
-               ah->hw_gen_timers.gen_timer_index[idx] = i;
-       }
 }
 EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
 
index a7e5a05b2eff88e8d367cea6403058cc2813ebbc..768c733cad31d4ef7ae1c45bd17c2e207f2ca82f 100644 (file)
@@ -98,10 +98,8 @@ struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
 {
        struct ieee80211_channel *curchan = chandef->chan;
        struct ath9k_channel *channel;
-       u8 chan_idx;
 
-       chan_idx = curchan->hw_value;
-       channel = &ah->channels[chan_idx];
+       channel = &ah->channels[curchan->hw_value];
        ath9k_cmn_update_ichannel(channel, chandef);
 
        return channel;
index 2f7dccfdb72784bf5c098a72ed703cf3abc0f2a2..b041052a10eeaba1bd5e919422a205877a65a131 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/export.h>
-#include <linux/relay.h>
 #include <asm/unaligned.h>
 
 #include "ath9k.h"
 #define REG_READ_D(_ah, _reg) \
        ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
 
+void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause)
+{
+       if (sync_cause)
+               sc->debug.stats.istats.sync_cause_all++;
+       if (sync_cause & AR_INTR_SYNC_RTC_IRQ)
+               sc->debug.stats.istats.sync_rtc_irq++;
+       if (sync_cause & AR_INTR_SYNC_MAC_IRQ)
+               sc->debug.stats.istats.sync_mac_irq++;
+       if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS)
+               sc->debug.stats.istats.eeprom_illegal_access++;
+       if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT)
+               sc->debug.stats.istats.apb_timeout++;
+       if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT)
+               sc->debug.stats.istats.pci_mode_conflict++;
+       if (sync_cause & AR_INTR_SYNC_HOST1_FATAL)
+               sc->debug.stats.istats.host1_fatal++;
+       if (sync_cause & AR_INTR_SYNC_HOST1_PERR)
+               sc->debug.stats.istats.host1_perr++;
+       if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR)
+               sc->debug.stats.istats.trcv_fifo_perr++;
+       if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP)
+               sc->debug.stats.istats.radm_cpl_ep++;
+       if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT)
+               sc->debug.stats.istats.radm_cpl_dllp_abort++;
+       if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT)
+               sc->debug.stats.istats.radm_cpl_tlp_abort++;
+       if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR)
+               sc->debug.stats.istats.radm_cpl_ecrc_err++;
+       if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT)
+               sc->debug.stats.istats.radm_cpl_timeout++;
+       if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
+               sc->debug.stats.istats.local_timeout++;
+       if (sync_cause & AR_INTR_SYNC_PM_ACCESS)
+               sc->debug.stats.istats.pm_access++;
+       if (sync_cause & AR_INTR_SYNC_MAC_AWAKE)
+               sc->debug.stats.istats.mac_awake++;
+       if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP)
+               sc->debug.stats.istats.mac_asleep++;
+       if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS)
+               sc->debug.stats.istats.mac_sleep_access++;
+}
 
 static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf,
                                      size_t count, loff_t *ppos)
@@ -1016,293 +1056,6 @@ static const struct file_operations fops_recv = {
        .llseek = default_llseek,
 };
 
-static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
-                                      size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       char *mode = "";
-       unsigned int len;
-
-       switch (sc->spectral_mode) {
-       case SPECTRAL_DISABLED:
-               mode = "disable";
-               break;
-       case SPECTRAL_BACKGROUND:
-               mode = "background";
-               break;
-       case SPECTRAL_CHANSCAN:
-               mode = "chanscan";
-               break;
-       case SPECTRAL_MANUAL:
-               mode = "manual";
-               break;
-       }
-       len = strlen(mode);
-       return simple_read_from_buffer(user_buf, count, ppos, mode, len);
-}
-
-static ssize_t write_file_spec_scan_ctl(struct file *file,
-                                       const char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       char buf[32];
-       ssize_t len;
-
-       if (config_enabled(CONFIG_ATH9K_TX99))
-               return -EOPNOTSUPP;
-
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-
-       buf[len] = '\0';
-
-       if (strncmp("trigger", buf, 7) == 0) {
-               ath9k_spectral_scan_trigger(sc->hw);
-       } else if (strncmp("background", buf, 9) == 0) {
-               ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
-               ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
-       } else if (strncmp("chanscan", buf, 8) == 0) {
-               ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN);
-               ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n");
-       } else if (strncmp("manual", buf, 6) == 0) {
-               ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL);
-               ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n");
-       } else if (strncmp("disable", buf, 7) == 0) {
-               ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED);
-               ath_dbg(common, CONFIG, "spectral scan: disabled\n");
-       } else {
-               return -EINVAL;
-       }
-
-       return count;
-}
-
-static const struct file_operations fops_spec_scan_ctl = {
-       .read = read_file_spec_scan_ctl,
-       .write = write_file_spec_scan_ctl,
-       .open = simple_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
-static ssize_t read_file_spectral_short_repeat(struct file *file,
-                                              char __user *user_buf,
-                                              size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       char buf[32];
-       unsigned int len;
-
-       len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t write_file_spectral_short_repeat(struct file *file,
-                                               const char __user *user_buf,
-                                               size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       unsigned long val;
-       char buf[32];
-       ssize_t len;
-
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-
-       buf[len] = '\0';
-       if (kstrtoul(buf, 0, &val))
-               return -EINVAL;
-
-       if (val < 0 || val > 1)
-               return -EINVAL;
-
-       sc->spec_config.short_repeat = val;
-       return count;
-}
-
-static const struct file_operations fops_spectral_short_repeat = {
-       .read = read_file_spectral_short_repeat,
-       .write = write_file_spectral_short_repeat,
-       .open = simple_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
-static ssize_t read_file_spectral_count(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       char buf[32];
-       unsigned int len;
-
-       len = sprintf(buf, "%d\n", sc->spec_config.count);
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t write_file_spectral_count(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       unsigned long val;
-       char buf[32];
-       ssize_t len;
-
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-
-       buf[len] = '\0';
-       if (kstrtoul(buf, 0, &val))
-               return -EINVAL;
-
-       if (val < 0 || val > 255)
-               return -EINVAL;
-
-       sc->spec_config.count = val;
-       return count;
-}
-
-static const struct file_operations fops_spectral_count = {
-       .read = read_file_spectral_count,
-       .write = write_file_spectral_count,
-       .open = simple_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
-static ssize_t read_file_spectral_period(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       char buf[32];
-       unsigned int len;
-
-       len = sprintf(buf, "%d\n", sc->spec_config.period);
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t write_file_spectral_period(struct file *file,
-                                         const char __user *user_buf,
-                                         size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       unsigned long val;
-       char buf[32];
-       ssize_t len;
-
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-
-       buf[len] = '\0';
-       if (kstrtoul(buf, 0, &val))
-               return -EINVAL;
-
-       if (val < 0 || val > 255)
-               return -EINVAL;
-
-       sc->spec_config.period = val;
-       return count;
-}
-
-static const struct file_operations fops_spectral_period = {
-       .read = read_file_spectral_period,
-       .write = write_file_spectral_period,
-       .open = simple_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
-static ssize_t read_file_spectral_fft_period(struct file *file,
-                                            char __user *user_buf,
-                                            size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       char buf[32];
-       unsigned int len;
-
-       len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t write_file_spectral_fft_period(struct file *file,
-                                             const char __user *user_buf,
-                                             size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       unsigned long val;
-       char buf[32];
-       ssize_t len;
-
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-
-       buf[len] = '\0';
-       if (kstrtoul(buf, 0, &val))
-               return -EINVAL;
-
-       if (val < 0 || val > 15)
-               return -EINVAL;
-
-       sc->spec_config.fft_period = val;
-       return count;
-}
-
-static const struct file_operations fops_spectral_fft_period = {
-       .read = read_file_spectral_fft_period,
-       .write = write_file_spectral_fft_period,
-       .open = simple_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
-static struct dentry *create_buf_file_handler(const char *filename,
-                                             struct dentry *parent,
-                                             umode_t mode,
-                                             struct rchan_buf *buf,
-                                             int *is_global)
-{
-       struct dentry *buf_file;
-
-       buf_file = debugfs_create_file(filename, mode, parent, buf,
-                                      &relay_file_operations);
-       *is_global = 1;
-       return buf_file;
-}
-
-static int remove_buf_file_handler(struct dentry *dentry)
-{
-       debugfs_remove(dentry);
-
-       return 0;
-}
-
-void ath_debug_send_fft_sample(struct ath_softc *sc,
-                              struct fft_sample_tlv *fft_sample_tlv)
-{
-       int length;
-       if (!sc->rfs_chan_spec_scan)
-               return;
-
-       length = __be16_to_cpu(fft_sample_tlv->length) +
-                sizeof(*fft_sample_tlv);
-       relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
-}
-
-static struct rchan_callbacks rfs_spec_scan_cb = {
-       .create_buf_file = create_buf_file_handler,
-       .remove_buf_file = remove_buf_file_handler,
-};
-
-
 static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
                                 size_t count, loff_t *ppos)
 {
@@ -1772,10 +1525,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
 
 void ath9k_deinit_debug(struct ath_softc *sc)
 {
-       if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
-               relay_close(sc->rfs_chan_spec_scan);
-               sc->rfs_chan_spec_scan = NULL;
-       }
+       ath9k_spectral_deinit_debug(sc);
 }
 
 int ath9k_init_debug(struct ath_hw *ah)
@@ -1795,6 +1545,7 @@ int ath9k_init_debug(struct ath_hw *ah)
 
        ath9k_dfs_init_debug(sc);
        ath9k_tx99_init_debug(sc);
+       ath9k_spectral_init_debug(sc);
 
        debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_dma);
@@ -1841,23 +1592,6 @@ int ath9k_init_debug(struct ath_hw *ah)
                            &fops_base_eeprom);
        debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_modal_eeprom);
-       sc->rfs_chan_spec_scan = relay_open("spectral_scan",
-                                           sc->debug.debugfs_phy,
-                                           1024, 256, &rfs_spec_scan_cb,
-                                           NULL);
-       debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
-                           sc->debug.debugfs_phy, sc,
-                           &fops_spec_scan_ctl);
-       debugfs_create_file("spectral_short_repeat", S_IRUSR | S_IWUSR,
-                           sc->debug.debugfs_phy, sc,
-                           &fops_spectral_short_repeat);
-       debugfs_create_file("spectral_count", S_IRUSR | S_IWUSR,
-                           sc->debug.debugfs_phy, sc, &fops_spectral_count);
-       debugfs_create_file("spectral_period", S_IRUSR | S_IWUSR,
-                           sc->debug.debugfs_phy, sc, &fops_spectral_period);
-       debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR,
-                           sc->debug.debugfs_phy, sc,
-                           &fops_spectral_fft_period);
        debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
                           sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
        debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
index d6e3fa4299a4fa5e4f85e49502a900920d48f718..ec02d38ea8eae813b4078106a2426c2cd1862319 100644 (file)
@@ -292,11 +292,11 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
                           struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta,
                           struct dentry *dir);
-void ath_debug_send_fft_sample(struct ath_softc *sc,
-                              struct fft_sample_tlv *fft_sample);
 void ath9k_debug_stat_ant(struct ath_softc *sc,
                          struct ath_hw_antcomb_conf *div_ant_conf,
                          int main_rssi_avg, int alt_rssi_avg);
+void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause);
+
 #else
 
 #define RX_STAT_INC(c) /* NOP */
@@ -331,6 +331,11 @@ static inline void ath9k_debug_stat_ant(struct ath_softc *sc,
 
 }
 
+static inline void
+ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause)
+{
+}
+
 #endif /* CONFIG_ATH9K_DEBUGFS */
 
 #endif /* DEBUG_H */
index 7187d3671512eae62e3e1da59bb1aea9866a7be8..857bb28b389411ea2e1586abd3f5c749c0127327 100644 (file)
@@ -158,8 +158,8 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
                return;
        }
 
-       ard.rssi = rs->rs_rssi_ctl0;
-       ard.ext_rssi = rs->rs_rssi_ext0;
+       ard.rssi = rs->rs_rssi_ctl[0];
+       ard.ext_rssi = rs->rs_rssi_ext[0];
 
        /*
         * hardware stores this as 8 bit signed value.
index b4091716e9b3322881a6ed65fc3996a57e59a8b8..07b806c56c56b4b0a5167cd704493a85285a8b58 100644 (file)
@@ -1085,31 +1085,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
 
 static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
 {
-#define EEP_MAP4K_SPURCHAN \
-       (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
-       struct ath_common *common = ath9k_hw_common(ah);
-
-       u16 spur_val = AR_NO_SPUR;
-
-       ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
-               i, is2GHz, ah->config.spurchans[i][is2GHz]);
-
-       switch (ah->config.spurmode) {
-       case SPUR_DISABLE:
-               break;
-       case SPUR_ENABLE_IOCTL:
-               spur_val = ah->config.spurchans[i][is2GHz];
-               ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
-                       spur_val);
-               break;
-       case SPUR_ENABLE_EEPROM:
-               spur_val = EEP_MAP4K_SPURCHAN;
-               break;
-       }
-
-       return spur_val;
-
-#undef EEP_MAP4K_SPURCHAN
+       return ah->eeprom.map4k.modalHeader.spurChans[i].spurChan;
 }
 
 const struct eeprom_ops eep_4k_ops = {
index e1d0c217c104f9ba6c2b0a1e55a941e2ccc63d20..5ba1385c9838016a942df4e189bf7d8a484fad6e 100644 (file)
@@ -1004,31 +1004,7 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
 static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
                                            u16 i, bool is2GHz)
 {
-#define EEP_MAP9287_SPURCHAN \
-       (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
-
-       struct ath_common *common = ath9k_hw_common(ah);
-       u16 spur_val = AR_NO_SPUR;
-
-       ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
-               i, is2GHz, ah->config.spurchans[i][is2GHz]);
-
-       switch (ah->config.spurmode) {
-       case SPUR_DISABLE:
-               break;
-       case SPUR_ENABLE_IOCTL:
-               spur_val = ah->config.spurchans[i][is2GHz];
-               ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
-                       spur_val);
-               break;
-       case SPUR_ENABLE_EEPROM:
-               spur_val = EEP_MAP9287_SPURCHAN;
-               break;
-       }
-
-       return spur_val;
-
-#undef EEP_MAP9287_SPURCHAN
+       return ah->eeprom.map9287.modalHeader.spurChans[i].spurChan;
 }
 
 const struct eeprom_ops eep_ar9287_ops = {
index 39107e31e79aaa98fa93453f74db8b4e416ae457..3218ca9947463a844ed38f22956faedaca688cbb 100644 (file)
@@ -1348,31 +1348,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
 
 static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
 {
-#define EEP_DEF_SPURCHAN \
-       (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
-       struct ath_common *common = ath9k_hw_common(ah);
-
-       u16 spur_val = AR_NO_SPUR;
-
-       ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
-               i, is2GHz, ah->config.spurchans[i][is2GHz]);
-
-       switch (ah->config.spurmode) {
-       case SPUR_DISABLE:
-               break;
-       case SPUR_ENABLE_IOCTL:
-               spur_val = ah->config.spurchans[i][is2GHz];
-               ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
-                       spur_val);
-               break;
-       case SPUR_ENABLE_EEPROM:
-               spur_val = EEP_DEF_SPURCHAN;
-               break;
-       }
-
-       return spur_val;
-
-#undef EEP_DEF_SPURCHAN
+       return ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan;
 }
 
 const struct eeprom_ops eep_def_ops = {
index c34f21241da947e5297bc7ad18e6de9cc3430825..b1956bf6e01e12480fad2b0d8e580abca118399c 100644 (file)
@@ -157,36 +157,6 @@ static void ath_detect_bt_priority(struct ath_softc *sc)
        }
 }
 
-static void ath9k_gen_timer_start(struct ath_hw *ah,
-                                 struct ath_gen_timer *timer,
-                                 u32 trig_timeout,
-                                 u32 timer_period)
-{
-       ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period);
-
-       if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
-               ath9k_hw_disable_interrupts(ah);
-               ah->imask |= ATH9K_INT_GENTIMER;
-               ath9k_hw_set_interrupts(ah);
-               ath9k_hw_enable_interrupts(ah);
-       }
-}
-
-static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
-{
-       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
-
-       ath9k_hw_gen_timer_stop(ah, timer);
-
-       /* if no timer is enabled, turn off interrupt mask */
-       if (timer_table->timer_mask.val == 0) {
-               ath9k_hw_disable_interrupts(ah);
-               ah->imask &= ~ATH9K_INT_GENTIMER;
-               ath9k_hw_set_interrupts(ah);
-               ath9k_hw_enable_interrupts(ah);
-       }
-}
-
 static void ath_mci_ftp_adjust(struct ath_softc *sc)
 {
        struct ath_btcoex *btcoex = &sc->btcoex;
@@ -257,19 +227,9 @@ static void ath_btcoex_period_timer(unsigned long data)
 
        spin_unlock_bh(&btcoex->btcoex_lock);
 
-       /*
-        * btcoex_period is in msec while (btocex/btscan_)no_stomp are in usec,
-        * ensure that we properly convert btcoex_period to usec
-        * for any comparision with (btcoex/btscan_)no_stomp.
-        */
-       if (btcoex->btcoex_period * 1000 != btcoex->btcoex_no_stomp) {
-               if (btcoex->hw_timer_enabled)
-                       ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
-
-               ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
-                                     timer_period * 10);
-               btcoex->hw_timer_enabled = true;
-       }
+       if (btcoex->btcoex_period != btcoex->btcoex_no_stomp)
+               mod_timer(&btcoex->no_stomp_timer,
+                        jiffies + msecs_to_jiffies(timer_period));
 
        ath9k_ps_restore(sc);
 
@@ -282,7 +242,7 @@ skip_hw_wakeup:
  * Generic tsf based hw timer which configures weight
  * registers to time slice between wlan and bt traffic
  */
-static void ath_btcoex_no_stomp_timer(void *arg)
+static void ath_btcoex_no_stomp_timer(unsigned long arg)
 {
        struct ath_softc *sc = (struct ath_softc *)arg;
        struct ath_hw *ah = sc->sc_ah;
@@ -311,24 +271,18 @@ static int ath_init_btcoex_timer(struct ath_softc *sc)
        struct ath_btcoex *btcoex = &sc->btcoex;
 
        btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
-       btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 1000 *
+       btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
                btcoex->btcoex_period / 100;
-       btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 1000 *
+       btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
                                   btcoex->btcoex_period / 100;
 
        setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
                        (unsigned long) sc);
+       setup_timer(&btcoex->no_stomp_timer, ath_btcoex_no_stomp_timer,
+                       (unsigned long) sc);
 
        spin_lock_init(&btcoex->btcoex_lock);
 
-       btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah,
-                       ath_btcoex_no_stomp_timer,
-                       ath_btcoex_no_stomp_timer,
-                       (void *) sc, AR_FIRST_NDP_TIMER);
-
-       if (!btcoex->no_stomp_timer)
-               return -ENOMEM;
-
        return 0;
 }
 
@@ -343,10 +297,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
        ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n");
 
        /* make sure duty cycle timer is also stopped when resuming */
-       if (btcoex->hw_timer_enabled) {
-               ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
-               btcoex->hw_timer_enabled = false;
-       }
+       del_timer_sync(&btcoex->no_stomp_timer);
 
        btcoex->bt_priority_cnt = 0;
        btcoex->bt_priority_time = jiffies;
@@ -363,24 +314,16 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
 void ath9k_btcoex_timer_pause(struct ath_softc *sc)
 {
        struct ath_btcoex *btcoex = &sc->btcoex;
-       struct ath_hw *ah = sc->sc_ah;
 
        del_timer_sync(&btcoex->period_timer);
-
-       if (btcoex->hw_timer_enabled) {
-               ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
-               btcoex->hw_timer_enabled = false;
-       }
+       del_timer_sync(&btcoex->no_stomp_timer);
 }
 
 void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
 {
        struct ath_btcoex *btcoex = &sc->btcoex;
 
-       if (btcoex->hw_timer_enabled) {
-               ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
-               btcoex->hw_timer_enabled = false;
-       }
+       del_timer_sync(&btcoex->no_stomp_timer);
 }
 
 u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
@@ -400,12 +343,6 @@ u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
 
 void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status)
 {
-       struct ath_hw *ah = sc->sc_ah;
-
-       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
-               if (status & ATH9K_INT_GENTIMER)
-                       ath_gen_timer_isr(sc->sc_ah);
-
        if (status & ATH9K_INT_MCI)
                ath_mci_intr(sc);
 }
@@ -447,10 +384,6 @@ void ath9k_deinit_btcoex(struct ath_softc *sc)
 {
        struct ath_hw *ah = sc->sc_ah;
 
-        if ((sc->btcoex.no_stomp_timer) &&
-           ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
-               ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
-
        if (ath9k_hw_mci_is_enabled(ah))
                ath_mci_cleanup(sc);
 }
index 055d7c25e090bd33ce70de75c8352dc22dbb4003..58da3468d1f0ac1b3de6522b7118640f2c80da76 100644 (file)
@@ -600,10 +600,15 @@ void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
 struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv);
 
 #ifdef CONFIG_MAC80211_LEDS
+void ath9k_configure_leds(struct ath9k_htc_priv *priv);
 void ath9k_init_leds(struct ath9k_htc_priv *priv);
 void ath9k_deinit_leds(struct ath9k_htc_priv *priv);
 void ath9k_led_work(struct work_struct *work);
 #else
+static inline void ath9k_configure_leds(struct ath9k_htc_priv *priv)
+{
+}
+
 static inline void ath9k_init_leds(struct ath9k_htc_priv *priv)
 {
 }
index e0c03bd641821a165d8fd922bedd14c5f685d321..8b575773459677055fe6b427e8443f65796c4ae2 100644 (file)
@@ -70,11 +70,11 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
        struct ath9k_beacon_state bs;
        enum ath9k_int imask = 0;
        int dtimperiod, dtimcount, sleepduration;
-       int cfpperiod, cfpcount, bmiss_timeout;
+       int bmiss_timeout;
        u32 nexttbtt = 0, intval, tsftu;
        __be32 htc_imask = 0;
        u64 tsf;
-       int num_beacons, offset, dtim_dec_count, cfp_dec_count;
+       int num_beacons, offset, dtim_dec_count;
        int ret __attribute__ ((unused));
        u8 cmd_rsp;
 
@@ -84,7 +84,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
        bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);
 
        /*
-        * Setup dtim and cfp parameters according to
+        * Setup dtim parameters according to
         * last beacon we received (which may be none).
         */
        dtimperiod = bss_conf->dtim_period;
@@ -93,8 +93,6 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
        dtimcount = 1;
        if (dtimcount >= dtimperiod)    /* NB: sanity check */
                dtimcount = 0;
-       cfpperiod = 1;                  /* NB: no PCF support yet */
-       cfpcount = 0;
 
        sleepduration = intval;
        if (sleepduration <= 0)
@@ -102,7 +100,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
 
        /*
         * Pull nexttbtt forward to reflect the current
-        * TSF and calculate dtim+cfp state for the result.
+        * TSF and calculate dtim state for the result.
         */
        tsf = ath9k_hw_gettsf64(priv->ah);
        tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
@@ -115,26 +113,14 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
 
        /* DTIM Beacon every dtimperiod Beacon */
        dtim_dec_count = num_beacons % dtimperiod;
-       /* CFP every cfpperiod DTIM Beacon */
-       cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
-       if (dtim_dec_count)
-               cfp_dec_count++;
-
        dtimcount -= dtim_dec_count;
        if (dtimcount < 0)
                dtimcount += dtimperiod;
 
-       cfpcount -= cfp_dec_count;
-       if (cfpcount < 0)
-               cfpcount += cfpperiod;
-
-       bs.bs_intval = intval;
-       bs.bs_nexttbtt = nexttbtt;
-       bs.bs_dtimperiod = dtimperiod*intval;
-       bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
-       bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
-       bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
-       bs.bs_cfpmaxduration = 0;
+       bs.bs_intval = TU_TO_USEC(intval);
+       bs.bs_nexttbtt = TU_TO_USEC(nexttbtt);
+       bs.bs_dtimperiod = dtimperiod * bs.bs_intval;
+       bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount * bs.bs_intval;
 
        /*
         * Calculate the number of consecutive beacons to miss* before taking
@@ -161,7 +147,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
         * XXX fixed at 100ms
         */
 
-       bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
+       bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
+                                                sleepduration));
        if (bs.bs_sleepduration > bs.bs_dtimperiod)
                bs.bs_sleepduration = bs.bs_dtimperiod;
 
@@ -170,10 +157,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
 
        ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n",
                intval, tsf, tsftu);
-       ath_dbg(common, CONFIG,
-               "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
-               bs.bs_bmissthreshold, bs.bs_sleepduration,
-               bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
+       ath_dbg(common, CONFIG, "bmiss: %u sleep: %u\n",
+               bs.bs_bmissthreshold, bs.bs_sleepduration);
 
        /* Set the computed STA beacon timers */
 
index 105582d6b714956e124b291b56480d0c3c0adb6e..50f74a2a4cf8f99b8a619d7502cc6a225fa9005c 100644 (file)
@@ -255,6 +255,17 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
        cancel_work_sync(&priv->led_work);
 }
 
+
+void ath9k_configure_leds(struct ath9k_htc_priv *priv)
+{
+       /* Configure gpio 1 for output */
+       ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
+                           AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+       /* LED off, active low */
+       ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
+
+}
+
 void ath9k_init_leds(struct ath9k_htc_priv *priv)
 {
        int ret;
@@ -268,11 +279,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv)
        else
                priv->ah->led_pin = ATH_LED_PIN_DEF;
 
-       /* Configure gpio 1 for output */
-       ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
-                           AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-       /* LED off, active low */
-       ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
+       ath9k_configure_leds(priv);
 
        snprintf(priv->led_name, sizeof(priv->led_name),
                "ath9k_htc-%s", wiphy_name(priv->hw->wiphy));
index c3676bf1d6c45ab92d8a161d18ad5f3f0c586d18..b576c44bb31499a8e33c2f17cf9049f7ef205bdf 100644 (file)
@@ -1000,6 +1000,8 @@ int ath9k_htc_resume(struct htc_target *htc_handle)
 
        ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
                                      priv->ah->hw_version.usbdev);
+       ath9k_configure_leds(priv);
+
        return ret;
 }
 #endif
index 9a2657fdd9ccd4ec62f96f8a639182e2ded29fec..608d739d13782233db4271f9248c3472601b1a5f 100644 (file)
@@ -127,21 +127,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
        struct ath9k_vif_iter_data *iter_data = data;
        int i;
 
-       for (i = 0; i < ETH_ALEN; i++)
-               iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       if (iter_data->hw_macaddr != NULL) {
+               for (i = 0; i < ETH_ALEN; i++)
+                       iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       } else {
+               iter_data->hw_macaddr = mac;
+       }
 }
 
-static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
+static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv,
                                     struct ieee80211_vif *vif)
 {
        struct ath_common *common = ath9k_hw_common(priv->ah);
        struct ath9k_vif_iter_data iter_data;
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
-       iter_data.hw_macaddr = common->macaddr;
+       iter_data.hw_macaddr = NULL;
        memset(&iter_data.mask, 0xff, ETH_ALEN);
 
        if (vif)
@@ -153,6 +158,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
                ath9k_htc_bssid_iter, &iter_data);
 
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+
+       if (iter_data.hw_macaddr)
+               memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
+
        ath_hw_setbssidmask(common);
 }
 
@@ -1063,7 +1072,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        priv->vif_slot |= (1 << avp->index);
        priv->nvifs++;
@@ -1128,7 +1137,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 
        ath9k_htc_set_opmode(priv);
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        /*
         * Stop ANI only if there are no associated station interfaces.
index c028df76b564971ffa9a878325dd63e826757ab1..b41e008298dce90da1cfb131072d75242faebf06 100644 (file)
@@ -1077,7 +1077,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
 
        if (ieee80211_is_beacon(hdr->frame_control) &&
            !is_zero_ether_addr(common->curbssid) &&
-           ether_addr_equal(hdr->addr3, common->curbssid)) {
+           ether_addr_equal_64bits(hdr->addr3, common->curbssid)) {
                s8 rssi = rxbuf->rxstatus.rs_rssi;
 
                if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
index 4f9378ddf07f21455a33a908180b9a28729bf6cd..a47ea8423f1eb2a6a8d43f4d451475f55bac6674 100644 (file)
@@ -49,9 +49,10 @@ static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
        return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
 }
 
-static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
+static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked,
+                                  u32 *sync_cause_p)
 {
-       return ath9k_hw_ops(ah)->get_isr(ah, masked);
+       return ath9k_hw_ops(ah)->get_isr(ah, masked, sync_cause_p);
 }
 
 static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
@@ -106,6 +107,21 @@ static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
 
 /* Private hardware call ops */
 
+static inline void ath9k_hw_init_hang_checks(struct ath_hw *ah)
+{
+       ath9k_hw_private_ops(ah)->init_hang_checks(ah);
+}
+
+static inline bool ath9k_hw_detect_mac_hang(struct ath_hw *ah)
+{
+       return ath9k_hw_private_ops(ah)->detect_mac_hang(ah);
+}
+
+static inline bool ath9k_hw_detect_bb_hang(struct ath_hw *ah)
+{
+       return ath9k_hw_private_ops(ah)->detect_bb_hang(ah);
+}
+
 /* PHY ops */
 
 static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah,
@@ -231,4 +247,31 @@ static inline void ath9k_hw_set_radar_params(struct ath_hw *ah)
        ath9k_hw_private_ops(ah)->set_radar_params(ah, &ah->radar_conf);
 }
 
+static inline void ath9k_hw_init_cal_settings(struct ath_hw *ah)
+{
+       ath9k_hw_private_ops(ah)->init_cal_settings(ah);
+}
+
+static inline u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
+                                              struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan);
+}
+
+static inline void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs)
+               return;
+
+       ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah);
+}
+
+static inline void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs)
+               return;
+
+       ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah);
+}
+
 #endif /* ATH9K_HW_OPS_H */
index 4ee24b1eec38fa12ba86c838573a31b8d808f28f..ce41658a600344db2c027bcdfb9de41ccee50965 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/time.h>
+#include <linux/bitops.h>
 #include <asm/unaligned.h>
 
 #include "hw.h"
@@ -36,99 +37,6 @@ MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
 MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
 MODULE_LICENSE("Dual BSD/GPL");
 
-static int __init ath9k_init(void)
-{
-       return 0;
-}
-module_init(ath9k_init);
-
-static void __exit ath9k_exit(void)
-{
-       return;
-}
-module_exit(ath9k_exit);
-
-/* Private hardware callbacks */
-
-static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
-{
-       ath9k_hw_private_ops(ah)->init_cal_settings(ah);
-}
-
-static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
-                                       struct ath9k_channel *chan)
-{
-       return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan);
-}
-
-static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
-{
-       if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs)
-               return;
-
-       ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah);
-}
-
-static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah)
-{
-       /* You will not have this callback if using the old ANI */
-       if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs)
-               return;
-
-       ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah);
-}
-
-/********************/
-/* Helper Functions */
-/********************/
-
-#ifdef CONFIG_ATH9K_DEBUGFS
-
-void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause)
-{
-       struct ath_softc *sc = common->priv;
-       if (sync_cause)
-               sc->debug.stats.istats.sync_cause_all++;
-       if (sync_cause & AR_INTR_SYNC_RTC_IRQ)
-               sc->debug.stats.istats.sync_rtc_irq++;
-       if (sync_cause & AR_INTR_SYNC_MAC_IRQ)
-               sc->debug.stats.istats.sync_mac_irq++;
-       if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS)
-               sc->debug.stats.istats.eeprom_illegal_access++;
-       if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT)
-               sc->debug.stats.istats.apb_timeout++;
-       if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT)
-               sc->debug.stats.istats.pci_mode_conflict++;
-       if (sync_cause & AR_INTR_SYNC_HOST1_FATAL)
-               sc->debug.stats.istats.host1_fatal++;
-       if (sync_cause & AR_INTR_SYNC_HOST1_PERR)
-               sc->debug.stats.istats.host1_perr++;
-       if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR)
-               sc->debug.stats.istats.trcv_fifo_perr++;
-       if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP)
-               sc->debug.stats.istats.radm_cpl_ep++;
-       if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT)
-               sc->debug.stats.istats.radm_cpl_dllp_abort++;
-       if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT)
-               sc->debug.stats.istats.radm_cpl_tlp_abort++;
-       if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR)
-               sc->debug.stats.istats.radm_cpl_ecrc_err++;
-       if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT)
-               sc->debug.stats.istats.radm_cpl_timeout++;
-       if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
-               sc->debug.stats.istats.local_timeout++;
-       if (sync_cause & AR_INTR_SYNC_PM_ACCESS)
-               sc->debug.stats.istats.pm_access++;
-       if (sync_cause & AR_INTR_SYNC_MAC_AWAKE)
-               sc->debug.stats.istats.mac_awake++;
-       if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP)
-               sc->debug.stats.istats.mac_asleep++;
-       if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS)
-               sc->debug.stats.istats.mac_sleep_access++;
-}
-#endif
-
-
 static void ath9k_hw_set_clockrate(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
@@ -337,6 +245,9 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
        case AR9300_DEVID_QCA955X:
                ah->hw_version.macVersion = AR_SREV_VERSION_9550;
                return;
+       case AR9300_DEVID_AR953X:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9531;
+               return;
        }
 
        val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
@@ -438,21 +349,13 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah)
 
 static void ath9k_hw_init_config(struct ath_hw *ah)
 {
-       int i;
+       struct ath_common *common = ath9k_hw_common(ah);
 
        ah->config.dma_beacon_response_time = 1;
        ah->config.sw_beacon_response_time = 6;
-       ah->config.additional_swba_backoff = 0;
-       ah->config.ack_6mb = 0x0;
        ah->config.cwm_ignore_extcca = 0;
-       ah->config.pcie_clock_req = 0;
        ah->config.analog_shiftreg = 1;
 
-       for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
-               ah->config.spurchans[i][0] = AR_NO_SPUR;
-               ah->config.spurchans[i][1] = AR_NO_SPUR;
-       }
-
        ah->config.rx_intr_mitigation = true;
 
        /*
@@ -473,6 +376,24 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
         */
        if (num_possible_cpus() > 1)
                ah->config.serialize_regmode = SER_REG_MODE_AUTO;
+
+       if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
+               if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
+                   ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) &&
+                    !ah->is_pciexpress)) {
+                       ah->config.serialize_regmode = SER_REG_MODE_ON;
+               } else {
+                       ah->config.serialize_regmode = SER_REG_MODE_OFF;
+               }
+       }
+
+       ath_dbg(common, RESET, "serialize_regmode is %d\n",
+               ah->config.serialize_regmode);
+
+       if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+               ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
+       else
+               ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
 }
 
 static void ath9k_hw_init_defaults(struct ath_hw *ah)
@@ -485,16 +406,24 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
        ah->hw_version.magic = AR5416_MAGIC;
        ah->hw_version.subvendorid = 0;
 
-       ah->atim_window = 0;
-       ah->sta_id1_defaults =
-               AR_STA_ID1_CRPT_MIC_ENABLE |
-               AR_STA_ID1_MCAST_KSRCH;
+       ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE |
+                              AR_STA_ID1_MCAST_KSRCH;
        if (AR_SREV_9100(ah))
                ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
+
        ah->slottime = ATH9K_SLOT_TIME_9;
        ah->globaltxtimeout = (u32) -1;
        ah->power_mode = ATH9K_PM_UNDEFINED;
        ah->htc_reset_init = true;
+
+       ah->ani_function = ATH9K_ANI_ALL;
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
+
+       if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+               ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
+       else
+               ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
 }
 
 static int ath9k_hw_init_macaddr(struct ath_hw *ah)
@@ -576,6 +505,31 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 
        ath9k_hw_read_revisions(ah);
 
+       switch (ah->hw_version.macVersion) {
+       case AR_SREV_VERSION_5416_PCI:
+       case AR_SREV_VERSION_5416_PCIE:
+       case AR_SREV_VERSION_9160:
+       case AR_SREV_VERSION_9100:
+       case AR_SREV_VERSION_9280:
+       case AR_SREV_VERSION_9285:
+       case AR_SREV_VERSION_9287:
+       case AR_SREV_VERSION_9271:
+       case AR_SREV_VERSION_9300:
+       case AR_SREV_VERSION_9330:
+       case AR_SREV_VERSION_9485:
+       case AR_SREV_VERSION_9340:
+       case AR_SREV_VERSION_9462:
+       case AR_SREV_VERSION_9550:
+       case AR_SREV_VERSION_9565:
+       case AR_SREV_VERSION_9531:
+               break;
+       default:
+               ath_err(common,
+                       "Mac Chip Rev 0x%02x.%x is not supported by this driver\n",
+                       ah->hw_version.macVersion, ah->hw_version.macRev);
+               return -EOPNOTSUPP;
+       }
+
        /*
         * Read back AR_WA into a permanent copy and set bits 14 and 17.
         * We need to do this to avoid RMW of this register. We cannot
@@ -609,50 +563,6 @@ static int __ath9k_hw_init(struct ath_hw *ah)
                return -EIO;
        }
 
-       if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
-               if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
-                   ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) &&
-                    !ah->is_pciexpress)) {
-                       ah->config.serialize_regmode =
-                               SER_REG_MODE_ON;
-               } else {
-                       ah->config.serialize_regmode =
-                               SER_REG_MODE_OFF;
-               }
-       }
-
-       ath_dbg(common, RESET, "serialize_regmode is %d\n",
-               ah->config.serialize_regmode);
-
-       if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
-               ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
-       else
-               ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
-
-       switch (ah->hw_version.macVersion) {
-       case AR_SREV_VERSION_5416_PCI:
-       case AR_SREV_VERSION_5416_PCIE:
-       case AR_SREV_VERSION_9160:
-       case AR_SREV_VERSION_9100:
-       case AR_SREV_VERSION_9280:
-       case AR_SREV_VERSION_9285:
-       case AR_SREV_VERSION_9287:
-       case AR_SREV_VERSION_9271:
-       case AR_SREV_VERSION_9300:
-       case AR_SREV_VERSION_9330:
-       case AR_SREV_VERSION_9485:
-       case AR_SREV_VERSION_9340:
-       case AR_SREV_VERSION_9462:
-       case AR_SREV_VERSION_9550:
-       case AR_SREV_VERSION_9565:
-               break;
-       default:
-               ath_err(common,
-                       "Mac Chip Rev 0x%02x.%x is not supported by this driver\n",
-                       ah->hw_version.macVersion, ah->hw_version.macRev);
-               return -EOPNOTSUPP;
-       }
-
        if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
            AR_SREV_9330(ah) || AR_SREV_9550(ah))
                ah->is_pciexpress = false;
@@ -660,10 +570,6 @@ static int __ath9k_hw_init(struct ath_hw *ah)
        ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
        ath9k_hw_init_cal_settings(ah);
 
-       ah->ani_function = ATH9K_ANI_ALL;
-       if (!AR_SREV_9300_20_OR_LATER(ah))
-               ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
-
        if (!ah->is_pciexpress)
                ath9k_hw_disablepcie(ah);
 
@@ -682,15 +588,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
                return r;
        }
 
-       if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
-               ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
-       else
-               ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
-
-       if (AR_SREV_9330(ah))
-               ah->bb_watchdog_timeout_ms = 85;
-       else
-               ah->bb_watchdog_timeout_ms = 25;
+       ath9k_hw_init_hang_checks(ah);
 
        common->state = ATH_HW_INITIALIZED;
 
@@ -723,6 +621,7 @@ int ath9k_hw_init(struct ath_hw *ah)
        case AR9300_DEVID_AR9462:
        case AR9485_DEVID_AR1111:
        case AR9300_DEVID_AR9565:
+       case AR9300_DEVID_AR953X:
                break;
        default:
                if (common->bus_ops->ath_bus_type == ATH_USB)
@@ -858,7 +757,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
                /* program BB PLL phase_shift */
                REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
                              AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
-       } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
+       } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
                u32 regval, pll2_divint, pll2_divfrac, refdiv;
 
                REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
@@ -868,9 +767,15 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
                udelay(100);
 
                if (ah->is_clk_25mhz) {
-                       pll2_divint = 0x54;
-                       pll2_divfrac = 0x1eb85;
-                       refdiv = 3;
+                       if (AR_SREV_9531(ah)) {
+                               pll2_divint = 0x1c;
+                               pll2_divfrac = 0xa3d2;
+                               refdiv = 1;
+                       } else {
+                               pll2_divint = 0x54;
+                               pll2_divfrac = 0x1eb85;
+                               refdiv = 3;
+                       }
                } else {
                        if (AR_SREV_9340(ah)) {
                                pll2_divint = 88;
@@ -884,7 +789,10 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
                }
 
                regval = REG_READ(ah, AR_PHY_PLL_MODE);
-               regval |= (0x1 << 16);
+               if (AR_SREV_9531(ah))
+                       regval |= (0x1 << 22);
+               else
+                       regval |= (0x1 << 16);
                REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
                udelay(100);
 
@@ -894,14 +802,33 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
 
                regval = REG_READ(ah, AR_PHY_PLL_MODE);
                if (AR_SREV_9340(ah))
-                       regval = (regval & 0x80071fff) | (0x1 << 30) |
-                                (0x1 << 13) | (0x4 << 26) | (0x18 << 19);
+                       regval = (regval & 0x80071fff) |
+                               (0x1 << 30) |
+                               (0x1 << 13) |
+                               (0x4 << 26) |
+                               (0x18 << 19);
+               else if (AR_SREV_9531(ah))
+                       regval = (regval & 0x01c00fff) |
+                               (0x1 << 31) |
+                               (0x2 << 29) |
+                               (0xa << 25) |
+                               (0x1 << 19) |
+                               (0x6 << 12);
                else
-                       regval = (regval & 0x80071fff) | (0x3 << 30) |
-                                (0x1 << 13) | (0x4 << 26) | (0x60 << 19);
+                       regval = (regval & 0x80071fff) |
+                               (0x3 << 30) |
+                               (0x1 << 13) |
+                               (0x4 << 26) |
+                               (0x60 << 19);
                REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
-               REG_WRITE(ah, AR_PHY_PLL_MODE,
-                         REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff);
+
+               if (AR_SREV_9531(ah))
+                       REG_WRITE(ah, AR_PHY_PLL_MODE,
+                                 REG_READ(ah, AR_PHY_PLL_MODE) & 0xffbfffff);
+               else
+                       REG_WRITE(ah, AR_PHY_PLL_MODE,
+                                 REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff);
+
                udelay(1000);
        }
 
@@ -1281,6 +1208,42 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
        *coef_exponent = coef_exp - 16;
 }
 
+/* AR9330 WAR:
+ * call external reset function to reset WMAC if:
+ * - doing a cold reset
+ * - we have pending frames in the TX queues.
+ */
+static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
+{
+       int i, npend = 0;
+
+       for (i = 0; i < AR_NUM_QCU; i++) {
+               npend = ath9k_hw_numtxpending(ah, i);
+               if (npend)
+                       break;
+       }
+
+       if (ah->external_reset &&
+           (npend || type == ATH9K_RESET_COLD)) {
+               int reset_err = 0;
+
+               ath_dbg(ath9k_hw_common(ah), RESET,
+                       "reset MAC via external reset\n");
+
+               reset_err = ah->external_reset();
+               if (reset_err) {
+                       ath_err(ath9k_hw_common(ah),
+                               "External reset failed, err=%d\n",
+                               reset_err);
+                       return false;
+               }
+
+               REG_WRITE(ah, AR_RTC_RESET, 1);
+       }
+
+       return true;
+}
+
 static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
 {
        u32 rst_flags;
@@ -1331,38 +1294,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
        }
 
        if (AR_SREV_9330(ah)) {
-               int npend = 0;
-               int i;
-
-               /* AR9330 WAR:
-                * call external reset function to reset WMAC if:
-                * - doing a cold reset
-                * - we have pending frames in the TX queues
-                */
-
-               for (i = 0; i < AR_NUM_QCU; i++) {
-                       npend = ath9k_hw_numtxpending(ah, i);
-                       if (npend)
-                               break;
-               }
-
-               if (ah->external_reset &&
-                   (npend || type == ATH9K_RESET_COLD)) {
-                       int reset_err = 0;
-
-                       ath_dbg(ath9k_hw_common(ah), RESET,
-                               "reset MAC via external reset\n");
-
-                       reset_err = ah->external_reset();
-                       if (reset_err) {
-                               ath_err(ath9k_hw_common(ah),
-                                       "External reset failed, err=%d\n",
-                                       reset_err);
-                               return false;
-                       }
-
-                       REG_WRITE(ah, AR_RTC_RESET, 1);
-               }
+               if (!ath9k_hw_ar9330_reset_war(ah, type))
+                       return false;
        }
 
        if (ath9k_hw_mci_is_enabled(ah))
@@ -1372,7 +1305,12 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
 
        REGWRITE_BUFFER_FLUSH(ah);
 
-       udelay(50);
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               udelay(50);
+       else if (AR_SREV_9100(ah))
+               udelay(10000);
+       else
+               udelay(100);
 
        REG_WRITE(ah, AR_RTC_RC, 0);
        if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
@@ -1408,8 +1346,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 
        REGWRITE_BUFFER_FLUSH(ah);
 
-       if (!AR_SREV_9300_20_OR_LATER(ah))
-               udelay(2);
+       udelay(2);
 
        if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                REG_WRITE(ah, AR_RC, 0);
@@ -1485,7 +1422,6 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
        if (AR_SREV_9330(ah))
                ar9003_hw_internal_regulator_apply(ah);
        ath9k_hw_init_pll(ah, chan);
-       ath9k_hw_set_rfmode(ah, chan);
 
        return true;
 }
@@ -1574,76 +1510,6 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah)
        }
 }
 
-static bool ath9k_hw_check_dcs(u32 dma_dbg, u32 num_dcu_states,
-                              int *hang_state, int *hang_pos)
-{
-       static u32 dcu_chain_state[] = {5, 6, 9}; /* DCU chain stuck states */
-       u32 chain_state, dcs_pos, i;
-
-       for (dcs_pos = 0; dcs_pos < num_dcu_states; dcs_pos++) {
-               chain_state = (dma_dbg >> (5 * dcs_pos)) & 0x1f;
-               for (i = 0; i < 3; i++) {
-                       if (chain_state == dcu_chain_state[i]) {
-                               *hang_state = chain_state;
-                               *hang_pos = dcs_pos;
-                               return true;
-                       }
-               }
-       }
-       return false;
-}
-
-#define DCU_COMPLETE_STATE        1
-#define DCU_COMPLETE_STATE_MASK 0x3
-#define NUM_STATUS_READS         50
-static bool ath9k_hw_detect_mac_hang(struct ath_hw *ah)
-{
-       u32 chain_state, comp_state, dcs_reg = AR_DMADBG_4;
-       u32 i, hang_pos, hang_state, num_state = 6;
-
-       comp_state = REG_READ(ah, AR_DMADBG_6);
-
-       if ((comp_state & DCU_COMPLETE_STATE_MASK) != DCU_COMPLETE_STATE) {
-               ath_dbg(ath9k_hw_common(ah), RESET,
-                       "MAC Hang signature not found at DCU complete\n");
-               return false;
-       }
-
-       chain_state = REG_READ(ah, dcs_reg);
-       if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos))
-               goto hang_check_iter;
-
-       dcs_reg = AR_DMADBG_5;
-       num_state = 4;
-       chain_state = REG_READ(ah, dcs_reg);
-       if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos))
-               goto hang_check_iter;
-
-       ath_dbg(ath9k_hw_common(ah), RESET,
-               "MAC Hang signature 1 not found\n");
-       return false;
-
-hang_check_iter:
-       ath_dbg(ath9k_hw_common(ah), RESET,
-               "DCU registers: chain %08x complete %08x Hang: state %d pos %d\n",
-               chain_state, comp_state, hang_state, hang_pos);
-
-       for (i = 0; i < NUM_STATUS_READS; i++) {
-               chain_state = REG_READ(ah, dcs_reg);
-               chain_state = (chain_state >> (5 * hang_pos)) & 0x1f;
-               comp_state = REG_READ(ah, AR_DMADBG_6);
-
-               if (((comp_state & DCU_COMPLETE_STATE_MASK) !=
-                                       DCU_COMPLETE_STATE) ||
-                   (chain_state != hang_state))
-                       return false;
-       }
-
-       ath_dbg(ath9k_hw_common(ah), RESET, "MAC Hang signature 1 found\n");
-
-       return true;
-}
-
 void ath9k_hw_check_nav(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
@@ -1718,7 +1584,6 @@ static void ath9k_hw_reset_opmode(struct ath_hw *ah,
 
        REG_RMW(ah, AR_STA_ID1, macStaId1
                  | AR_STA_ID1_RTS_USE_DEF
-                 | (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
                  | ah->sta_id1_defaults,
                  ~AR_STA_ID1_SADH_MASK);
        ath_hw_setbssidmask(common);
@@ -1777,7 +1642,7 @@ static void ath9k_hw_init_desc(struct ath_hw *ah)
                }
 #ifdef __BIG_ENDIAN
                else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
-                        AR_SREV_9550(ah))
+                        AR_SREV_9550(ah) || AR_SREV_9531(ah))
                        REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
                else
                        REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
@@ -1907,7 +1772,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        /* Save TSF before chip reset, a cold reset clears it */
        tsf = ath9k_hw_gettsf64(ah);
        getrawmonotonic(&ts);
-       usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000;
+       usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000;
 
        saveLedState = REG_READ(ah, AR_CFG_LED) &
                (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
@@ -1941,7 +1806,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
        /* Restore TSF */
        getrawmonotonic(&ts);
-       usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000 - usec;
+       usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000 - usec;
        ath9k_hw_settsf64(ah, tsf + usec);
 
        if (AR_SREV_9280_20_OR_LATER(ah))
@@ -1954,6 +1819,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        if (r)
                return r;
 
+       ath9k_hw_set_rfmode(ah, chan);
+
        if (ath9k_hw_mci_is_enabled(ah))
                ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep);
 
@@ -2048,10 +1915,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        ath9k_hw_loadnf(ah, chan);
        ath9k_hw_start_nfcal(ah, true);
 
-       if (AR_SREV_9300_20_OR_LATER(ah)) {
+       if (AR_SREV_9300_20_OR_LATER(ah))
                ar9003_hw_bb_watchdog_config(ah);
+
+       if (ah->config.hw_hang_checks & HW_PHYRESTART_CLC_WAR)
                ar9003_hw_disable_phy_restart(ah);
-       }
 
        ath9k_hw_apply_gpio_override(ah);
 
@@ -2175,7 +2043,11 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
 
        REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
                    AR_RTC_FORCE_WAKE_EN);
-       udelay(50);
+
+       if (AR_SREV_9100(ah))
+               udelay(10000);
+       else
+               udelay(50);
 
        for (i = POWER_UP_TIME / 50; i > 0; i--) {
                val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
@@ -2264,9 +2136,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
        case NL80211_IFTYPE_ADHOC:
                REG_SET_BIT(ah, AR_TXCFG,
                            AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
-               REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon +
-                         TU_TO_USEC(ah->atim_window ? ah->atim_window : 1));
-               flags |= AR_NDP_TIMER_EN;
        case NL80211_IFTYPE_MESH_POINT:
        case NL80211_IFTYPE_AP:
                REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
@@ -2287,7 +2156,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
        REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period);
        REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period);
        REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period);
-       REG_WRITE(ah, AR_NDP_PERIOD, beacon_period);
 
        REGWRITE_BUFFER_FLUSH(ah);
 
@@ -2304,12 +2172,9 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
 
        ENABLE_REGWRITE_BUFFER(ah);
 
-       REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
-
-       REG_WRITE(ah, AR_BEACON_PERIOD,
-                 TU_TO_USEC(bs->bs_intval));
-       REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
-                 TU_TO_USEC(bs->bs_intval));
+       REG_WRITE(ah, AR_NEXT_TBTT_TIMER, bs->bs_nexttbtt);
+       REG_WRITE(ah, AR_BEACON_PERIOD, bs->bs_intval);
+       REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bs->bs_intval);
 
        REGWRITE_BUFFER_FLUSH(ah);
 
@@ -2337,9 +2202,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
 
        ENABLE_REGWRITE_BUFFER(ah);
 
-       REG_WRITE(ah, AR_NEXT_DTIM,
-                 TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
-       REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
+       REG_WRITE(ah, AR_NEXT_DTIM, bs->bs_nextdtim - SLEEP_SLOP);
+       REG_WRITE(ah, AR_NEXT_TIM, nextTbtt - SLEEP_SLOP);
 
        REG_WRITE(ah, AR_SLEEP1,
                  SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
@@ -2353,8 +2217,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
        REG_WRITE(ah, AR_SLEEP2,
                  SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
 
-       REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
-       REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
+       REG_WRITE(ah, AR_TIM_PERIOD, beaconintval);
+       REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod);
 
        REGWRITE_BUFFER_FLUSH(ah);
 
@@ -2612,13 +2476,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
            ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
                        pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
 
-       /*
-        * Fast channel change across bands is available
-        * only for AR9462 and AR9565.
-        */
-       if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
-               pCap->hw_caps |= ATH9K_HW_CAP_FCC_BAND_SWITCH;
-
        return 0;
 }
 
@@ -2990,20 +2847,6 @@ static const struct ath_gen_timer_configuration gen_tmr_configuration[] =
 
 /* HW generic timer primitives */
 
-/* compute and clear index of rightmost 1 */
-static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
-{
-       u32 b;
-
-       b = *mask;
-       b &= (0-b);
-       *mask &= ~b;
-       b *= debruijn32;
-       b >>= 27;
-
-       return timer_table->gen_timer_index[b];
-}
-
 u32 ath9k_hw_gettsf32(struct ath_hw *ah)
 {
        return REG_READ(ah, AR_TSF_L32);
@@ -3019,6 +2862,10 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
        struct ath_gen_timer *timer;
 
+       if ((timer_index < AR_FIRST_NDP_TIMER) ||
+               (timer_index >= ATH_MAX_GEN_TIMER))
+               return NULL;
+
        timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
        if (timer == NULL)
                return NULL;
@@ -3036,23 +2883,13 @@ EXPORT_SYMBOL(ath_gen_timer_alloc);
 
 void ath9k_hw_gen_timer_start(struct ath_hw *ah,
                              struct ath_gen_timer *timer,
-                             u32 trig_timeout,
+                             u32 timer_next,
                              u32 timer_period)
 {
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
-       u32 tsf, timer_next;
-
-       BUG_ON(!timer_period);
-
-       set_bit(timer->index, &timer_table->timer_mask.timer_bits);
+       u32 mask = 0;
 
-       tsf = ath9k_hw_gettsf32(ah);
-
-       timer_next = tsf + trig_timeout;
-
-       ath_dbg(ath9k_hw_common(ah), BTCOEX,
-               "current tsf %x period %x timer_next %x\n",
-               tsf, timer_period, timer_next);
+       timer_table->timer_mask |= BIT(timer->index);
 
        /*
         * Program generic timer registers
@@ -3078,10 +2915,19 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
                                       (1 << timer->index));
        }
 
-       /* Enable both trigger and thresh interrupt masks */
-       REG_SET_BIT(ah, AR_IMR_S5,
-               (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
-               SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
+       if (timer->trigger)
+               mask |= SM(AR_GENTMR_BIT(timer->index),
+                          AR_IMR_S5_GENTIMER_TRIG);
+       if (timer->overflow)
+               mask |= SM(AR_GENTMR_BIT(timer->index),
+                          AR_IMR_S5_GENTIMER_THRESH);
+
+       REG_SET_BIT(ah, AR_IMR_S5, mask);
+
+       if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
+               ah->imask |= ATH9K_INT_GENTIMER;
+               ath9k_hw_set_interrupts(ah);
+       }
 }
 EXPORT_SYMBOL(ath9k_hw_gen_timer_start);
 
@@ -3089,11 +2935,6 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
 {
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
 
-       if ((timer->index < AR_FIRST_NDP_TIMER) ||
-               (timer->index >= ATH_MAX_GEN_TIMER)) {
-               return;
-       }
-
        /* Clear generic timer enable bits. */
        REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
                        gen_tmr_configuration[timer->index].mode_mask);
@@ -3113,7 +2954,12 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
                (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
                SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
 
-       clear_bit(timer->index, &timer_table->timer_mask.timer_bits);
+       timer_table->timer_mask &= ~BIT(timer->index);
+
+       if (timer_table->timer_mask == 0) {
+               ah->imask &= ~ATH9K_INT_GENTIMER;
+               ath9k_hw_set_interrupts(ah);
+       }
 }
 EXPORT_SYMBOL(ath9k_hw_gen_timer_stop);
 
@@ -3134,32 +2980,32 @@ void ath_gen_timer_isr(struct ath_hw *ah)
 {
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
        struct ath_gen_timer *timer;
-       struct ath_common *common = ath9k_hw_common(ah);
-       u32 trigger_mask, thresh_mask, index;
+       unsigned long trigger_mask, thresh_mask;
+       unsigned int index;
 
        /* get hardware generic timer interrupt status */
        trigger_mask = ah->intr_gen_timer_trigger;
        thresh_mask = ah->intr_gen_timer_thresh;
-       trigger_mask &= timer_table->timer_mask.val;
-       thresh_mask &= timer_table->timer_mask.val;
-
-       trigger_mask &= ~thresh_mask;
+       trigger_mask &= timer_table->timer_mask;
+       thresh_mask &= timer_table->timer_mask;
 
-       while (thresh_mask) {
-               index = rightmost_index(timer_table, &thresh_mask);
+       for_each_set_bit(index, &thresh_mask, ARRAY_SIZE(timer_table->timers)) {
                timer = timer_table->timers[index];
-               BUG_ON(!timer);
-               ath_dbg(common, BTCOEX, "TSF overflow for Gen timer %d\n",
-                       index);
+               if (!timer)
+                   continue;
+               if (!timer->overflow)
+                   continue;
+
+               trigger_mask &= ~BIT(index);
                timer->overflow(timer->arg);
        }
 
-       while (trigger_mask) {
-               index = rightmost_index(timer_table, &trigger_mask);
+       for_each_set_bit(index, &trigger_mask, ARRAY_SIZE(timer_table->timers)) {
                timer = timer_table->timers[index];
-               BUG_ON(!timer);
-               ath_dbg(common, BTCOEX,
-                       "Gen timer[%d] trigger\n", index);
+               if (!timer)
+                   continue;
+               if (!timer->trigger)
+                   continue;
                timer->trigger(timer->arg);
        }
 }
index b1ff54631dcaa35c181f3b9f8cd03dbffc5d1259..e766399bdcdaede07d547832e0797a89dfb8efb1 100644 (file)
@@ -52,6 +52,7 @@
 #define AR9300_DEVID_QCA955X   0x0038
 #define AR9485_DEVID_AR1111    0x0037
 #define AR9300_DEVID_AR9565     0x0036
+#define AR9300_DEVID_AR953X     0x003d
 
 #define AR5416_AR9100_DEVID    0x000b
 
 #define CAB_TIMEOUT_VAL             10
 #define BEACON_TIMEOUT_VAL          10
 #define MIN_BEACON_TIMEOUT_VAL      1
-#define SLEEP_SLOP                  3
+#define SLEEP_SLOP                  TU_TO_USEC(3)
 
 #define INIT_CONFIG_STATUS          0x00000000
 #define INIT_RSSI_THR               0x00000700
@@ -277,13 +278,25 @@ struct ath9k_hw_capabilities {
        u8 txs_len;
 };
 
+#define AR_NO_SPUR             0x8000
+#define AR_BASE_FREQ_2GHZ      2300
+#define AR_BASE_FREQ_5GHZ      4900
+#define AR_SPUR_FEEQ_BOUND_HT40 19
+#define AR_SPUR_FEEQ_BOUND_HT20 10
+
+enum ath9k_hw_hang_checks {
+       HW_BB_WATCHDOG            = BIT(0),
+       HW_PHYRESTART_CLC_WAR     = BIT(1),
+       HW_BB_RIFS_HANG           = BIT(2),
+       HW_BB_DFS_HANG            = BIT(3),
+       HW_BB_RX_CLEAR_STUCK_HANG = BIT(4),
+       HW_MAC_HANG               = BIT(5),
+};
+
 struct ath9k_ops_config {
        int dma_beacon_response_time;
        int sw_beacon_response_time;
-       int additional_swba_backoff;
-       int ack_6mb;
        u32 cwm_ignore_extcca;
-       u8 pcie_clock_req;
        u32 pcie_waen;
        u8 analog_shiftreg;
        u32 ofdm_trig_low;
@@ -294,20 +307,9 @@ struct ath9k_ops_config {
        int serialize_regmode;
        bool rx_intr_mitigation;
        bool tx_intr_mitigation;
-#define SPUR_DISABLE           0
-#define SPUR_ENABLE_IOCTL      1
-#define SPUR_ENABLE_EEPROM     2
-#define AR_SPUR_5413_1         1640
-#define AR_SPUR_5413_2         1200
-#define AR_NO_SPUR             0x8000
-#define AR_BASE_FREQ_2GHZ      2300
-#define AR_BASE_FREQ_5GHZ      4900
-#define AR_SPUR_FEEQ_BOUND_HT40 19
-#define AR_SPUR_FEEQ_BOUND_HT20 10
-       int spurmode;
-       u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
        u8 max_txtrig_level;
        u16 ani_poll_interval; /* ANI poll interval in ms */
+       u16 hw_hang_checks;
 
        /* Platform specific config */
        u32 aspm_l1_fix;
@@ -460,10 +462,6 @@ struct ath9k_beacon_state {
        u32 bs_intval;
 #define ATH9K_TSFOOR_THRESHOLD    0x00004240 /* 16k us */
        u32 bs_dtimperiod;
-       u16 bs_cfpperiod;
-       u16 bs_cfpmaxduration;
-       u32 bs_cfpnext;
-       u16 bs_timoffset;
        u16 bs_bmissthreshold;
        u32 bs_sleepduration;
        u32 bs_tsfoor_threshold;
@@ -499,12 +497,6 @@ struct ath9k_hw_version {
 
 #define AR_GENTMR_BIT(_index)  (1 << (_index))
 
-/*
- * Using de Bruijin sequence to look up 1's index in a 32 bit number
- * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
- */
-#define debruijn32 0x077CB531U
-
 struct ath_gen_timer_configuration {
        u32 next_addr;
        u32 period_addr;
@@ -520,12 +512,8 @@ struct ath_gen_timer {
 };
 
 struct ath_gen_timer_table {
-       u32 gen_timer_index[32];
        struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER];
-       union {
-               unsigned long timer_bits;
-               u16 val;
-       } timer_mask;
+       u16 timer_mask;
 };
 
 struct ath_hw_antcomb_conf {
@@ -596,6 +584,10 @@ struct ath_hw_radar_conf {
  *     register settings through the register initialization.
  */
 struct ath_hw_private_ops {
+       void (*init_hang_checks)(struct ath_hw *ah);
+       bool (*detect_mac_hang)(struct ath_hw *ah);
+       bool (*detect_bb_hang)(struct ath_hw *ah);
+
        /* Calibration ops */
        void (*init_cal_settings)(struct ath_hw *ah);
        bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan);
@@ -690,7 +682,8 @@ struct ath_hw_ops {
                          struct ath9k_channel *chan,
                          u8 rxchainmask,
                          bool longcal);
-       bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
+       bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked,
+                       u32 *sync_cause_p);
        void (*set_txdesc)(struct ath_hw *ah, void *ds,
                           struct ath_tx_info *i);
        int (*proc_txdesc)(struct ath_hw *ah, void *ds,
@@ -786,7 +779,6 @@ struct ath_hw {
        u32 txurn_interrupt_mask;
        atomic_t intr_ref_cnt;
        bool chip_fullsleep;
-       u32 atim_window;
        u32 modes_index;
 
        /* Calibration */
@@ -1018,13 +1010,6 @@ bool ath9k_hw_check_alive(struct ath_hw *ah);
 
 bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
 
-#ifdef CONFIG_ATH9K_DEBUGFS
-void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause);
-#else
-static inline void ath9k_debug_sync_cause(struct ath_common *common,
-                                         u32 sync_cause) {}
-#endif
-
 /* Generic hw timer primitives */
 struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
                                          void (*trigger)(void *),
@@ -1059,6 +1044,7 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
  * Code specific to AR9003, we stuff these here to avoid callbacks
  * for older families
  */
+bool ar9003_hw_bb_watchdog_check(struct ath_hw *ah);
 void ar9003_hw_bb_watchdog_config(struct ath_hw *ah);
 void ar9003_hw_bb_watchdog_read(struct ath_hw *ah);
 void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah);
index 609b7e13f3f0afaf3c3f86cdb0589c302a5e98d0..f2a17fcf1ae412834bd7c0c0b16471429b007e59 100644 (file)
@@ -470,7 +470,6 @@ static int ath9k_init_queues(struct ath_softc *sc)
 
        sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
        sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
-
        ath_cabq_update(sc);
 
        sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0);
@@ -705,7 +704,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        ah->reg_ops.read = ath9k_ioread32;
        ah->reg_ops.write = ath9k_iowrite32;
        ah->reg_ops.rmw = ath9k_reg_rmw;
-       atomic_set(&ah->intr_ref_cnt, -1);
        sc->sc_ah = ah;
        pCap = &ah->caps;
 
@@ -765,10 +763,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
 
        setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc);
        INIT_WORK(&sc->hw_reset_work, ath_reset_work);
-       INIT_WORK(&sc->hw_check_work, ath_hw_check);
        INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
        INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
-       setup_timer(&sc->rx_poll_timer, ath_rx_poll, (unsigned long)sc);
 
        /*
         * Cache line size is used to size and align various
@@ -899,7 +895,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
        }
 };
 
-void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
index aed7e29dc50f152b954278020b8b2999f3e795e7..30dcef5aba100d0edfaf7171aa38726ef6e42674 100644 (file)
@@ -65,50 +65,26 @@ void ath_tx_complete_poll_work(struct work_struct *work)
 /*
  * Checks if the BB/MAC is hung.
  */
-void ath_hw_check(struct work_struct *work)
+bool ath_hw_check(struct ath_softc *sc)
 {
-       struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       unsigned long flags;
-       int busy;
-       u8 is_alive, nbeacon = 1;
        enum ath_reset_type type;
+       bool is_alive;
 
        ath9k_ps_wakeup(sc);
+
        is_alive = ath9k_hw_check_alive(sc->sc_ah);
 
-       if ((is_alive && !AR_SREV_9300(sc->sc_ah)) || sc->tx99_state)
-               goto out;
-       else if (!is_alive && AR_SREV_9300(sc->sc_ah)) {
+       if (!is_alive) {
                ath_dbg(common, RESET,
-                       "DCU stuck is detected. Schedule chip reset\n");
+                       "HW hang detected, schedule chip reset\n");
                type = RESET_TYPE_MAC_HANG;
-               goto sched_reset;
-       }
-
-       spin_lock_irqsave(&common->cc_lock, flags);
-       busy = ath_update_survey_stats(sc);
-       spin_unlock_irqrestore(&common->cc_lock, flags);
-
-       ath_dbg(common, RESET, "Possible baseband hang, busy=%d (try %d)\n",
-               busy, sc->hw_busy_count + 1);
-       if (busy >= 99) {
-               if (++sc->hw_busy_count >= 3) {
-                       type = RESET_TYPE_BB_HANG;
-                       goto sched_reset;
-               }
-       } else if (busy >= 0) {
-               sc->hw_busy_count = 0;
-               nbeacon = 3;
+               ath9k_queue_reset(sc, type);
        }
 
-       ath_start_rx_poll(sc, nbeacon);
-       goto out;
-
-sched_reset:
-       ath9k_queue_reset(sc, type);
-out:
        ath9k_ps_restore(sc);
+
+       return is_alive;
 }
 
 /*
@@ -161,29 +137,6 @@ void ath_hw_pll_work(struct work_struct *work)
                                     msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
 }
 
-/*
- * RX Polling - monitors baseband hangs.
- */
-void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon)
-{
-       if (!AR_SREV_9300(sc->sc_ah))
-               return;
-
-       if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
-               return;
-
-       mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies
-                 (nbeacon * sc->cur_beacon_conf.beacon_interval));
-}
-
-void ath_rx_poll(unsigned long data)
-{
-       struct ath_softc *sc = (struct ath_softc *)data;
-
-       if (!test_bit(SC_OP_INVALID, &sc->sc_flags))
-               ieee80211_queue_work(sc->hw, &sc->hw_check_work);
-}
-
 /*
  * PA Pre-distortion.
  */
@@ -409,10 +362,10 @@ void ath_ani_calibrate(unsigned long data)
 
        /* Call ANI routine if necessary */
        if (aniflag) {
-               spin_lock_irqsave(&common->cc_lock, flags);
+               spin_lock(&common->cc_lock);
                ath9k_hw_ani_monitor(ah, ah->curchan);
                ath_update_survey_stats(sc);
-               spin_unlock_irqrestore(&common->cc_lock, flags);
+               spin_unlock(&common->cc_lock);
        }
 
        /* Perform calibration if necessary */
index 6a18f9d3e9cc952ef116f9fda1bf56f37526d8bc..5f727588ca2788b0e598ccf98450af8f396c7135 100644 (file)
@@ -481,8 +481,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
                            | AR_Q_MISC_CBR_INCR_DIS0);
                value = (qi->tqi_readyTime -
                         (ah->config.sw_beacon_response_time -
-                         ah->config.dma_beacon_response_time) -
-                        ah->config.additional_swba_backoff) * 1024;
+                         ah->config.dma_beacon_response_time)) * 1024;
                REG_WRITE(ah, AR_QRDYTIMECFG(q),
                          value | AR_Q_RDYTIMECFG_EN);
                REG_SET_BIT(ah, AR_DMISC(q),
@@ -550,25 +549,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
 
        if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
                rs->rs_rssi = ATH9K_RSSI_BAD;
-               rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
-               rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
-               rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
-               rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
-               rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
-               rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
+               rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
        } else {
                rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
-               rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
+               rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
                                                AR_RxRSSIAnt00);
-               rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
+               rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
                                                AR_RxRSSIAnt01);
-               rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
+               rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
                                                AR_RxRSSIAnt02);
-               rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
+               rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
                                                AR_RxRSSIAnt10);
-               rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
+               rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
                                                AR_RxRSSIAnt11);
-               rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
+               rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
                                                AR_RxRSSIAnt12);
        }
        if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
@@ -923,11 +922,29 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah)
                        mask2 |= AR_IMR_S2_CST;
        }
 
+       if (ah->config.hw_hang_checks & HW_BB_WATCHDOG) {
+               if (ints & ATH9K_INT_BB_WATCHDOG) {
+                       mask |= AR_IMR_BCNMISC;
+                       mask2 |= AR_IMR_S2_BB_WATCHDOG;
+               }
+       }
+
        ath_dbg(common, INTERRUPT, "new IMR 0x%x\n", mask);
        REG_WRITE(ah, AR_IMR, mask);
-       ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
-                          AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
-                          AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
+       ah->imrs2_reg &= ~(AR_IMR_S2_TIM |
+                          AR_IMR_S2_DTIM |
+                          AR_IMR_S2_DTIMSYNC |
+                          AR_IMR_S2_CABEND |
+                          AR_IMR_S2_CABTO |
+                          AR_IMR_S2_TSFOOR |
+                          AR_IMR_S2_GTT |
+                          AR_IMR_S2_CST);
+
+       if (ah->config.hw_hang_checks & HW_BB_WATCHDOG) {
+               if (ints & ATH9K_INT_BB_WATCHDOG)
+                       ah->imrs2_reg &= ~AR_IMR_S2_BB_WATCHDOG;
+       }
+
        ah->imrs2_reg |= mask2;
        REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
 
index e3eed81f24391c61b1389a749d471cf4ad662056..10271373a0cd1081fa89b53ee35992982fd7679b 100644 (file)
@@ -133,12 +133,8 @@ struct ath_rx_status {
        u8 rs_rate;
        u8 rs_antenna;
        u8 rs_more;
-       int8_t rs_rssi_ctl0;
-       int8_t rs_rssi_ctl1;
-       int8_t rs_rssi_ctl2;
-       int8_t rs_rssi_ext0;
-       int8_t rs_rssi_ext1;
-       int8_t rs_rssi_ext2;
+       int8_t rs_rssi_ctl[3];
+       int8_t rs_rssi_ext[3];
        u8 rs_isaggr;
        u8 rs_firstaggr;
        u8 rs_moreaggr;
index b1dcf89138d30d4ce8899e9a117ee96ac29212e5..d0c3aec7c74e5ba4821eb2a234a1902476d4fa89 100644 (file)
@@ -170,7 +170,6 @@ void ath9k_ps_restore(struct ath_softc *sc)
 static void __ath_cancel_work(struct ath_softc *sc)
 {
        cancel_work_sync(&sc->paprd_work);
-       cancel_work_sync(&sc->hw_check_work);
        cancel_delayed_work_sync(&sc->tx_complete_work);
        cancel_delayed_work_sync(&sc->hw_pll_work);
 
@@ -194,7 +193,6 @@ void ath_restart_work(struct ath_softc *sc)
                ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
                                     msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
 
-       ath_start_rx_poll(sc, 3);
        ath_start_ani(sc);
 }
 
@@ -204,11 +202,7 @@ static bool ath_prepare_reset(struct ath_softc *sc)
        bool ret = true;
 
        ieee80211_stop_queues(sc->hw);
-
-       sc->hw_busy_count = 0;
        ath_stop_ani(sc);
-       del_timer_sync(&sc->rx_poll_timer);
-
        ath9k_hw_disable_interrupts(ah);
 
        if (!ath_drain_all_txq(sc))
@@ -336,7 +330,6 @@ static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chand
        struct ieee80211_hw *hw = sc->hw;
        struct ath9k_channel *hchan;
        struct ieee80211_channel *chan = chandef->chan;
-       unsigned long flags;
        bool offchannel;
        int pos = chan->hw_value;
        int old_pos = -1;
@@ -354,9 +347,9 @@ static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chand
                chan->center_freq, chandef->width);
 
        /* update survey stats for the old channel before switching */
-       spin_lock_irqsave(&common->cc_lock, flags);
+       spin_lock_bh(&common->cc_lock);
        ath_update_survey_stats(sc);
-       spin_unlock_irqrestore(&common->cc_lock, flags);
+       spin_unlock_bh(&common->cc_lock);
 
        ath9k_cmn_get_channel(hw, ah, chandef);
 
@@ -427,12 +420,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
        an->vif = vif;
 
        ath_tx_node_init(sc, an);
-
-       if (sta->ht_cap.ht_supported) {
-               an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
-                                    sta->ht_cap.ampdu_factor);
-               an->mpdudensity = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
-       }
 }
 
 static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
@@ -454,14 +441,8 @@ void ath9k_tasklet(unsigned long data)
        ath9k_ps_wakeup(sc);
        spin_lock(&sc->sc_pcu_lock);
 
-       if ((status & ATH9K_INT_FATAL) ||
-           (status & ATH9K_INT_BB_WATCHDOG)) {
-
-               if (status & ATH9K_INT_FATAL)
-                       type = RESET_TYPE_FATAL_INT;
-               else
-                       type = RESET_TYPE_BB_WATCHDOG;
-
+       if (status & ATH9K_INT_FATAL) {
+               type = RESET_TYPE_FATAL_INT;
                ath9k_queue_reset(sc, type);
 
                /*
@@ -473,6 +454,28 @@ void ath9k_tasklet(unsigned long data)
                goto out;
        }
 
+       if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
+           (status & ATH9K_INT_BB_WATCHDOG)) {
+               spin_lock(&common->cc_lock);
+               ath_hw_cycle_counters_update(common);
+               ar9003_hw_bb_watchdog_dbg_info(ah);
+               spin_unlock(&common->cc_lock);
+
+               if (ar9003_hw_bb_watchdog_check(ah)) {
+                       type = RESET_TYPE_BB_WATCHDOG;
+                       ath9k_queue_reset(sc, type);
+
+                       /*
+                        * Increment the ref. counter here so that
+                        * interrupts are enabled in the reset routine.
+                        */
+                       atomic_inc(&ah->intr_ref_cnt);
+                       ath_dbg(common, ANY,
+                               "BB_WATCHDOG: Skipping interrupts\n");
+                       goto out;
+               }
+       }
+
        spin_lock_irqsave(&sc->sc_pm_lock, flags);
        if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {
                /*
@@ -508,6 +511,9 @@ void ath9k_tasklet(unsigned long data)
                wake_up(&sc->tx_wait);
        }
 
+       if (status & ATH9K_INT_GENTIMER)
+               ath_gen_timer_isr(sc->sc_ah);
+
        ath9k_btcoex_handle_interrupt(sc, status);
 
        /* re-enable hardware interrupt */
@@ -538,6 +544,7 @@ irqreturn_t ath_isr(int irq, void *dev)
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        enum ath9k_int status;
+       u32 sync_cause = 0;
        bool sched = false;
 
        /*
@@ -564,7 +571,8 @@ irqreturn_t ath_isr(int irq, void *dev)
         * bits we haven't explicitly enabled so we mask the
         * value to insure we only process bits we requested.
         */
-       ath9k_hw_getisr(ah, &status);   /* NB: clears ISR too */
+       ath9k_hw_getisr(ah, &status, &sync_cause); /* NB: clears ISR too */
+       ath9k_debug_sync_cause(sc, sync_cause);
        status &= ah->imask;    /* discard unasked-for bits */
 
        /*
@@ -588,16 +596,9 @@ irqreturn_t ath_isr(int irq, void *dev)
            !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
                goto chip_reset;
 
-       if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
-           (status & ATH9K_INT_BB_WATCHDOG)) {
-
-               spin_lock(&common->cc_lock);
-               ath_hw_cycle_counters_update(common);
-               ar9003_hw_bb_watchdog_dbg_info(ah);
-               spin_unlock(&common->cc_lock);
-
+       if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
+           (status & ATH9K_INT_BB_WATCHDOG))
                goto chip_reset;
-       }
 
 #ifdef CONFIG_ATH9K_WOW
        if (status & ATH9K_INT_BMISS) {
@@ -727,11 +728,13 @@ static int ath9k_start(struct ieee80211_hw *hw)
 
        if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
                ah->imask |= ATH9K_INT_RXHP |
-                            ATH9K_INT_RXLP |
-                            ATH9K_INT_BB_WATCHDOG;
+                            ATH9K_INT_RXLP;
        else
                ah->imask |= ATH9K_INT_RX;
 
+       if (ah->config.hw_hang_checks & HW_BB_WATCHDOG)
+               ah->imask |= ATH9K_INT_BB_WATCHDOG;
+
        ah->imask |= ATH9K_INT_GTT;
 
        if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
@@ -757,6 +760,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
         */
        ath9k_cmn_init_crypto(sc->sc_ah);
 
+       ath9k_hw_reset_tsf(ah);
+
        spin_unlock_bh(&sc->sc_pcu_lock);
 
        mutex_unlock(&sc->mutex);
@@ -853,7 +858,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
        mutex_lock(&sc->mutex);
 
        ath_cancel_work(sc);
-       del_timer_sync(&sc->rx_poll_timer);
 
        if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {
                ath_dbg(common, ANY, "Device not present\n");
@@ -987,8 +991,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
        struct ath_common *common = ath9k_hw_common(ah);
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
        memset(iter_data, 0, sizeof(*iter_data));
        memset(&iter_data->mask, 0xff, ETH_ALEN);
@@ -1657,13 +1662,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
-           (changed & BSS_CHANGED_BEACON_INT)) {
-               if (ah->opmode == NL80211_IFTYPE_AP &&
-                   bss_conf->enable_beacon)
-                       ath9k_set_tsfadjust(sc, vif);
-               if (ath9k_allow_beacon_config(sc, vif))
-                       ath9k_beacon_config(sc, vif, changed);
-       }
+           (changed & BSS_CHANGED_BEACON_INT))
+               ath9k_beacon_config(sc, vif, changed);
 
        if (changed & BSS_CHANGED_ERP_SLOT) {
                if (bss_conf->use_short_slot)
@@ -1788,13 +1788,12 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ieee80211_supported_band *sband;
        struct ieee80211_channel *chan;
-       unsigned long flags;
        int pos;
 
        if (config_enabled(CONFIG_ATH9K_TX99))
                return -EOPNOTSUPP;
 
-       spin_lock_irqsave(&common->cc_lock, flags);
+       spin_lock_bh(&common->cc_lock);
        if (idx == 0)
                ath_update_survey_stats(sc);
 
@@ -1808,7 +1807,7 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
                sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
 
        if (!sband || idx >= sband->n_channels) {
-               spin_unlock_irqrestore(&common->cc_lock, flags);
+               spin_unlock_bh(&common->cc_lock);
                return -ENOENT;
        }
 
@@ -1816,7 +1815,7 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
        pos = chan->hw_value;
        memcpy(survey, &sc->survey[pos], sizeof(*survey));
        survey->channel = chan;
-       spin_unlock_irqrestore(&common->cc_lock, flags);
+       spin_unlock_bh(&common->cc_lock);
 
        return 0;
 }
index 0ac1b5f04256517050be277696e9a9eae4f2391c..71799fcade543fca00ba709970c26f6ff33a948e 100644 (file)
@@ -200,7 +200,7 @@ skip_tuning:
        if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE)
                btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE;
 
-       btcoex->btcoex_no_stomp =  btcoex->btcoex_period * 1000 *
+       btcoex->btcoex_no_stomp =  btcoex->btcoex_period *
                (100 - btcoex->duty_cycle) / 100;
 
        ath9k_hw_btcoex_enable(sc->sc_ah);
index e9a585758941fc9305fa859bab091992eb9946a8..55724b02316b17d44c9d7d788f0d55452c616286 100644 (file)
@@ -409,6 +409,16 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         0x11AD, /* LITEON */
                         0x0632),
          .driver_data = ATH9K_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x06B2),
+         .driver_data = ATH9K_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0842),
+         .driver_data = ATH9K_PCI_AR9565_1ANT },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         0x11AD, /* LITEON */
@@ -424,6 +434,16 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         0x1B9A, /* XAVI */
                         0x2812),
          .driver_data = ATH9K_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x1B9A, /* XAVI */
+                        0x28A1),
+         .driver_data = ATH9K_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x218A),
+         .driver_data = ATH9K_PCI_AR9565_1ANT },
 
        /* WB335 1-ANT / Antenna Diversity */
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
@@ -469,22 +489,17 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         0x11AD, /* LITEON */
-                        0x0682),
+                        0x06A2),
          .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
-                        PCI_VENDOR_ID_AZWAVE,
-                        0x213A),
-         .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
-       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
-                        0x0036,
-                        PCI_VENDOR_ID_LENOVO,
-                        0x3026),
+                        0x11AD, /* LITEON */
+                        0x0682),
          .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
-                        PCI_VENDOR_ID_LENOVO,
-                        0x4026),
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x213A),
          .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
@@ -504,37 +519,35 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_DELL,
-                        0x020E),
+                        0x020C),
          .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
 
-       /* WB335 2-ANT */
+       /* WB335 2-ANT / Antenna-Diversity */
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_SAMSUNG,
                         0x411A),
-         .driver_data = ATH9K_PCI_AR9565_2ANT },
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_SAMSUNG,
                         0x411B),
-         .driver_data = ATH9K_PCI_AR9565_2ANT },
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_SAMSUNG,
                         0x411C),
-         .driver_data = ATH9K_PCI_AR9565_2ANT },
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_SAMSUNG,
                         0x411D),
-         .driver_data = ATH9K_PCI_AR9565_2ANT },
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_SAMSUNG,
                         0x411E),
-         .driver_data = ATH9K_PCI_AR9565_2ANT },
-
-       /* WB335 2-ANT / Antenna-Diversity */
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_ATHEROS,
@@ -560,11 +573,31 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         0x11AD, /* LITEON */
                         0x0612),
          .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0832),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0692),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_AZWAVE,
                         0x2130),
          .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x213B),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2182),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         0x144F, /* ASKEY */
@@ -575,6 +608,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         0x1B9A, /* XAVI */
                         0x2810),
          .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x1B9A, /* XAVI */
+                        0x28A2),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         0x185F, /* WNC */
@@ -590,6 +628,31 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         PCI_VENDOR_ID_FOXCONN,
                         0xE07F),
          .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE081),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_LENOVO,
+                        0x3026),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_LENOVO,
+                        0x4026),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_ASUSTEK,
+                        0x85F2),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_DELL,
+                        0x020E),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
 
        /* PCI-E AR9565 (WB335) */
        { PCI_VDEVICE(ATHEROS, 0x0036),
index 95ddca5495d492cb5a1bf4bb99d8ee3283a9e1ec..f7cc5b37a18ff4b54fd7be877629107c9ba2f576 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/dma-mapping.h>
-#include <linux/relay.h>
 #include "ath9k.h"
 #include "ar9003_mac.h"
 
@@ -420,7 +419,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
                rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
        }
 
-       if (AR_SREV_9550(sc->sc_ah))
+       if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah))
                rfilt |= ATH9K_RX_FILTER_4ADDRESS;
 
        return rfilt;
@@ -851,20 +850,15 @@ static int ath9k_process_rate(struct ath_common *common,
        enum ieee80211_band band;
        unsigned int i = 0;
        struct ath_softc __maybe_unused *sc = common->priv;
+       struct ath_hw *ah = sc->sc_ah;
 
-       band = hw->conf.chandef.chan->band;
+       band = ah->curchan->chan->band;
        sband = hw->wiphy->bands[band];
 
-       switch (hw->conf.chandef.width) {
-       case NL80211_CHAN_WIDTH_5:
+       if (IS_CHAN_QUARTER_RATE(ah->curchan))
                rxs->flag |= RX_FLAG_5MHZ;
-               break;
-       case NL80211_CHAN_WIDTH_10:
+       else if (IS_CHAN_HALF_RATE(ah->curchan))
                rxs->flag |= RX_FLAG_10MHZ;
-               break;
-       default:
-               break;
-       }
 
        if (rx_stats->rs_rate & 0x80) {
                /* HT rate */
@@ -906,6 +900,7 @@ static void ath9k_process_rssi(struct ath_common *common,
        struct ath_hw *ah = common->ah;
        int last_rssi;
        int rssi = rx_stats->rs_rssi;
+       int i, j;
 
        /*
         * RSSI is not available for subframes in an A-MPDU.
@@ -924,6 +919,20 @@ static void ath9k_process_rssi(struct ath_common *common,
                return;
        }
 
+       for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
+               s8 rssi;
+
+               if (!(ah->rxchainmask & BIT(i)))
+                       continue;
+
+               rssi = rx_stats->rs_rssi_ctl[i];
+               if (rssi != ATH9K_RSSI_BAD) {
+                   rxs->chains |= BIT(j);
+                   rxs->chain_signal[j] = ah->noise + rssi;
+               }
+               j++;
+       }
+
        /*
         * Update Beacon RSSI, this is used by ANI.
         */
@@ -960,186 +969,6 @@ static void ath9k_process_tsf(struct ath_rx_status *rs,
                rxs->mactime += 0x100000000ULL;
 }
 
-#ifdef CONFIG_ATH9K_DEBUGFS
-static s8 fix_rssi_inv_only(u8 rssi_val)
-{
-       if (rssi_val == 128)
-               rssi_val = 0;
-       return (s8) rssi_val;
-}
-#endif
-
-/* returns 1 if this was a spectral frame, even if not handled. */
-static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
-                          struct ath_rx_status *rs, u64 tsf)
-{
-#ifdef CONFIG_ATH9K_DEBUGFS
-       struct ath_hw *ah = sc->sc_ah;
-       u8 num_bins, *bins, *vdata = (u8 *)hdr;
-       struct fft_sample_ht20 fft_sample_20;
-       struct fft_sample_ht20_40 fft_sample_40;
-       struct fft_sample_tlv *tlv;
-       struct ath_radar_info *radar_info;
-       int len = rs->rs_datalen;
-       int dc_pos;
-       u16 fft_len, length, freq = ah->curchan->chan->center_freq;
-       enum nl80211_channel_type chan_type;
-
-       /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
-        * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
-        * yet, but this is supposed to be possible as well.
-        */
-       if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
-           rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
-           rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
-               return 0;
-
-       /* check if spectral scan bit is set. This does not have to be checked
-        * if received through a SPECTRAL phy error, but shouldn't hurt.
-        */
-       radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
-       if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
-               return 0;
-
-       chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef);
-       if ((chan_type == NL80211_CHAN_HT40MINUS) ||
-           (chan_type == NL80211_CHAN_HT40PLUS)) {
-               fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN;
-               num_bins = SPECTRAL_HT20_40_NUM_BINS;
-               bins = (u8 *)fft_sample_40.data;
-       } else {
-               fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN;
-               num_bins = SPECTRAL_HT20_NUM_BINS;
-               bins = (u8 *)fft_sample_20.data;
-       }
-
-       /* Variation in the data length is possible and will be fixed later */
-       if ((len > fft_len + 2) || (len < fft_len - 1))
-               return 1;
-
-       switch (len - fft_len) {
-       case 0:
-               /* length correct, nothing to do. */
-               memcpy(bins, vdata, num_bins);
-               break;
-       case -1:
-               /* first byte missing, duplicate it. */
-               memcpy(&bins[1], vdata, num_bins - 1);
-               bins[0] = vdata[0];
-               break;
-       case 2:
-               /* MAC added 2 extra bytes at bin 30 and 32, remove them. */
-               memcpy(bins, vdata, 30);
-               bins[30] = vdata[31];
-               memcpy(&bins[31], &vdata[33], num_bins - 31);
-               break;
-       case 1:
-               /* MAC added 2 extra bytes AND first byte is missing. */
-               bins[0] = vdata[0];
-               memcpy(&bins[1], vdata, 30);
-               bins[31] = vdata[31];
-               memcpy(&bins[32], &vdata[33], num_bins - 32);
-               break;
-       default:
-               return 1;
-       }
-
-       /* DC value (value in the middle) is the blind spot of the spectral
-        * sample and invalid, interpolate it.
-        */
-       dc_pos = num_bins / 2;
-       bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2;
-
-       if ((chan_type == NL80211_CHAN_HT40MINUS) ||
-           (chan_type == NL80211_CHAN_HT40PLUS)) {
-               s8 lower_rssi, upper_rssi;
-               s16 ext_nf;
-               u8 lower_max_index, upper_max_index;
-               u8 lower_bitmap_w, upper_bitmap_w;
-               u16 lower_mag, upper_mag;
-               struct ath9k_hw_cal_data *caldata = ah->caldata;
-               struct ath_ht20_40_mag_info *mag_info;
-
-               if (caldata)
-                       ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan,
-                                       caldata->nfCalHist[3].privNF);
-               else
-                       ext_nf = ATH_DEFAULT_NOISE_FLOOR;
-
-               length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv);
-               fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40;
-               fft_sample_40.tlv.length = __cpu_to_be16(length);
-               fft_sample_40.freq = __cpu_to_be16(freq);
-               fft_sample_40.channel_type = chan_type;
-
-               if (chan_type == NL80211_CHAN_HT40PLUS) {
-                       lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
-                       upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
-
-                       fft_sample_40.lower_noise = ah->noise;
-                       fft_sample_40.upper_noise = ext_nf;
-               } else {
-                       lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
-                       upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
-
-                       fft_sample_40.lower_noise = ext_nf;
-                       fft_sample_40.upper_noise = ah->noise;
-               }
-               fft_sample_40.lower_rssi = lower_rssi;
-               fft_sample_40.upper_rssi = upper_rssi;
-
-               mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1;
-               lower_mag = spectral_max_magnitude(mag_info->lower_bins);
-               upper_mag = spectral_max_magnitude(mag_info->upper_bins);
-               fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag);
-               fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag);
-               lower_max_index = spectral_max_index(mag_info->lower_bins);
-               upper_max_index = spectral_max_index(mag_info->upper_bins);
-               fft_sample_40.lower_max_index = lower_max_index;
-               fft_sample_40.upper_max_index = upper_max_index;
-               lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins);
-               upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins);
-               fft_sample_40.lower_bitmap_weight = lower_bitmap_w;
-               fft_sample_40.upper_bitmap_weight = upper_bitmap_w;
-               fft_sample_40.max_exp = mag_info->max_exp & 0xf;
-
-               fft_sample_40.tsf = __cpu_to_be64(tsf);
-
-               tlv = (struct fft_sample_tlv *)&fft_sample_40;
-       } else {
-               u8 max_index, bitmap_w;
-               u16 magnitude;
-               struct ath_ht20_mag_info *mag_info;
-
-               length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv);
-               fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20;
-               fft_sample_20.tlv.length = __cpu_to_be16(length);
-               fft_sample_20.freq = __cpu_to_be16(freq);
-
-               fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
-               fft_sample_20.noise = ah->noise;
-
-               mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
-               magnitude = spectral_max_magnitude(mag_info->all_bins);
-               fft_sample_20.max_magnitude = __cpu_to_be16(magnitude);
-               max_index = spectral_max_index(mag_info->all_bins);
-               fft_sample_20.max_index = max_index;
-               bitmap_w = spectral_bitmap_weight(mag_info->all_bins);
-               fft_sample_20.bitmap_weight = bitmap_w;
-               fft_sample_20.max_exp = mag_info->max_exp & 0xf;
-
-               fft_sample_20.tsf = __cpu_to_be64(tsf);
-
-               tlv = (struct fft_sample_tlv *)&fft_sample_20;
-       }
-
-       ath_debug_send_fft_sample(sc, tlv);
-       return 1;
-#else
-       return 0;
-#endif
-}
-
 static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr)
 {
        struct ath_hw *ah = sc->sc_ah;
@@ -1148,7 +977,7 @@ static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr)
        if (ieee80211_is_beacon(hdr->frame_control)) {
                RX_STAT_INC(rx_beacons);
                if (!is_zero_ether_addr(common->curbssid) &&
-                   ether_addr_equal(hdr->addr3, common->curbssid))
+                   ether_addr_equal_64bits(hdr->addr3, common->curbssid))
                        return true;
        }
 
@@ -1243,9 +1072,13 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
        }
 
        rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr);
-       if (rx_stats->is_mybeacon) {
-               sc->hw_busy_count = 0;
-               ath_start_rx_poll(sc, 3);
+
+       /*
+        * This shouldn't happen, but have a safety check anyway.
+        */
+       if (WARN_ON(!ah->curchan)) {
+               ret = -EINVAL;
+               goto exit;
        }
 
        if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
@@ -1255,8 +1088,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
 
        ath9k_process_rssi(common, hw, rx_stats, rx_status);
 
-       rx_status->band = hw->conf.chandef.chan->band;
-       rx_status->freq = hw->conf.chandef.chan->center_freq;
+       rx_status->band = ah->curchan->chan->band;
+       rx_status->freq = ah->curchan->chan->center_freq;
        rx_status->antenna = rx_stats->rs_antenna;
        rx_status->flag |= RX_FLAG_MACTIME_END;
 
index 9ad007312c9d4fa53b5c9365c3950f3fbfbb7a86..b1fd3fa84983df0e0b85d86b86b02c158883fd35 100644 (file)
 #define AR_IMR_S2              0x00ac
 #define AR_IMR_S2_QCU_TXURN    0x000003FF
 #define AR_IMR_S2_QCU_TXURN_S  0
+#define AR_IMR_S2_BB_WATCHDOG  0x00010000
 #define AR_IMR_S2_CST          0x00400000
 #define AR_IMR_S2_GTT          0x00800000
 #define AR_IMR_S2_TIM          0x01000000
 #define AR_SREV_REVISION_9565_101       1
 #define AR_SREV_REVISION_9565_11        2
 #define AR_SREV_VERSION_9550           0x400
+#define AR_SREV_VERSION_9531            0x500
+#define AR_SREV_REVISION_9531_10        0
+#define AR_SREV_REVISION_9531_11        1
 
 #define AR_SREV_5416(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
 #define AR_SREV_9580(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
        ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10))
-
 #define AR_SREV_9580_10(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10))
 
+#define AR_SREV_9531(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531))
+#define AR_SREV_9531_10(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_10))
+#define AR_SREV_9531_11(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_11))
+
 /* NOTE: When adding chips newer than Peacock, add chip check here */
 #define AR_SREV_9580_10_OR_LATER(_ah) \
        (AR_SREV_9580(_ah))
diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c
new file mode 100644 (file)
index 0000000..99f4de9
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/relay.h>
+#include "ath9k.h"
+
+static s8 fix_rssi_inv_only(u8 rssi_val)
+{
+       if (rssi_val == 128)
+               rssi_val = 0;
+       return (s8) rssi_val;
+}
+
+static void ath_debug_send_fft_sample(struct ath_softc *sc,
+                                     struct fft_sample_tlv *fft_sample_tlv)
+{
+       int length;
+       if (!sc->rfs_chan_spec_scan)
+               return;
+
+       length = __be16_to_cpu(fft_sample_tlv->length) +
+                sizeof(*fft_sample_tlv);
+       relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
+}
+
+/* returns 1 if this was a spectral frame, even if not handled. */
+int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
+                   struct ath_rx_status *rs, u64 tsf)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       u8 num_bins, *bins, *vdata = (u8 *)hdr;
+       struct fft_sample_ht20 fft_sample_20;
+       struct fft_sample_ht20_40 fft_sample_40;
+       struct fft_sample_tlv *tlv;
+       struct ath_radar_info *radar_info;
+       int len = rs->rs_datalen;
+       int dc_pos;
+       u16 fft_len, length, freq = ah->curchan->chan->center_freq;
+       enum nl80211_channel_type chan_type;
+
+       /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
+        * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
+        * yet, but this is supposed to be possible as well.
+        */
+       if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
+           rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
+           rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
+               return 0;
+
+       /* check if spectral scan bit is set. This does not have to be checked
+        * if received through a SPECTRAL phy error, but shouldn't hurt.
+        */
+       radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
+       if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
+               return 0;
+
+       chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef);
+       if ((chan_type == NL80211_CHAN_HT40MINUS) ||
+           (chan_type == NL80211_CHAN_HT40PLUS)) {
+               fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN;
+               num_bins = SPECTRAL_HT20_40_NUM_BINS;
+               bins = (u8 *)fft_sample_40.data;
+       } else {
+               fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN;
+               num_bins = SPECTRAL_HT20_NUM_BINS;
+               bins = (u8 *)fft_sample_20.data;
+       }
+
+       /* Variation in the data length is possible and will be fixed later */
+       if ((len > fft_len + 2) || (len < fft_len - 1))
+               return 1;
+
+       switch (len - fft_len) {
+       case 0:
+               /* length correct, nothing to do. */
+               memcpy(bins, vdata, num_bins);
+               break;
+       case -1:
+               /* first byte missing, duplicate it. */
+               memcpy(&bins[1], vdata, num_bins - 1);
+               bins[0] = vdata[0];
+               break;
+       case 2:
+               /* MAC added 2 extra bytes at bin 30 and 32, remove them. */
+               memcpy(bins, vdata, 30);
+               bins[30] = vdata[31];
+               memcpy(&bins[31], &vdata[33], num_bins - 31);
+               break;
+       case 1:
+               /* MAC added 2 extra bytes AND first byte is missing. */
+               bins[0] = vdata[0];
+               memcpy(&bins[1], vdata, 30);
+               bins[31] = vdata[31];
+               memcpy(&bins[32], &vdata[33], num_bins - 32);
+               break;
+       default:
+               return 1;
+       }
+
+       /* DC value (value in the middle) is the blind spot of the spectral
+        * sample and invalid, interpolate it.
+        */
+       dc_pos = num_bins / 2;
+       bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2;
+
+       if ((chan_type == NL80211_CHAN_HT40MINUS) ||
+           (chan_type == NL80211_CHAN_HT40PLUS)) {
+               s8 lower_rssi, upper_rssi;
+               s16 ext_nf;
+               u8 lower_max_index, upper_max_index;
+               u8 lower_bitmap_w, upper_bitmap_w;
+               u16 lower_mag, upper_mag;
+               struct ath9k_hw_cal_data *caldata = ah->caldata;
+               struct ath_ht20_40_mag_info *mag_info;
+
+               if (caldata)
+                       ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan,
+                                       caldata->nfCalHist[3].privNF);
+               else
+                       ext_nf = ATH_DEFAULT_NOISE_FLOOR;
+
+               length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv);
+               fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40;
+               fft_sample_40.tlv.length = __cpu_to_be16(length);
+               fft_sample_40.freq = __cpu_to_be16(freq);
+               fft_sample_40.channel_type = chan_type;
+
+               if (chan_type == NL80211_CHAN_HT40PLUS) {
+                       lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
+                       upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
+
+                       fft_sample_40.lower_noise = ah->noise;
+                       fft_sample_40.upper_noise = ext_nf;
+               } else {
+                       lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
+                       upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
+
+                       fft_sample_40.lower_noise = ext_nf;
+                       fft_sample_40.upper_noise = ah->noise;
+               }
+               fft_sample_40.lower_rssi = lower_rssi;
+               fft_sample_40.upper_rssi = upper_rssi;
+
+               mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1;
+               lower_mag = spectral_max_magnitude(mag_info->lower_bins);
+               upper_mag = spectral_max_magnitude(mag_info->upper_bins);
+               fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag);
+               fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag);
+               lower_max_index = spectral_max_index(mag_info->lower_bins);
+               upper_max_index = spectral_max_index(mag_info->upper_bins);
+               fft_sample_40.lower_max_index = lower_max_index;
+               fft_sample_40.upper_max_index = upper_max_index;
+               lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins);
+               upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins);
+               fft_sample_40.lower_bitmap_weight = lower_bitmap_w;
+               fft_sample_40.upper_bitmap_weight = upper_bitmap_w;
+               fft_sample_40.max_exp = mag_info->max_exp & 0xf;
+
+               fft_sample_40.tsf = __cpu_to_be64(tsf);
+
+               tlv = (struct fft_sample_tlv *)&fft_sample_40;
+       } else {
+               u8 max_index, bitmap_w;
+               u16 magnitude;
+               struct ath_ht20_mag_info *mag_info;
+
+               length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv);
+               fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20;
+               fft_sample_20.tlv.length = __cpu_to_be16(length);
+               fft_sample_20.freq = __cpu_to_be16(freq);
+
+               fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
+               fft_sample_20.noise = ah->noise;
+
+               mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
+               magnitude = spectral_max_magnitude(mag_info->all_bins);
+               fft_sample_20.max_magnitude = __cpu_to_be16(magnitude);
+               max_index = spectral_max_index(mag_info->all_bins);
+               fft_sample_20.max_index = max_index;
+               bitmap_w = spectral_bitmap_weight(mag_info->all_bins);
+               fft_sample_20.bitmap_weight = bitmap_w;
+               fft_sample_20.max_exp = mag_info->max_exp & 0xf;
+
+               fft_sample_20.tsf = __cpu_to_be64(tsf);
+
+               tlv = (struct fft_sample_tlv *)&fft_sample_20;
+       }
+
+       ath_debug_send_fft_sample(sc, tlv);
+
+       return 1;
+}
+
+/*********************/
+/* spectral_scan_ctl */
+/*********************/
+
+static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
+                                      size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char *mode = "";
+       unsigned int len;
+
+       switch (sc->spectral_mode) {
+       case SPECTRAL_DISABLED:
+               mode = "disable";
+               break;
+       case SPECTRAL_BACKGROUND:
+               mode = "background";
+               break;
+       case SPECTRAL_CHANSCAN:
+               mode = "chanscan";
+               break;
+       case SPECTRAL_MANUAL:
+               mode = "manual";
+               break;
+       }
+       len = strlen(mode);
+       return simple_read_from_buffer(user_buf, count, ppos, mode, len);
+}
+
+static ssize_t write_file_spec_scan_ctl(struct file *file,
+                                       const char __user *user_buf,
+                                       size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       char buf[32];
+       ssize_t len;
+
+       if (config_enabled(CONFIG_ATH9K_TX99))
+               return -EOPNOTSUPP;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+
+       if (strncmp("trigger", buf, 7) == 0) {
+               ath9k_spectral_scan_trigger(sc->hw);
+       } else if (strncmp("background", buf, 9) == 0) {
+               ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
+               ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
+       } else if (strncmp("chanscan", buf, 8) == 0) {
+               ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN);
+               ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n");
+       } else if (strncmp("manual", buf, 6) == 0) {
+               ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL);
+               ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n");
+       } else if (strncmp("disable", buf, 7) == 0) {
+               ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED);
+               ath_dbg(common, CONFIG, "spectral scan: disabled\n");
+       } else {
+               return -EINVAL;
+       }
+
+       return count;
+}
+
+static const struct file_operations fops_spec_scan_ctl = {
+       .read = read_file_spec_scan_ctl,
+       .write = write_file_spec_scan_ctl,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+/*************************/
+/* spectral_short_repeat */
+/*************************/
+
+static ssize_t read_file_spectral_short_repeat(struct file *file,
+                                              char __user *user_buf,
+                                              size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_short_repeat(struct file *file,
+                                               const char __user *user_buf,
+                                               size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       unsigned long val;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (kstrtoul(buf, 0, &val))
+               return -EINVAL;
+
+       if (val < 0 || val > 1)
+               return -EINVAL;
+
+       sc->spec_config.short_repeat = val;
+       return count;
+}
+
+static const struct file_operations fops_spectral_short_repeat = {
+       .read = read_file_spectral_short_repeat,
+       .write = write_file_spectral_short_repeat,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+/******************/
+/* spectral_count */
+/******************/
+
+static ssize_t read_file_spectral_count(struct file *file,
+                                       char __user *user_buf,
+                                       size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "%d\n", sc->spec_config.count);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_count(struct file *file,
+                                        const char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       unsigned long val;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (kstrtoul(buf, 0, &val))
+               return -EINVAL;
+
+       if (val < 0 || val > 255)
+               return -EINVAL;
+
+       sc->spec_config.count = val;
+       return count;
+}
+
+static const struct file_operations fops_spectral_count = {
+       .read = read_file_spectral_count,
+       .write = write_file_spectral_count,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+/*******************/
+/* spectral_period */
+/*******************/
+
+static ssize_t read_file_spectral_period(struct file *file,
+                                        char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "%d\n", sc->spec_config.period);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_period(struct file *file,
+                                         const char __user *user_buf,
+                                         size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       unsigned long val;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (kstrtoul(buf, 0, &val))
+               return -EINVAL;
+
+       if (val < 0 || val > 255)
+               return -EINVAL;
+
+       sc->spec_config.period = val;
+       return count;
+}
+
+static const struct file_operations fops_spectral_period = {
+       .read = read_file_spectral_period,
+       .write = write_file_spectral_period,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+/***********************/
+/* spectral_fft_period */
+/***********************/
+
+static ssize_t read_file_spectral_fft_period(struct file *file,
+                                            char __user *user_buf,
+                                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_fft_period(struct file *file,
+                                             const char __user *user_buf,
+                                             size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       unsigned long val;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (kstrtoul(buf, 0, &val))
+               return -EINVAL;
+
+       if (val < 0 || val > 15)
+               return -EINVAL;
+
+       sc->spec_config.fft_period = val;
+       return count;
+}
+
+static const struct file_operations fops_spectral_fft_period = {
+       .read = read_file_spectral_fft_period,
+       .write = write_file_spectral_fft_period,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+/*******************/
+/* Relay interface */
+/*******************/
+
+static struct dentry *create_buf_file_handler(const char *filename,
+                                             struct dentry *parent,
+                                             umode_t mode,
+                                             struct rchan_buf *buf,
+                                             int *is_global)
+{
+       struct dentry *buf_file;
+
+       buf_file = debugfs_create_file(filename, mode, parent, buf,
+                                      &relay_file_operations);
+       *is_global = 1;
+       return buf_file;
+}
+
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+       debugfs_remove(dentry);
+
+       return 0;
+}
+
+static struct rchan_callbacks rfs_spec_scan_cb = {
+       .create_buf_file = create_buf_file_handler,
+       .remove_buf_file = remove_buf_file_handler,
+};
+
+/*********************/
+/* Debug Init/Deinit */
+/*********************/
+
+void ath9k_spectral_deinit_debug(struct ath_softc *sc)
+{
+       if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
+               relay_close(sc->rfs_chan_spec_scan);
+               sc->rfs_chan_spec_scan = NULL;
+       }
+}
+
+void ath9k_spectral_init_debug(struct ath_softc *sc)
+{
+       sc->rfs_chan_spec_scan = relay_open("spectral_scan",
+                                           sc->debug.debugfs_phy,
+                                           1024, 256, &rfs_spec_scan_cb,
+                                           NULL);
+       debugfs_create_file("spectral_scan_ctl",
+                           S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc,
+                           &fops_spec_scan_ctl);
+       debugfs_create_file("spectral_short_repeat",
+                           S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc,
+                           &fops_spectral_short_repeat);
+       debugfs_create_file("spectral_count",
+                           S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc,
+                           &fops_spectral_count);
+       debugfs_create_file("spectral_period",
+                           S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc,
+                           &fops_spectral_period);
+       debugfs_create_file("spectral_fft_period",
+                           S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc,
+                           &fops_spectral_fft_period);
+}
diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h
new file mode 100644 (file)
index 0000000..ead6341
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_H
+#define SPECTRAL_H
+
+/* enum spectral_mode:
+ *
+ * @SPECTRAL_DISABLED: spectral mode is disabled
+ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
+ *     something else.
+ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
+ *     is performed manually.
+ * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels
+ *     during a channel scan.
+ */
+enum spectral_mode {
+       SPECTRAL_DISABLED = 0,
+       SPECTRAL_BACKGROUND,
+       SPECTRAL_MANUAL,
+       SPECTRAL_CHANSCAN,
+};
+
+#define SPECTRAL_SCAN_BITMASK          0x10
+/* Radar info packet format, used for DFS and spectral formats. */
+struct ath_radar_info {
+       u8 pulse_length_pri;
+       u8 pulse_length_ext;
+       u8 pulse_bw_info;
+} __packed;
+
+/* The HT20 spectral data has 4 bytes of additional information at it's end.
+ *
+ * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]}
+ * [7:0]: all bins  max_magnitude[9:2]
+ * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]}
+ * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
+ */
+struct ath_ht20_mag_info {
+       u8 all_bins[3];
+       u8 max_exp;
+} __packed;
+
+#define SPECTRAL_HT20_NUM_BINS         56
+
+/* WARNING: don't actually use this struct! MAC may vary the amount of
+ * data by -1/+2. This struct is for reference only.
+ */
+struct ath_ht20_fft_packet {
+       u8 data[SPECTRAL_HT20_NUM_BINS];
+       struct ath_ht20_mag_info mag_info;
+       struct ath_radar_info radar_info;
+} __packed;
+
+#define SPECTRAL_HT20_TOTAL_DATA_LEN   (sizeof(struct ath_ht20_fft_packet))
+
+/* Dynamic 20/40 mode:
+ *
+ * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]}
+ * [7:0]: lower bins  max_magnitude[9:2]
+ * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]}
+ * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]}
+ * [7:0]: upper bins  max_magnitude[9:2]
+ * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]}
+ * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
+ */
+struct ath_ht20_40_mag_info {
+       u8 lower_bins[3];
+       u8 upper_bins[3];
+       u8 max_exp;
+} __packed;
+
+#define SPECTRAL_HT20_40_NUM_BINS              128
+
+/* WARNING: don't actually use this struct! MAC may vary the amount of
+ * data. This struct is for reference only.
+ */
+struct ath_ht20_40_fft_packet {
+       u8 data[SPECTRAL_HT20_40_NUM_BINS];
+       struct ath_ht20_40_mag_info mag_info;
+       struct ath_radar_info radar_info;
+} __packed;
+
+
+#define SPECTRAL_HT20_40_TOTAL_DATA_LEN        (sizeof(struct ath_ht20_40_fft_packet))
+
+/* grabs the max magnitude from the all/upper/lower bins */
+static inline u16 spectral_max_magnitude(u8 *bins)
+{
+       return (bins[0] & 0xc0) >> 6 |
+              (bins[1] & 0xff) << 2 |
+              (bins[2] & 0x03) << 10;
+}
+
+/* return the max magnitude from the all/upper/lower bins */
+static inline u8 spectral_max_index(u8 *bins)
+{
+       s8 m = (bins[2] & 0xfc) >> 2;
+
+       /* TODO: this still doesn't always report the right values ... */
+       if (m > 32)
+               m |= 0xe0;
+       else
+               m &= ~0xe0;
+
+       return m + 29;
+}
+
+/* return the bitmap weight from the all/upper/lower bins */
+static inline u8 spectral_bitmap_weight(u8 *bins)
+{
+       return bins[0] & 0x3f;
+}
+
+/* FFT sample format given to userspace via debugfs.
+ *
+ * Please keep the type/length at the front position and change
+ * other fields after adding another sample type
+ *
+ * TODO: this might need rework when switching to nl80211-based
+ * interface.
+ */
+enum ath_fft_sample_type {
+       ATH_FFT_SAMPLE_HT20 = 1,
+       ATH_FFT_SAMPLE_HT20_40,
+};
+
+struct fft_sample_tlv {
+       u8 type;        /* see ath_fft_sample */
+       __be16 length;
+       /* type dependent data follows */
+} __packed;
+
+struct fft_sample_ht20 {
+       struct fft_sample_tlv tlv;
+
+       u8 max_exp;
+
+       __be16 freq;
+       s8 rssi;
+       s8 noise;
+
+       __be16 max_magnitude;
+       u8 max_index;
+       u8 bitmap_weight;
+
+       __be64 tsf;
+
+       u8 data[SPECTRAL_HT20_NUM_BINS];
+} __packed;
+
+struct fft_sample_ht20_40 {
+       struct fft_sample_tlv tlv;
+
+       u8 channel_type;
+       __be16 freq;
+
+       s8 lower_rssi;
+       s8 upper_rssi;
+
+       __be64 tsf;
+
+       s8 lower_noise;
+       s8 upper_noise;
+
+       __be16 lower_max_magnitude;
+       __be16 upper_max_magnitude;
+
+       u8 lower_max_index;
+       u8 upper_max_index;
+
+       u8 lower_bitmap_weight;
+       u8 upper_bitmap_weight;
+
+       u8 max_exp;
+
+       u8 data[SPECTRAL_HT20_40_NUM_BINS];
+} __packed;
+
+void ath9k_spectral_init_debug(struct ath_softc *sc);
+void ath9k_spectral_deinit_debug(struct ath_softc *sc);
+
+void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw);
+int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
+                              enum spectral_mode spectral_mode);
+
+#ifdef CONFIG_ATH9K_DEBUGFS
+int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
+                   struct ath_rx_status *rs, u64 tsf);
+#else
+static inline int ath_process_fft(struct ath_softc *sc,
+                                 struct ieee80211_hdr *hdr,
+                                 struct ath_rx_status *rs, u64 tsf)
+{
+       return 0;
+}
+#endif /* CONFIG_ATH9K_DEBUGFS */
+
+#endif /* SPECTRAL_H */
index f1cde81bb7a2573f1905c2725c29c176da7013f0..1b3230fa36510916c740bbc62a2a1b6ec202f5a0 100644 (file)
@@ -197,7 +197,6 @@ int ath9k_suspend(struct ieee80211_hw *hw,
 
        ath_cancel_work(sc);
        ath_stop_ani(sc);
-       del_timer_sync(&sc->rx_poll_timer);
 
        if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {
                ath_dbg(common, ANY, "Device not present\n");
index a907bc94800d323090a7e4d401d6ba4dab9a8835..e8d0e7fc77dae5ecfe650276aa2cda1c759ed8d9 100644 (file)
@@ -174,14 +174,7 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
 static struct ath_atx_tid *
 ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb)
 {
-       struct ieee80211_hdr *hdr;
-       u8 tidno = 0;
-
-       hdr = (struct ieee80211_hdr *) skb->data;
-       if (ieee80211_is_data_qos(hdr->frame_control))
-               tidno = ieee80211_get_qos_ctl(hdr)[0];
-
-       tidno &= IEEE80211_QOS_CTL_TID_MASK;
+       u8 tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
        return ATH_AN_2_TID(an, tidno);
 }
 
@@ -781,11 +774,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
        if (bt_aggr_limit)
                aggr_limit = bt_aggr_limit;
 
-       /*
-        * h/w can accept aggregates up to 16 bit lengths (65535).
-        * The IE, however can hold up to 65536, which shows up here
-        * as zero. Ignore 65536 since we  are constrained by hw.
-        */
        if (tid->an->maxampdu)
                aggr_limit = min(aggr_limit, tid->an->maxampdu);
 
@@ -1410,8 +1398,8 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
         * has already been added.
         */
        if (sta->ht_cap.ht_supported) {
-               an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
-                                    sta->ht_cap.ampdu_factor);
+               an->maxampdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+                                     sta->ht_cap.ampdu_factor)) - 1;
                density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
                an->mpdudensity = density;
        }
index 3d70cd277fd73745b96eeb0fe2042eb9789b68f4..1c0af9cd9a85e3fa88b1f5f79c4e1042a0e0c920 100644 (file)
@@ -37,7 +37,6 @@
  *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/seq_file.h>
index 349fa22a921adc48183bffcc24befb3741f1f392..4c3f576c3144befb6173e9ad9bd5b8487db6dc32 100644 (file)
@@ -37,7 +37,6 @@
  *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
index e935f61c7fad1b8ea60cfbaad45affe081611222..1b1b20751ead35ae71aad63240d3f76836ff0a31 100644 (file)
@@ -37,7 +37,6 @@
  *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
@@ -536,7 +535,7 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
                return;
 
        /* and only beacons from the associated BSSID, please */
-       if (!ether_addr_equal(hdr->addr3, ar->common.curbssid) ||
+       if (!ether_addr_equal_64bits(hdr->addr3, ar->common.curbssid) ||
            !ar->common.curaid)
                return;
 
@@ -602,8 +601,8 @@ static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len)
 
                if (bar->start_seq_num == entry_bar->start_seq_num &&
                    TID_CHECK(bar->control, entry_bar->control) &&
-                   ether_addr_equal(bar->ra, entry_bar->ta) &&
-                   ether_addr_equal(bar->ta, entry_bar->ra)) {
+                   ether_addr_equal_64bits(bar->ra, entry_bar->ta) &&
+                   ether_addr_equal_64bits(bar->ta, entry_bar->ra)) {
                        struct ieee80211_tx_info *tx_info;
 
                        tx_info = IEEE80211_SKB_CB(entry_skb);
index e3f696ee4d2393b00cbebd38d7f2840c51376149..4cadfd48ffdf8bd19f0206c138337f2e58177622 100644 (file)
@@ -37,7 +37,6 @@
  *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
index 8f37562e0b113d6e5d4b13e50ea87cba679c6628..750626b0e22d528d6d76fbe4ad402a2c175316be 100644 (file)
@@ -2060,22 +2060,28 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
        case WCN36XX_HAL_OTA_TX_COMPL_IND:
        case WCN36XX_HAL_MISSED_BEACON_IND:
        case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
-               mutex_lock(&wcn->hal_ind_mutex);
                msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
-               if (msg_ind) {
-                       msg_ind->msg_len = len;
-                       msg_ind->msg = kmalloc(len, GFP_KERNEL);
-                       memcpy(msg_ind->msg, buf, len);
-                       list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
-                       queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
-                       wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
+               if (!msg_ind)
+                       goto nomem;
+               msg_ind->msg_len = len;
+               msg_ind->msg = kmalloc(len, GFP_KERNEL);
+               if (!msg_ind->msg) {
+                       kfree(msg_ind);
+nomem:
+                       /*
+                        * FIXME: Do something smarter then just
+                        * printing an error.
+                        */
+                       wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
+                                   msg_header->msg_type);
+                       break;
                }
+               memcpy(msg_ind->msg, buf, len);
+               mutex_lock(&wcn->hal_ind_mutex);
+               list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
+               queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
                mutex_unlock(&wcn->hal_ind_mutex);
-               if (msg_ind)
-                       break;
-               /* FIXME: Do something smarter then just printing an error. */
-               wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
-                           msg_header->msg_type);
+               wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
                break;
        default:
                wcn36xx_err("SMD_EVENT (%d) not supported\n",
index 8205d3e4ab66613134ca4b6dff022a9995eb0e24..10919f95a83c19cd744003a2a49022ecda3b2a8c 100644 (file)
@@ -156,6 +156,19 @@ void wil6210_enable_irq(struct wil6210_priv *wil)
        iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
                  offsetof(struct RGF_ICR, ICC));
 
+       /* interrupt moderation parameters */
+       if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+               /* disable interrupt moderation for monitor
+                * to get better timestamp precision
+                */
+               iowrite32(0, wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL));
+       } else {
+               iowrite32(WIL6210_ITR_TRSH,
+                         wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
+               iowrite32(BIT_DMA_ITR_CNT_CRL_EN,
+                         wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL));
+       }
+
        wil6210_unmask_irq_pseudo(wil);
        wil6210_unmask_irq_tx(wil);
        wil6210_unmask_irq_rx(wil);
index d505b2676a736381366652e6815891286e6fe319..9b88440ef05b10bd613cf27e5bb0ccf76e4fc2b4 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <net/ipv6.h>
+#include <asm/processor.h>
 
 #include "wil6210.h"
 #include "wmi.h"
@@ -377,6 +378,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
        }
        skb_trim(skb, dmalen);
 
+       prefetch(skb->data);
+
        wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
                          skb->data, skb_headlen(skb), false);
 
@@ -673,9 +676,12 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil,
        if (skb->ip_summed != CHECKSUM_PARTIAL)
                return 0;
 
+       d->dma.b11 = ETH_HLEN; /* MAC header length */
+
        switch (skb->protocol) {
        case cpu_to_be16(ETH_P_IP):
                protocol = ip_hdr(skb)->protocol;
+               d->dma.b11 |= BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS);
                break;
        case cpu_to_be16(ETH_P_IPV6):
                protocol = ipv6_hdr(skb)->nexthdr;
@@ -701,8 +707,6 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil,
        }
 
        d->dma.ip_length = skb_network_header_len(skb);
-       d->dma.b11 = ETH_HLEN; /* MAC header length */
-       d->dma.b11 |= BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS);
        /* Enable TCP/UDP checksum */
        d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS);
        /* Calculate pseudo-header */
index c4a51638736a27ab4a41ffe1e3e5026400e4e249..1f91eaf95bbebd0dfd70d316943558c5882ed54d 100644 (file)
@@ -39,6 +39,7 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
 #define WIL6210_MAX_TX_RINGS   (24) /* HW limit */
 #define WIL6210_MAX_CID                (8) /* HW limit */
 #define WIL6210_NAPI_BUDGET    (16) /* arbitrary */
+#define WIL6210_ITR_TRSH       (10000) /* arbitrary - about 15 IRQs/msec */
 
 /* Hardware definitions begin */
 
index b73b7e3e21961315b61b2515edd8a85bbd323698..bf93ea859f2d7f1fc05257a86a0b5b1525dd62c3 100644 (file)
@@ -39,7 +39,6 @@
 
 ******************************************************************************/
 
-#include <linux/init.h>
 #include <linux/interrupt.h>
 
 #include <linux/kernel.h>
index 5e2749dd112420562a4efde6ca3717de5cc16446..4cfb4d99ced0c3ceb22c05814008d5d21250ef04 100644 (file)
@@ -32,7 +32,6 @@
 #ifdef __IN_PCMCIA_PACKAGE__
 #include <pcmcia/k_compat.h>
 #endif
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/ptrace.h>
index 64d5973ec28b1c1ca62d7611bf03169eec45f4cf..5cd97e3cbee36d83a24ad0d15ae490db38718fcc 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/netdevice.h>
 #include "atmel.h"
 
index 2082402d4b6364e03424f4ef00161b0fae9c298b..5681b9862023ee360bebc502be6facd22535884e 100644 (file)
@@ -36,7 +36,6 @@ brcmfmac-objs += \
 brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
                dhd_sdio.o \
                bcmsdh.o \
-               bcmsdh_sdmmc.o \
                sdio_chip.o
 brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
                usb.o
index 06848e426f9adf408f4795e09f28a7d2a31946ea..c229210d50badeb3b146320822d03057a98c28ce 100644 (file)
@@ -41,9 +41,6 @@ struct brcmf_proto_bcdc_dcmd {
        __le32 status;  /* status code returned from the device */
 };
 
-/* Max valid buffer size that can be sent to the dongle */
-#define BCDC_MAX_MSG_SIZE      (ETH_FRAME_LEN+ETH_FCS_LEN)
-
 /* BCDC flag definitions */
 #define BCDC_DCMD_ERROR                0x01            /* 1=cmd failed */
 #define BCDC_DCMD_SET          0x02            /* 0=get, 1=set cmd */
@@ -101,32 +98,41 @@ struct brcmf_proto_bcdc_header {
                                         * plus any space that might be needed
                                         * for bus alignment padding.
                                         */
-#define ROUND_UP_MARGIN        2048    /* Biggest bus block size possible for
-                                * round off at the end of buffer
-                                * Currently is SDIO
-                                */
-
 struct brcmf_bcdc {
        u16 reqid;
        u8 bus_header[BUS_HEADER_LEN];
        struct brcmf_proto_bcdc_dcmd msg;
-       unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN];
+       unsigned char buf[BRCMF_DCMD_MAXLEN];
 };
 
-static int brcmf_proto_bcdc_msg(struct brcmf_pub *drvr)
+
+static int
+brcmf_proto_bcdc_msg(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
+                    uint len, bool set)
 {
        struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
-       int len = le32_to_cpu(bcdc->msg.len) +
-                       sizeof(struct brcmf_proto_bcdc_dcmd);
+       struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
+       u32 flags;
 
        brcmf_dbg(BCDC, "Enter\n");
 
-       /* NOTE : bcdc->msg.len holds the desired length of the buffer to be
-        *        returned. Only up to BCDC_MAX_MSG_SIZE of this buffer area
-        *        is actually sent to the dongle
-        */
-       if (len > BCDC_MAX_MSG_SIZE)
-               len = BCDC_MAX_MSG_SIZE;
+       memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
+
+       msg->cmd = cpu_to_le32(cmd);
+       msg->len = cpu_to_le32(len);
+       flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT);
+       if (set)
+               flags |= BCDC_DCMD_SET;
+       flags = (flags & ~BCDC_DCMD_IF_MASK) |
+               (ifidx << BCDC_DCMD_IF_SHIFT);
+       msg->flags = cpu_to_le32(flags);
+
+       if (buf)
+               memcpy(bcdc->buf, buf, len);
+
+       len += sizeof(*msg);
+       if (len > BRCMF_TX_IOCTL_MAX_MSG_SIZE)
+               len = BRCMF_TX_IOCTL_MAX_MSG_SIZE;
 
        /* Send request */
        return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len);
@@ -161,19 +167,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
 
        brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
 
-       memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
-
-       msg->cmd = cpu_to_le32(cmd);
-       msg->len = cpu_to_le32(len);
-       flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT);
-       flags = (flags & ~BCDC_DCMD_IF_MASK) |
-               (ifidx << BCDC_DCMD_IF_SHIFT);
-       msg->flags = cpu_to_le32(flags);
-
-       if (buf)
-               memcpy(bcdc->buf, buf, len);
-
-       ret = brcmf_proto_bcdc_msg(drvr);
+       ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
        if (ret < 0) {
                brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
                          ret);
@@ -227,19 +221,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
 
        brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
 
-       memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
-
-       msg->cmd = cpu_to_le32(cmd);
-       msg->len = cpu_to_le32(len);
-       flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT) | BCDC_DCMD_SET;
-       flags = (flags & ~BCDC_DCMD_IF_MASK) |
-               (ifidx << BCDC_DCMD_IF_SHIFT);
-       msg->flags = cpu_to_le32(flags);
-
-       if (buf)
-               memcpy(bcdc->buf, buf, len);
-
-       ret = brcmf_proto_bcdc_msg(drvr);
+       ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true);
        if (ret < 0)
                goto done;
 
@@ -347,6 +329,15 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
        return 0;
 }
 
+static int
+brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
+                       struct sk_buff *pktbuf)
+{
+       brcmf_proto_bcdc_hdrpush(drvr, ifidx, offset, pktbuf);
+       return brcmf_bus_txdata(drvr->bus_if, pktbuf);
+}
+
+
 int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
 {
        struct brcmf_bcdc *bcdc;
@@ -361,15 +352,15 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
                goto fail;
        }
 
-       drvr->proto->hdrpush = brcmf_proto_bcdc_hdrpush;
        drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
        drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
        drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
+       drvr->proto->txdata = brcmf_proto_bcdc_txdata;
        drvr->proto->pd = bcdc;
 
        drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
        drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
-                       sizeof(struct brcmf_proto_bcdc_dcmd) + ROUND_UP_MARGIN;
+                       sizeof(struct brcmf_proto_bcdc_dcmd);
        return 0;
 
 fail:
index 91651ec7f13fedddaa7c18cce14c7654eb77404e..34c993dd0602f161b7366478d3a972809b413c9a 100644 (file)
 #include <linux/completion.h>
 #include <linux/scatterlist.h>
 #include <linux/mmc/sdio.h>
+#include <linux/mmc/core.h>
 #include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
 #include <linux/platform_data/brcmfmac-sdio.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <net/cfg80211.h>
 
 #include <defs.h>
 #include <brcm_hw_ids.h>
 #include "dhd_bus.h"
 #include "dhd_dbg.h"
 #include "sdio_host.h"
+#include "sdio_chip.h"
 
 #define SDIOH_API_ACCESS_RETRY_LIMIT   2
 
+#define DMA_ALIGN_MASK 0x03
 
-static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id)
+#define SDIO_FUNC1_BLOCKSIZE           64
+#define SDIO_FUNC2_BLOCKSIZE           512
+/* Maximum milliseconds to wait for F2 to come up */
+#define SDIO_WAIT_F2RDY        3000
+
+
+static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id)
 {
        struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
        struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
@@ -54,27 +70,46 @@ static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id)
                sdiodev->irq_en = false;
        }
 
-       brcmf_sdbrcm_isr(sdiodev->bus);
+       brcmf_sdio_isr(sdiodev->bus);
 
        return IRQ_HANDLED;
 }
 
-static void brcmf_sdio_ib_irqhandler(struct sdio_func *func)
+static void brcmf_sdiod_ib_irqhandler(struct sdio_func *func)
 {
        struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
        struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 
        brcmf_dbg(INTR, "IB intr triggered\n");
 
-       brcmf_sdbrcm_isr(sdiodev->bus);
+       brcmf_sdio_isr(sdiodev->bus);
 }
 
 /* dummy handler for SDIO function 2 interrupt */
-static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
+static void brcmf_sdiod_dummy_irqhandler(struct sdio_func *func)
+{
+}
+
+static bool brcmf_sdiod_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
+{
+       bool is_err = false;
+#ifdef CONFIG_PM_SLEEP
+       is_err = atomic_read(&sdiodev->suspend);
+#endif
+       return is_err;
+}
+
+static void brcmf_sdiod_pm_resume_wait(struct brcmf_sdio_dev *sdiodev,
+                                      wait_queue_head_t *wq)
 {
+#ifdef CONFIG_PM_SLEEP
+       int retry = 0;
+       while (atomic_read(&sdiodev->suspend) && retry++ != 30)
+               wait_event_timeout(*wq, false, HZ/100);
+#endif
 }
 
-int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
+int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
 {
        int ret = 0;
        u8 data;
@@ -84,7 +119,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
                brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
                          sdiodev->pdata->oob_irq_nr);
                ret = request_irq(sdiodev->pdata->oob_irq_nr,
-                                 brcmf_sdio_oob_irqhandler,
+                                 brcmf_sdiod_oob_irqhandler,
                                  sdiodev->pdata->oob_irq_flags,
                                  "brcmf_oob_intr",
                                  &sdiodev->func[1]->dev);
@@ -108,36 +143,36 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
                sdio_claim_host(sdiodev->func[1]);
 
                /* must configure SDIO_CCCR_IENx to enable irq */
-               data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
+               data = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
                data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
-               brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
+               brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
 
                /* redirect, configure and enable io for interrupt signal */
                data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
                if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
                        data |= SDIO_SEPINT_ACT_HI;
-               brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
+               brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
 
                sdio_release_host(sdiodev->func[1]);
        } else {
                brcmf_dbg(SDIO, "Entering\n");
                sdio_claim_host(sdiodev->func[1]);
-               sdio_claim_irq(sdiodev->func[1], brcmf_sdio_ib_irqhandler);
-               sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
+               sdio_claim_irq(sdiodev->func[1], brcmf_sdiod_ib_irqhandler);
+               sdio_claim_irq(sdiodev->func[2], brcmf_sdiod_dummy_irqhandler);
                sdio_release_host(sdiodev->func[1]);
        }
 
        return 0;
 }
 
-int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
+int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev)
 {
        brcmf_dbg(SDIO, "Entering\n");
 
        if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
                sdio_claim_host(sdiodev->func[1]);
-               brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
-               brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+               brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
+               brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
                sdio_release_host(sdiodev->func[1]);
 
                if (sdiodev->oob_irq_requested) {
@@ -160,29 +195,141 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
        return 0;
 }
 
+static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func,
+                                       uint regaddr, u8 byte)
+{
+       int err_ret;
+
+       /*
+        * Can only directly write to some F0 registers.
+        * Handle CCCR_IENx and CCCR_ABORT command
+        * as a special case.
+        */
+       if ((regaddr == SDIO_CCCR_ABORT) ||
+           (regaddr == SDIO_CCCR_IENx))
+               sdio_writeb(func, byte, regaddr, &err_ret);
+       else
+               sdio_f0_writeb(func, byte, regaddr, &err_ret);
+
+       return err_ret;
+}
+
+static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn,
+                                   u32 addr, u8 regsz, void *data, bool write)
+{
+       struct sdio_func *func;
+       int ret;
+
+       brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
+                 write, fn, addr, regsz);
+
+       brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
+       if (brcmf_sdiod_pm_resume_error(sdiodev))
+               return -EIO;
+
+       /* only allow byte access on F0 */
+       if (WARN_ON(regsz > 1 && !fn))
+               return -EINVAL;
+       func = sdiodev->func[fn];
+
+       switch (regsz) {
+       case sizeof(u8):
+               if (write) {
+                       if (fn)
+                               sdio_writeb(func, *(u8 *)data, addr, &ret);
+                       else
+                               ret = brcmf_sdiod_f0_writeb(func, addr,
+                                                           *(u8 *)data);
+               } else {
+                       if (fn)
+                               *(u8 *)data = sdio_readb(func, addr, &ret);
+                       else
+                               *(u8 *)data = sdio_f0_readb(func, addr, &ret);
+               }
+               break;
+       case sizeof(u16):
+               if (write)
+                       sdio_writew(func, *(u16 *)data, addr, &ret);
+               else
+                       *(u16 *)data = sdio_readw(func, addr, &ret);
+               break;
+       case sizeof(u32):
+               if (write)
+                       sdio_writel(func, *(u32 *)data, addr, &ret);
+               else
+                       *(u32 *)data = sdio_readl(func, addr, &ret);
+               break;
+       default:
+               brcmf_err("invalid size: %d\n", regsz);
+               break;
+       }
+
+       if (ret) {
+               /*
+                * SleepCSR register access can fail when
+                * waking up the device so reduce this noise
+                * in the logs.
+                */
+               if (addr != SBSDIO_FUNC1_SLEEPCSR)
+                       brcmf_err("failed to %s data F%d@0x%05x, err: %d\n",
+                                 write ? "write" : "read", fn, addr, ret);
+               else
+                       brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
+                                 write ? "write" : "read", fn, addr, ret);
+       }
+       return ret;
+}
+
+static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
+                                  u8 regsz, void *data, bool write)
+{
+       u8 func_num;
+       s32 retry = 0;
+       int ret;
+
+       /*
+        * figure out how to read the register based on address range
+        * 0x00 ~ 0x7FF: function 0 CCCR and FBR
+        * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
+        * The rest: function 1 silicon backplane core registers
+        */
+       if ((addr & ~REG_F0_REG_MASK) == 0)
+               func_num = SDIO_FUNC_0;
+       else
+               func_num = SDIO_FUNC_1;
+
+       do {
+               if (!write)
+                       memset(data, 0, regsz);
+               /* for retry wait for 1 ms till bus get settled down */
+               if (retry)
+                       usleep_range(1000, 2000);
+               ret = brcmf_sdiod_request_data(sdiodev, func_num, addr, regsz,
+                                              data, write);
+       } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
+
+       if (ret != 0)
+               brcmf_err("failed with %d\n", ret);
+
+       return ret;
+}
+
 static int
-brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
+brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
 {
        int err = 0, i;
        u8 addr[3];
-       s32 retry;
 
        addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
        addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK;
        addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
 
        for (i = 0; i < 3; i++) {
-               retry = 0;
-               do {
-                       if (retry)
-                               usleep_range(1000, 2000);
-                       err = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE,
-                                       SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW + i,
-                                       &addr[i]);
-               } while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
-
+               err = brcmf_sdiod_regrw_helper(sdiodev,
+                                              SBSDIO_FUNC1_SBADDRLOW + i,
+                                              sizeof(u8), &addr[i], true);
                if (err) {
-                       brcmf_err("failed at addr:0x%0x\n",
+                       brcmf_err("failed at addr: 0x%0x\n",
                                  SBSDIO_FUNC1_SBADDRLOW + i);
                        break;
                }
@@ -192,13 +339,13 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
 }
 
 static int
-brcmf_sdio_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr)
+brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr)
 {
        uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
        int err = 0;
 
        if (bar0 != sdiodev->sbwad) {
-               err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
+               err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
                if (err)
                        return err;
 
@@ -213,62 +360,14 @@ brcmf_sdio_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr)
        return 0;
 }
 
-int
-brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
-                       void *data, bool write)
-{
-       u8 func_num, reg_size;
-       s32 retry = 0;
-       int ret;
-
-       /*
-        * figure out how to read the register based on address range
-        * 0x00 ~ 0x7FF: function 0 CCCR and FBR
-        * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
-        * The rest: function 1 silicon backplane core registers
-        */
-       if ((addr & ~REG_F0_REG_MASK) == 0) {
-               func_num = SDIO_FUNC_0;
-               reg_size = 1;
-       } else if ((addr & ~REG_F1_MISC_MASK) == 0) {
-               func_num = SDIO_FUNC_1;
-               reg_size = 1;
-       } else {
-               func_num = SDIO_FUNC_1;
-               reg_size = 4;
-
-               ret = brcmf_sdio_addrprep(sdiodev, reg_size, &addr);
-               if (ret)
-                       goto done;
-       }
-
-       do {
-               if (!write)
-                       memset(data, 0, reg_size);
-               if (retry)      /* wait for 1 ms till bus get settled down */
-                       usleep_range(1000, 2000);
-               if (reg_size == 1)
-                       ret = brcmf_sdioh_request_byte(sdiodev, write,
-                                                      func_num, addr, data);
-               else
-                       ret = brcmf_sdioh_request_word(sdiodev, write,
-                                                      func_num, addr, data, 4);
-       } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
-
-done:
-       if (ret != 0)
-               brcmf_err("failed with %d\n", ret);
-
-       return ret;
-}
-
-u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
+u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
 {
        u8 data;
        int retval;
 
        brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
-       retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
+       retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
+                                         false);
        brcmf_dbg(SDIO, "data:0x%02x\n", data);
 
        if (ret)
@@ -277,52 +376,62 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
        return data;
 }
 
-u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
+u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
 {
        u32 data;
        int retval;
 
        brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
-       retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
+       retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr);
+       if (retval)
+               goto done;
+       retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
+                                         false);
        brcmf_dbg(SDIO, "data:0x%08x\n", data);
 
+done:
        if (ret)
                *ret = retval;
 
        return data;
 }
 
-void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
+void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
                      u8 data, int *ret)
 {
        int retval;
 
        brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
-       retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
-
+       retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
+                                         true);
        if (ret)
                *ret = retval;
 }
 
-void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
+void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
                      u32 data, int *ret)
 {
        int retval;
 
        brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
-       retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
+       retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr);
+       if (retval)
+               goto done;
+       retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
+                                         true);
 
+done:
        if (ret)
                *ret = retval;
 }
 
-static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
+static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
                             bool write, u32 addr, struct sk_buff *pkt)
 {
        unsigned int req_sz;
 
-       brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
-       if (brcmf_pm_resume_error(sdiodev))
+       brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
+       if (brcmf_sdiod_pm_resume_error(sdiodev))
                return -EIO;
 
        /* Single skb use the standard mmc interface */
@@ -345,7 +454,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 }
 
 /**
- * brcmf_sdio_sglist_rw - SDIO interface function for block data access
+ * brcmf_sdiod_sglist_rw - SDIO interface function for block data access
  * @sdiodev: brcmfmac sdio device
  * @fn: SDIO function number
  * @write: direction flag
@@ -356,9 +465,9 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
  * stack for block data access. It assumes that the skb passed down by the
  * caller has already been padded and aligned.
  */
-static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
-                               bool write, u32 addr,
-                               struct sk_buff_head *pktlist)
+static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
+                                bool write, u32 addr,
+                                struct sk_buff_head *pktlist)
 {
        unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
        unsigned int max_req_sz, orig_offset, dst_offset;
@@ -376,8 +485,8 @@ static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
        if (!pktlist->qlen)
                return -EINVAL;
 
-       brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
-       if (brcmf_pm_resume_error(sdiodev))
+       brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
+       if (brcmf_sdiod_pm_resume_error(sdiodev))
                return -EIO;
 
        target_list = pktlist;
@@ -524,9 +633,7 @@ exit:
        return ret;
 }
 
-int
-brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                     uint flags, u8 *buf, uint nbytes)
+int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
 {
        struct sk_buff *mypkt;
        int err;
@@ -538,7 +645,7 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
                return -EIO;
        }
 
-       err = brcmf_sdcard_recv_pkt(sdiodev, addr, fn, flags, mypkt);
+       err = brcmf_sdiod_recv_pkt(sdiodev, mypkt);
        if (!err)
                memcpy(buf, mypkt->data, nbytes);
 
@@ -546,50 +653,47 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
        return err;
 }
 
-int
-brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                     uint flags, struct sk_buff *pkt)
+int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt)
 {
-       uint width;
+       u32 addr = sdiodev->sbwad;
        int err = 0;
 
-       brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
-                 fn, addr, pkt->len);
+       brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
 
-       width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-       err = brcmf_sdio_addrprep(sdiodev, width, &addr);
+       err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
        if (err)
                goto done;
 
-       err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt);
+       err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, pkt);
 
 done:
        return err;
 }
 
-int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                           uint flags, struct sk_buff_head *pktq, uint totlen)
+int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
+                          struct sk_buff_head *pktq, uint totlen)
 {
        struct sk_buff *glom_skb;
        struct sk_buff *skb;
-       uint width;
+       u32 addr = sdiodev->sbwad;
        int err = 0;
 
-       brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
-                 fn, addr, pktq->qlen);
+       brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n",
+                 addr, pktq->qlen);
 
-       width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-       err = brcmf_sdio_addrprep(sdiodev, width, &addr);
+       err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
        if (err)
                goto done;
 
        if (pktq->qlen == 1)
-               err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq->next);
+               err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
+                                        pktq->next);
        else if (!sdiodev->sg_support) {
                glom_skb = brcmu_pkt_buf_get_skb(totlen);
                if (!glom_skb)
                        return -ENOMEM;
-               err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, glom_skb);
+               err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
+                                        glom_skb);
                if (err)
                        goto done;
 
@@ -598,18 +702,17 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
                        skb_pull(glom_skb, skb->len);
                }
        } else
-               err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
+               err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, false, addr,
+                                           pktq);
 
 done:
        return err;
 }
 
-int
-brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                     uint flags, u8 *buf, uint nbytes)
+int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
 {
        struct sk_buff *mypkt;
-       uint width;
+       u32 addr = sdiodev->sbwad;
        int err;
 
        mypkt = brcmu_pkt_buf_get_skb(nbytes);
@@ -621,48 +724,47 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 
        memcpy(mypkt->data, buf, nbytes);
 
-       width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-       err = brcmf_sdio_addrprep(sdiodev, width, &addr);
+       err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
 
        if (!err)
-               err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt);
+               err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, addr,
+                                        mypkt);
 
        brcmu_pkt_buf_free_skb(mypkt);
        return err;
 
 }
 
-int
-brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                     uint flags, struct sk_buff_head *pktq)
+int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
+                        struct sk_buff_head *pktq)
 {
        struct sk_buff *skb;
-       uint width;
+       u32 addr = sdiodev->sbwad;
        int err;
 
-       brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
-                 fn, addr, pktq->qlen);
+       brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen);
 
-       width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-       err = brcmf_sdio_addrprep(sdiodev, width, &addr);
+       err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
        if (err)
                return err;
 
        if (pktq->qlen == 1 || !sdiodev->sg_support)
                skb_queue_walk(pktq, skb) {
-                       err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, skb);
+                       err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true,
+                                                addr, skb);
                        if (err)
                                break;
                }
        else
-               err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
+               err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr,
+                                           pktq);
 
        return err;
 }
 
 int
-brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
-                u8 *data, uint size)
+brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
+                 u8 *data, uint size)
 {
        int bcmerror = 0;
        struct sk_buff *pkt;
@@ -689,7 +791,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
        /* Do the transfer(s) */
        while (size) {
                /* Set the backplane window to include the start address */
-               bcmerror = brcmf_sdcard_set_sbaddr_window(sdiodev, address);
+               bcmerror = brcmf_sdiod_set_sbaddr_window(sdiodev, address);
                if (bcmerror)
                        break;
 
@@ -703,8 +805,8 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
                skb_put(pkt, dsize);
                if (write)
                        memcpy(pkt->data, data, dsize);
-               bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write,
-                                            sdaddr, pkt);
+               bcmerror = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write,
+                                             sdaddr, pkt);
                if (bcmerror) {
                        brcmf_err("membytes transfer failed\n");
                        break;
@@ -726,7 +828,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
        dev_kfree_skb(pkt);
 
        /* Return the window to backplane enumeration space for core access */
-       if (brcmf_sdcard_set_sbaddr_window(sdiodev, sdiodev->sbwad))
+       if (brcmf_sdiod_set_sbaddr_window(sdiodev, sdiodev->sbwad))
                brcmf_err("FAILED to set window back to 0x%x\n",
                          sdiodev->sbwad);
 
@@ -735,65 +837,337 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
        return bcmerror;
 }
 
-int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
 {
        char t_func = (char)fn;
        brcmf_dbg(SDIO, "Enter\n");
 
        /* issue abort cmd52 command through F0 */
-       brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
-                                SDIO_CCCR_ABORT, &t_func);
+       brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT,
+                                sizeof(t_func), &t_func, true);
 
        brcmf_dbg(SDIO, "Exit\n");
        return 0;
 }
 
-int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
+static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
 {
-       u32 regs = 0;
+       sdiodev->bus_if->state = BRCMF_BUS_DOWN;
+
+       if (sdiodev->bus) {
+               brcmf_sdio_remove(sdiodev->bus);
+               sdiodev->bus = NULL;
+       }
+
+       /* Disable Function 2 */
+       sdio_claim_host(sdiodev->func[2]);
+       sdio_disable_func(sdiodev->func[2]);
+       sdio_release_host(sdiodev->func[2]);
+
+       /* Disable Function 1 */
+       sdio_claim_host(sdiodev->func[1]);
+       sdio_disable_func(sdiodev->func[1]);
+       sdio_release_host(sdiodev->func[1]);
+
+       sdiodev->sbwad = 0;
+
+       return 0;
+}
+
+static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
+{
+       struct sdio_func *func;
+       struct mmc_host *host;
+       uint max_blocks;
        int ret = 0;
 
-       ret = brcmf_sdioh_attach(sdiodev);
-       if (ret)
+       sdiodev->num_funcs = 2;
+
+       sdio_claim_host(sdiodev->func[1]);
+
+       ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
+       if (ret) {
+               brcmf_err("Failed to set F1 blocksize\n");
+               sdio_release_host(sdiodev->func[1]);
+               goto out;
+       }
+       ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
+       if (ret) {
+               brcmf_err("Failed to set F2 blocksize\n");
+               sdio_release_host(sdiodev->func[1]);
+               goto out;
+       }
+
+       /* increase F2 timeout */
+       sdiodev->func[2]->enable_timeout = SDIO_WAIT_F2RDY;
+
+       /* Enable Function 1 */
+       ret = sdio_enable_func(sdiodev->func[1]);
+       sdio_release_host(sdiodev->func[1]);
+       if (ret) {
+               brcmf_err("Failed to enable F1: err=%d\n", ret);
                goto out;
+       }
 
-       regs = SI_ENUM_BASE;
+       /*
+        * determine host related variables after brcmf_sdiod_probe()
+        * as func->cur_blksize is properly set and F2 init has been
+        * completed successfully.
+        */
+       func = sdiodev->func[2];
+       host = func->card->host;
+       sdiodev->sg_support = host->max_segs > 1;
+       max_blocks = min_t(uint, host->max_blk_count, 511u);
+       sdiodev->max_request_size = min_t(uint, host->max_req_size,
+                                         max_blocks * func->cur_blksize);
+       sdiodev->max_segment_count = min_t(uint, host->max_segs,
+                                          SG_MAX_SINGLE_ALLOC);
+       sdiodev->max_segment_size = host->max_seg_size;
 
        /* try to attach to the target device */
-       sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
+       sdiodev->bus = brcmf_sdio_probe(sdiodev);
        if (!sdiodev->bus) {
-               brcmf_err("device attach failed\n");
                ret = -ENODEV;
                goto out;
        }
 
 out:
        if (ret)
-               brcmf_sdio_remove(sdiodev);
+               brcmf_sdiod_remove(sdiodev);
 
        return ret;
 }
 
-int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
+/* devices we support, null terminated */
+static const struct sdio_device_id brcmf_sdmmc_ids[] = {
+       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM,
+                    SDIO_DEVICE_ID_BROADCOM_4335_4339)},
+       { /* end: all zeroes */ },
+};
+MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
+
+static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
+
+
+static int brcmf_ops_sdio_probe(struct sdio_func *func,
+                               const struct sdio_device_id *id)
 {
-       sdiodev->bus_if->state = BRCMF_BUS_DOWN;
+       int err;
+       struct brcmf_sdio_dev *sdiodev;
+       struct brcmf_bus *bus_if;
 
-       if (sdiodev->bus) {
-               brcmf_sdbrcm_disconnect(sdiodev->bus);
-               sdiodev->bus = NULL;
+       brcmf_dbg(SDIO, "Enter\n");
+       brcmf_dbg(SDIO, "Class=%x\n", func->class);
+       brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
+       brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+       brcmf_dbg(SDIO, "Function#: %d\n", func->num);
+
+       /* Consume func num 1 but dont do anything with it. */
+       if (func->num == 1)
+               return 0;
+
+       /* Ignore anything but func 2 */
+       if (func->num != 2)
+               return -ENODEV;
+
+       bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
+       if (!bus_if)
+               return -ENOMEM;
+       sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
+       if (!sdiodev) {
+               kfree(bus_if);
+               return -ENOMEM;
+       }
+
+       /* store refs to functions used. mmc_card does
+        * not hold the F0 function pointer.
+        */
+       sdiodev->func[0] = kmemdup(func, sizeof(*func), GFP_KERNEL);
+       sdiodev->func[0]->num = 0;
+       sdiodev->func[1] = func->card->sdio_func[0];
+       sdiodev->func[2] = func;
+
+       sdiodev->bus_if = bus_if;
+       bus_if->bus_priv.sdio = sdiodev;
+       bus_if->proto_type = BRCMF_PROTO_BCDC;
+       dev_set_drvdata(&func->dev, bus_if);
+       dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
+       sdiodev->dev = &sdiodev->func[1]->dev;
+       sdiodev->pdata = brcmfmac_sdio_pdata;
+
+       atomic_set(&sdiodev->suspend, false);
+       init_waitqueue_head(&sdiodev->request_word_wait);
+       init_waitqueue_head(&sdiodev->request_buffer_wait);
+
+       brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
+       err = brcmf_sdiod_probe(sdiodev);
+       if (err) {
+               brcmf_err("F2 error, probe failed %d...\n", err);
+               goto fail;
        }
 
-       brcmf_sdioh_detach(sdiodev);
+       brcmf_dbg(SDIO, "F2 init completed...\n");
+       return 0;
 
-       sdiodev->sbwad = 0;
+fail:
+       dev_set_drvdata(&func->dev, NULL);
+       dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
+       kfree(sdiodev->func[0]);
+       kfree(sdiodev);
+       kfree(bus_if);
+       return err;
+}
+
+static void brcmf_ops_sdio_remove(struct sdio_func *func)
+{
+       struct brcmf_bus *bus_if;
+       struct brcmf_sdio_dev *sdiodev;
+
+       brcmf_dbg(SDIO, "Enter\n");
+       brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
+       brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+       brcmf_dbg(SDIO, "Function: %d\n", func->num);
+
+       if (func->num != 1 && func->num != 2)
+               return;
+
+       bus_if = dev_get_drvdata(&func->dev);
+       if (bus_if) {
+               sdiodev = bus_if->bus_priv.sdio;
+               brcmf_sdiod_remove(sdiodev);
+
+               dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
+               dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
+
+               kfree(bus_if);
+               kfree(sdiodev->func[0]);
+               kfree(sdiodev);
+       }
+
+       brcmf_dbg(SDIO, "Exit\n");
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int brcmf_ops_sdio_suspend(struct device *dev)
+{
+       mmc_pm_flag_t sdio_flags;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+       int ret = 0;
+
+       brcmf_dbg(SDIO, "\n");
+
+       atomic_set(&sdiodev->suspend, true);
+
+       sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
+       if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
+               brcmf_err("Host can't keep power while suspended\n");
+               return -EINVAL;
+       }
+
+       ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
+       if (ret) {
+               brcmf_err("Failed to set pm_flags\n");
+               return ret;
+       }
+
+       brcmf_sdio_wd_timer(sdiodev->bus, 0);
+
+       return ret;
+}
+
+static int brcmf_ops_sdio_resume(struct device *dev)
+{
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+
+       brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
+       atomic_set(&sdiodev->suspend, false);
+       return 0;
+}
+
+static const struct dev_pm_ops brcmf_sdio_pm_ops = {
+       .suspend        = brcmf_ops_sdio_suspend,
+       .resume         = brcmf_ops_sdio_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+static struct sdio_driver brcmf_sdmmc_driver = {
+       .probe = brcmf_ops_sdio_probe,
+       .remove = brcmf_ops_sdio_remove,
+       .name = BRCMFMAC_SDIO_PDATA_NAME,
+       .id_table = brcmf_sdmmc_ids,
+#ifdef CONFIG_PM_SLEEP
+       .drv = {
+               .pm = &brcmf_sdio_pm_ops,
+       },
+#endif /* CONFIG_PM_SLEEP */
+};
+
+static int brcmf_sdio_pd_probe(struct platform_device *pdev)
+{
+       brcmf_dbg(SDIO, "Enter\n");
+
+       brcmfmac_sdio_pdata = dev_get_platdata(&pdev->dev);
+
+       if (brcmfmac_sdio_pdata->power_on)
+               brcmfmac_sdio_pdata->power_on();
 
        return 0;
 }
 
-void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
+static int brcmf_sdio_pd_remove(struct platform_device *pdev)
+{
+       brcmf_dbg(SDIO, "Enter\n");
+
+       if (brcmfmac_sdio_pdata->power_off)
+               brcmfmac_sdio_pdata->power_off();
+
+       sdio_unregister_driver(&brcmf_sdmmc_driver);
+
+       return 0;
+}
+
+static struct platform_driver brcmf_sdio_pd = {
+       .remove         = brcmf_sdio_pd_remove,
+       .driver         = {
+               .name   = BRCMFMAC_SDIO_PDATA_NAME,
+               .owner  = THIS_MODULE,
+       }
+};
+
+void brcmf_sdio_register(void)
+{
+       int ret;
+
+       ret = sdio_register_driver(&brcmf_sdmmc_driver);
+       if (ret)
+               brcmf_err("sdio_register_driver failed: %d\n", ret);
+}
+
+void brcmf_sdio_exit(void)
 {
-       if (enable)
-               brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
+       brcmf_dbg(SDIO, "Enter\n");
+
+       if (brcmfmac_sdio_pdata)
+               platform_driver_unregister(&brcmf_sdio_pd);
        else
-               brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
+               sdio_unregister_driver(&brcmf_sdmmc_driver);
+}
+
+void __init brcmf_sdio_init(void)
+{
+       int ret;
+
+       brcmf_dbg(SDIO, "Enter\n");
+
+       ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
+       if (ret == -ENODEV)
+               brcmf_dbg(SDIO, "No platform data available.\n");
 }
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
deleted file mode 100644 (file)
index a511c27..0000000
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/core.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/suspend.h>
-#include <linux/errno.h>
-#include <linux/sched.h>       /* request_irq() */
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/brcmfmac-sdio.h>
-#include <net/cfg80211.h>
-
-#include <defs.h>
-#include <brcm_hw_ids.h>
-#include <brcmu_utils.h>
-#include <brcmu_wifi.h>
-#include "sdio_host.h"
-#include "sdio_chip.h"
-#include "dhd_dbg.h"
-#include "dhd_bus.h"
-
-#define SDIO_VENDOR_ID_BROADCOM                0x02d0
-
-#define DMA_ALIGN_MASK 0x03
-
-#define SDIO_FUNC1_BLOCKSIZE           64
-#define SDIO_FUNC2_BLOCKSIZE           512
-
-/* devices we support, null terminated */
-static const struct sdio_device_id brcmf_sdmmc_ids[] = {
-       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
-       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM,
-                    SDIO_DEVICE_ID_BROADCOM_4335_4339)},
-       { /* end: all zeroes */ },
-};
-MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
-
-static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
-
-
-bool
-brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
-{
-       bool is_err = false;
-#ifdef CONFIG_PM_SLEEP
-       is_err = atomic_read(&sdiodev->suspend);
-#endif
-       return is_err;
-}
-
-void
-brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq)
-{
-#ifdef CONFIG_PM_SLEEP
-       int retry = 0;
-       while (atomic_read(&sdiodev->suspend) && retry++ != 30)
-               wait_event_timeout(*wq, false, HZ/100);
-#endif
-}
-
-static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
-                                           uint regaddr, u8 *byte)
-{
-       struct sdio_func *sdfunc = sdiodev->func[0];
-       int err_ret;
-
-       /*
-        * Can only directly write to some F0 registers.
-        * Handle F2 enable/disable and Abort command
-        * as a special case.
-        */
-       if (regaddr == SDIO_CCCR_IOEx) {
-               sdfunc = sdiodev->func[2];
-               if (sdfunc) {
-                       if (*byte & SDIO_FUNC_ENABLE_2) {
-                               /* Enable Function 2 */
-                               err_ret = sdio_enable_func(sdfunc);
-                               if (err_ret)
-                                       brcmf_err("enable F2 failed:%d\n",
-                                                 err_ret);
-                       } else {
-                               /* Disable Function 2 */
-                               err_ret = sdio_disable_func(sdfunc);
-                               if (err_ret)
-                                       brcmf_err("Disable F2 failed:%d\n",
-                                                 err_ret);
-                       }
-               } else {
-                       err_ret = -ENOENT;
-               }
-       } else if ((regaddr == SDIO_CCCR_ABORT) ||
-                  (regaddr == SDIO_CCCR_IENx)) {
-               sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
-                                GFP_KERNEL);
-               if (!sdfunc)
-                       return -ENOMEM;
-               sdfunc->num = 0;
-               sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
-               kfree(sdfunc);
-       } else if (regaddr < 0xF0) {
-               brcmf_err("F0 Wr:0x%02x: write disallowed\n", regaddr);
-               err_ret = -EPERM;
-       } else {
-               sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
-       }
-
-       return err_ret;
-}
-
-int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
-                            uint regaddr, u8 *byte)
-{
-       int err_ret;
-
-       brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
-
-       brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
-       if (brcmf_pm_resume_error(sdiodev))
-               return -EIO;
-
-       if (rw && func == 0) {
-               /* handle F0 separately */
-               err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
-       } else {
-               if (rw) /* CMD52 Write */
-                       sdio_writeb(sdiodev->func[func], *byte, regaddr,
-                                   &err_ret);
-               else if (func == 0) {
-                       *byte = sdio_f0_readb(sdiodev->func[func], regaddr,
-                                             &err_ret);
-               } else {
-                       *byte = sdio_readb(sdiodev->func[func], regaddr,
-                                          &err_ret);
-               }
-       }
-
-       if (err_ret) {
-               /*
-                * SleepCSR register access can fail when
-                * waking up the device so reduce this noise
-                * in the logs.
-                */
-               if (regaddr != SBSDIO_FUNC1_SLEEPCSR)
-                       brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
-                                 rw ? "write" : "read", func, regaddr, *byte,
-                                 err_ret);
-               else
-                       brcmf_dbg(SDIO, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
-                                 rw ? "write" : "read", func, regaddr, *byte,
-                                 err_ret);
-       }
-       return err_ret;
-}
-
-int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
-                            uint rw, uint func, uint addr, u32 *word,
-                            uint nbytes)
-{
-       int err_ret = -EIO;
-
-       if (func == 0) {
-               brcmf_err("Only CMD52 allowed to F0\n");
-               return -EINVAL;
-       }
-
-       brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
-                 rw, func, addr, nbytes);
-
-       brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
-       if (brcmf_pm_resume_error(sdiodev))
-               return -EIO;
-
-       if (rw) {               /* CMD52 Write */
-               if (nbytes == 4)
-                       sdio_writel(sdiodev->func[func], *word, addr,
-                                   &err_ret);
-               else if (nbytes == 2)
-                       sdio_writew(sdiodev->func[func], (*word & 0xFFFF),
-                                   addr, &err_ret);
-               else
-                       brcmf_err("Invalid nbytes: %d\n", nbytes);
-       } else {                /* CMD52 Read */
-               if (nbytes == 4)
-                       *word = sdio_readl(sdiodev->func[func], addr, &err_ret);
-               else if (nbytes == 2)
-                       *word = sdio_readw(sdiodev->func[func], addr,
-                                          &err_ret) & 0xFFFF;
-               else
-                       brcmf_err("Invalid nbytes: %d\n", nbytes);
-       }
-
-       if (err_ret)
-               brcmf_err("Failed to %s word, Err: 0x%08x\n",
-                         rw ? "write" : "read", err_ret);
-
-       return err_ret;
-}
-
-static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
-{
-       /* read 24 bits and return valid 17 bit addr */
-       int i, ret;
-       u32 scratch, regdata;
-       __le32 scratch_le;
-       u8 *ptr = (u8 *)&scratch_le;
-
-       for (i = 0; i < 3; i++) {
-               regdata = brcmf_sdio_regrl(sdiodev, regaddr, &ret);
-               if (ret != 0)
-                       brcmf_err("Can't read!\n");
-
-               *ptr++ = (u8) regdata;
-               regaddr++;
-       }
-
-       /* Only the lower 17-bits are valid */
-       scratch = le32_to_cpu(scratch_le);
-       scratch &= 0x0001FFFF;
-       return scratch;
-}
-
-static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
-{
-       int err_ret;
-       u32 fbraddr;
-       u8 func;
-
-       brcmf_dbg(SDIO, "\n");
-
-       /* Get the Card's common CIS address */
-       sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev,
-                                                          SDIO_CCCR_CIS);
-       brcmf_dbg(SDIO, "Card's Common CIS Ptr = 0x%x\n",
-                 sdiodev->func_cis_ptr[0]);
-
-       /* Get the Card's function CIS (for each function) */
-       for (fbraddr = SDIO_FBR_BASE(1), func = 1;
-            func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
-               sdiodev->func_cis_ptr[func] =
-                   brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr);
-               brcmf_dbg(SDIO, "Function %d CIS Ptr = 0x%x\n",
-                         func, sdiodev->func_cis_ptr[func]);
-       }
-
-       /* Enable Function 1 */
-       err_ret = sdio_enable_func(sdiodev->func[1]);
-       if (err_ret)
-               brcmf_err("Failed to enable F1 Err: 0x%08x\n", err_ret);
-
-       return false;
-}
-
-/*
- *     Public entry points & extern's
- */
-int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
-{
-       int err_ret = 0;
-       struct mmc_host *host;
-       struct sdio_func *func;
-       uint max_blocks;
-
-       brcmf_dbg(SDIO, "\n");
-
-       sdiodev->num_funcs = 2;
-
-       sdio_claim_host(sdiodev->func[1]);
-
-       err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
-       if (err_ret) {
-               brcmf_err("Failed to set F1 blocksize\n");
-               goto out;
-       }
-
-       err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
-       if (err_ret) {
-               brcmf_err("Failed to set F2 blocksize\n");
-               goto out;
-       }
-
-       brcmf_sdioh_enablefuncs(sdiodev);
-
-       /*
-        * determine host related variables after brcmf_sdio_probe()
-        * as func->cur_blksize is properly set and F2 init has been
-        * completed successfully.
-        */
-       func = sdiodev->func[2];
-       host = func->card->host;
-       sdiodev->sg_support = host->max_segs > 1;
-       max_blocks = min_t(uint, host->max_blk_count, 511u);
-       sdiodev->max_request_size = min_t(uint, host->max_req_size,
-                                         max_blocks * func->cur_blksize);
-       sdiodev->max_segment_count = min_t(uint, host->max_segs,
-                                          SG_MAX_SINGLE_ALLOC);
-       sdiodev->max_segment_size = host->max_seg_size;
-out:
-       sdio_release_host(sdiodev->func[1]);
-       brcmf_dbg(SDIO, "Done\n");
-       return err_ret;
-}
-
-void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
-{
-       brcmf_dbg(SDIO, "\n");
-
-       /* Disable Function 2 */
-       sdio_claim_host(sdiodev->func[2]);
-       sdio_disable_func(sdiodev->func[2]);
-       sdio_release_host(sdiodev->func[2]);
-
-       /* Disable Function 1 */
-       sdio_claim_host(sdiodev->func[1]);
-       sdio_disable_func(sdiodev->func[1]);
-       sdio_release_host(sdiodev->func[1]);
-
-}
-
-static int brcmf_ops_sdio_probe(struct sdio_func *func,
-                               const struct sdio_device_id *id)
-{
-       int err;
-       struct brcmf_sdio_dev *sdiodev;
-       struct brcmf_bus *bus_if;
-
-       brcmf_dbg(SDIO, "Enter\n");
-       brcmf_dbg(SDIO, "Class=%x\n", func->class);
-       brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
-       brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
-       brcmf_dbg(SDIO, "Function#: %d\n", func->num);
-
-       /* Consume func num 1 but dont do anything with it. */
-       if (func->num == 1)
-               return 0;
-
-       /* Ignore anything but func 2 */
-       if (func->num != 2)
-               return -ENODEV;
-
-       bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
-       if (!bus_if)
-               return -ENOMEM;
-       sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
-       if (!sdiodev) {
-               kfree(bus_if);
-               return -ENOMEM;
-       }
-
-       sdiodev->func[0] = func->card->sdio_func[0];
-       sdiodev->func[1] = func->card->sdio_func[0];
-       sdiodev->func[2] = func;
-
-       sdiodev->bus_if = bus_if;
-       bus_if->bus_priv.sdio = sdiodev;
-       dev_set_drvdata(&func->dev, bus_if);
-       dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
-       sdiodev->dev = &sdiodev->func[1]->dev;
-       sdiodev->pdata = brcmfmac_sdio_pdata;
-
-       atomic_set(&sdiodev->suspend, false);
-       init_waitqueue_head(&sdiodev->request_byte_wait);
-       init_waitqueue_head(&sdiodev->request_word_wait);
-       init_waitqueue_head(&sdiodev->request_buffer_wait);
-
-       brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n");
-       err = brcmf_sdio_probe(sdiodev);
-       if (err) {
-               brcmf_err("F2 error, probe failed %d...\n", err);
-               goto fail;
-       }
-
-       brcmf_dbg(SDIO, "F2 init completed...\n");
-       return 0;
-
-fail:
-       dev_set_drvdata(&func->dev, NULL);
-       dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
-       kfree(sdiodev);
-       kfree(bus_if);
-       return err;
-}
-
-static void brcmf_ops_sdio_remove(struct sdio_func *func)
-{
-       struct brcmf_bus *bus_if;
-       struct brcmf_sdio_dev *sdiodev;
-
-       brcmf_dbg(SDIO, "Enter\n");
-       brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
-       brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
-       brcmf_dbg(SDIO, "Function: %d\n", func->num);
-
-       if (func->num != 1 && func->num != 2)
-               return;
-
-       bus_if = dev_get_drvdata(&func->dev);
-       if (bus_if) {
-               sdiodev = bus_if->bus_priv.sdio;
-               brcmf_sdio_remove(sdiodev);
-
-               dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
-               dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
-
-               kfree(bus_if);
-               kfree(sdiodev);
-       }
-
-       brcmf_dbg(SDIO, "Exit\n");
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int brcmf_sdio_suspend(struct device *dev)
-{
-       mmc_pm_flag_t sdio_flags;
-       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-       int ret = 0;
-
-       brcmf_dbg(SDIO, "\n");
-
-       atomic_set(&sdiodev->suspend, true);
-
-       sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
-       if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
-               brcmf_err("Host can't keep power while suspended\n");
-               return -EINVAL;
-       }
-
-       ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
-       if (ret) {
-               brcmf_err("Failed to set pm_flags\n");
-               return ret;
-       }
-
-       brcmf_sdio_wdtmr_enable(sdiodev, false);
-
-       return ret;
-}
-
-static int brcmf_sdio_resume(struct device *dev)
-{
-       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-
-       brcmf_sdio_wdtmr_enable(sdiodev, true);
-       atomic_set(&sdiodev->suspend, false);
-       return 0;
-}
-
-static const struct dev_pm_ops brcmf_sdio_pm_ops = {
-       .suspend        = brcmf_sdio_suspend,
-       .resume         = brcmf_sdio_resume,
-};
-#endif /* CONFIG_PM_SLEEP */
-
-static struct sdio_driver brcmf_sdmmc_driver = {
-       .probe = brcmf_ops_sdio_probe,
-       .remove = brcmf_ops_sdio_remove,
-       .name = BRCMFMAC_SDIO_PDATA_NAME,
-       .id_table = brcmf_sdmmc_ids,
-#ifdef CONFIG_PM_SLEEP
-       .drv = {
-               .pm = &brcmf_sdio_pm_ops,
-       },
-#endif /* CONFIG_PM_SLEEP */
-};
-
-static int brcmf_sdio_pd_probe(struct platform_device *pdev)
-{
-       brcmf_dbg(SDIO, "Enter\n");
-
-       brcmfmac_sdio_pdata = dev_get_platdata(&pdev->dev);
-
-       if (brcmfmac_sdio_pdata->power_on)
-               brcmfmac_sdio_pdata->power_on();
-
-       return 0;
-}
-
-static int brcmf_sdio_pd_remove(struct platform_device *pdev)
-{
-       brcmf_dbg(SDIO, "Enter\n");
-
-       if (brcmfmac_sdio_pdata->power_off)
-               brcmfmac_sdio_pdata->power_off();
-
-       sdio_unregister_driver(&brcmf_sdmmc_driver);
-
-       return 0;
-}
-
-static struct platform_driver brcmf_sdio_pd = {
-       .remove         = brcmf_sdio_pd_remove,
-       .driver         = {
-               .name   = BRCMFMAC_SDIO_PDATA_NAME,
-               .owner  = THIS_MODULE,
-       }
-};
-
-void brcmf_sdio_register(void)
-{
-       int ret;
-
-       ret = sdio_register_driver(&brcmf_sdmmc_driver);
-       if (ret)
-               brcmf_err("sdio_register_driver failed: %d\n", ret);
-}
-
-void brcmf_sdio_exit(void)
-{
-       brcmf_dbg(SDIO, "Enter\n");
-
-       if (brcmfmac_sdio_pdata)
-               platform_driver_unregister(&brcmf_sdio_pd);
-       else
-               sdio_unregister_driver(&brcmf_sdmmc_driver);
-}
-
-void __init brcmf_sdio_init(void)
-{
-       int ret;
-
-       brcmf_dbg(SDIO, "Enter\n");
-
-       ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
-       if (ret == -ENODEV)
-               brcmf_dbg(SDIO, "No platform data available.\n");
-}
index 252024bcbc3ba736c65d18975f2b5106e026737a..939d6b13292248563f92bc4287632341c4997072 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef _BRCMF_H_
 #define _BRCMF_H_
 
-#define BRCMF_VERSION_STR              "4.218.248.5"
-
 #include "fweh.h"
 
 #define TOE_TX_CSUM_OL         0x00000001
 #define BRCMF_DCMD_MEDLEN      1536
 #define BRCMF_DCMD_MAXLEN      8192
 
+/* IOCTL from host to device are limited in lenght. A device can only handle
+ * ethernet frame size. This limitation is to be applied by protocol layer.
+ */
+#define BRCMF_TX_IOCTL_MAX_MSG_SIZE    (ETH_FRAME_LEN+ETH_FCS_LEN)
+
 #define BRCMF_AMPDU_RX_REORDER_MAXFLOWS                256
 
 /* Length of firmware version string stored for
index 6a54905528befd0238ce198acdbd6f9d642d1340..5c12a07673fa55701007be40c5d445abb5c4b5d6 100644 (file)
@@ -24,6 +24,12 @@ enum brcmf_bus_state {
        BRCMF_BUS_DATA          /* Ready for frame transfers */
 };
 
+/* The level of bus communication with the dongle */
+enum brcmf_bus_protocol_type {
+       BRCMF_PROTO_BCDC,
+       BRCMF_PROTO_MSGBUF
+};
+
 struct brcmf_bus_dcmd {
        char *name;
        char *param;
@@ -65,6 +71,7 @@ struct brcmf_bus_ops {
  * struct brcmf_bus - interface structure between common and bus layer
  *
  * @bus_priv: pointer to private bus device.
+ * @proto_type: protocol type, bcdc or msgbuf
  * @dev: device pointer of bus device.
  * @drvr: public driver information.
  * @state: operational state of the bus interface.
@@ -80,6 +87,7 @@ struct brcmf_bus {
                struct brcmf_sdio_dev *sdio;
                struct brcmf_usbdev *usb;
        } bus_priv;
+       enum brcmf_bus_protocol_type proto_type;
        struct device *dev;
        struct brcmf_pub *drvr;
        enum brcmf_bus_state state;
index 548dbb5542c63eb2631aafa8b2344013bfd90752..6a8983a1fb9c3451908c1cf28426d78e6600d091 100644 (file)
 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME        40
 #define BRCMF_DEFAULT_PACKET_FILTER    "100 0 0 0 0x01 0x00"
 
-#ifdef DEBUG
-static const char brcmf_version[] =
-       "Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on "
-       __DATE__ " at " __TIME__;
-#else
-static const char brcmf_version[] =
-       "Dongle Host Driver, version " BRCMF_VERSION_STR;
-#endif
-
 
 bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
                      struct sk_buff *pkt, int prec)
index bce0b8e511fd22eb085077169050426f42714838..af39edae8c627db18494a17c7ed2a2144a000bbd 100644 (file)
@@ -702,7 +702,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
 
        brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
 
-       ndev->destructor = free_netdev;
+       ndev->destructor = brcmf_cfg80211_free_netdev;
        return 0;
 
 fail:
@@ -859,8 +859,6 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
                }
                /* unregister will take care of freeing it */
                unregister_netdev(ifp->ndev);
-               if (bssidx == 0)
-                       brcmf_cfg80211_detach(drvr->config);
        } else {
                kfree(ifp);
        }
@@ -963,8 +961,7 @@ int brcmf_bus_start(struct device *dev)
 fail:
        if (ret < 0) {
                brcmf_err("failed: %d\n", ret);
-               if (drvr->config)
-                       brcmf_cfg80211_detach(drvr->config);
+               brcmf_cfg80211_detach(drvr->config);
                if (drvr->fws) {
                        brcmf_fws_del_interface(ifp);
                        brcmf_fws_deinit(drvr);
@@ -1039,6 +1036,8 @@ void brcmf_detach(struct device *dev)
                        brcmf_del_if(drvr, i);
                }
 
+       brcmf_cfg80211_detach(drvr->config);
+
        brcmf_bus_detach(drvr);
 
        brcmf_proto_detach(drvr);
index 0f95f3e79c10f6e04f8a5735a102e3059739e4f8..9c7f08a13105637d8dd8bdbd1d4eb54019e79d6c 100644 (file)
@@ -260,9 +260,6 @@ struct rte_console {
 #define MAX_HDR_READ   (1 << 6)
 #define MAX_RX_DATASZ  2048
 
-/* Maximum milliseconds to wait for F2 to come up */
-#define BRCMF_WAIT_F2RDY       3000
-
 /* Bump up limit on waiting for HT to account for first startup;
  * if the image is doing a CRC calculation before programming the PMU
  * for HT availability, it could take a couple hundred ms more, so
@@ -512,6 +509,8 @@ enum brcmf_sdio_frmtype {
 #define BCM4334_NVRAM_NAME             "brcm/brcmfmac4334-sdio.txt"
 #define BCM4335_FIRMWARE_NAME          "brcm/brcmfmac4335-sdio.bin"
 #define BCM4335_NVRAM_NAME             "brcm/brcmfmac4335-sdio.txt"
+#define BCM43362_FIRMWARE_NAME         "brcm/brcmfmac43362-sdio.bin"
+#define BCM43362_NVRAM_NAME            "brcm/brcmfmac43362-sdio.txt"
 #define BCM4339_FIRMWARE_NAME          "brcm/brcmfmac4339-sdio.bin"
 #define BCM4339_NVRAM_NAME             "brcm/brcmfmac4339-sdio.txt"
 
@@ -529,6 +528,8 @@ MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME);
 MODULE_FIRMWARE(BCM4334_NVRAM_NAME);
 MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME);
 MODULE_FIRMWARE(BCM4335_NVRAM_NAME);
+MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME);
+MODULE_FIRMWARE(BCM43362_NVRAM_NAME);
 MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME);
 MODULE_FIRMWARE(BCM4339_NVRAM_NAME);
 
@@ -555,11 +556,12 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = {
        { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
        { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
        { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
+       { BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
        { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }
 };
 
 
-static const struct firmware *brcmf_sdbrcm_get_fw(struct brcmf_sdio *bus,
+static const struct firmware *brcmf_sdio_get_fw(struct brcmf_sdio *bus,
                                                  enum brcmf_firmware_type type)
 {
        const struct firmware *fw;
@@ -624,8 +626,8 @@ r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
        u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
        int ret;
 
-       *regvar = brcmf_sdio_regrl(bus->sdiodev,
-                                  bus->ci->c_inf[idx].base + offset, &ret);
+       *regvar = brcmf_sdiod_regrl(bus->sdiodev,
+                                   bus->ci->c_inf[idx].base + offset, &ret);
 
        return ret;
 }
@@ -636,15 +638,15 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
        u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
        int ret;
 
-       brcmf_sdio_regwl(bus->sdiodev,
-                        bus->ci->c_inf[idx].base + reg_offset,
-                        regval, &ret);
+       brcmf_sdiod_regwl(bus->sdiodev,
+                         bus->ci->c_inf[idx].base + reg_offset,
+                         regval, &ret);
 
        return ret;
 }
 
 static int
-brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on)
+brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 {
        u8 wr_val = 0, rd_val, cmp_val, bmask;
        int err = 0;
@@ -654,8 +656,8 @@ brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on)
 
        wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
        /* 1st KSO write goes to AOS wake up core if device is asleep  */
-       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-                        wr_val, &err);
+       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+                         wr_val, &err);
        if (err) {
                brcmf_err("SDIO_AOS KSO write error: %d\n", err);
                return err;
@@ -685,15 +687,15 @@ brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on)
                 * just one write attempt may fail,
                 * read it back until it matches written value
                 */
-               rd_val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-                                         &err);
+               rd_val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+                                          &err);
                if (((rd_val & bmask) == cmp_val) && !err)
                        break;
                brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n",
                          try_cnt, MAX_KSO_ATTEMPTS, err);
                udelay(KSO_WAIT_US);
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-                                wr_val, &err);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+                                 wr_val, &err);
        } while (try_cnt++ < MAX_KSO_ATTEMPTS);
 
        return err;
@@ -704,7 +706,7 @@ brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on)
 #define HOSTINTMASK            (I_HMB_SW_MASK | I_CHIPACTIVE)
 
 /* Turn backplane clock on or off */
-static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
+static int brcmf_sdio_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 {
        int err;
        u8 clkctl, clkreq, devctl;
@@ -724,16 +726,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
                clkreq =
                    bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
 
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-                                clkreq, &err);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+                                 clkreq, &err);
                if (err) {
                        brcmf_err("HT Avail request error: %d\n", err);
                        return -EBADE;
                }
 
                /* Check current status */
-               clkctl = brcmf_sdio_regrb(bus->sdiodev,
-                                         SBSDIO_FUNC1_CHIPCLKCSR, &err);
+               clkctl = brcmf_sdiod_regrb(bus->sdiodev,
+                                          SBSDIO_FUNC1_CHIPCLKCSR, &err);
                if (err) {
                        brcmf_err("HT Avail read error: %d\n", err);
                        return -EBADE;
@@ -742,8 +744,8 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
                /* Go to pending and await interrupt if appropriate */
                if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
                        /* Allow only clock-available interrupt */
-                       devctl = brcmf_sdio_regrb(bus->sdiodev,
-                                                 SBSDIO_DEVICE_CTL, &err);
+                       devctl = brcmf_sdiod_regrb(bus->sdiodev,
+                                                  SBSDIO_DEVICE_CTL, &err);
                        if (err) {
                                brcmf_err("Devctl error setting CA: %d\n",
                                          err);
@@ -751,28 +753,28 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
                        }
 
                        devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
-                       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-                                        devctl, &err);
+                       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+                                         devctl, &err);
                        brcmf_dbg(SDIO, "CLKCTL: set PENDING\n");
                        bus->clkstate = CLK_PENDING;
 
                        return 0;
                } else if (bus->clkstate == CLK_PENDING) {
                        /* Cancel CA-only interrupt filter */
-                       devctl = brcmf_sdio_regrb(bus->sdiodev,
-                                                 SBSDIO_DEVICE_CTL, &err);
+                       devctl = brcmf_sdiod_regrb(bus->sdiodev,
+                                                  SBSDIO_DEVICE_CTL, &err);
                        devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-                       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-                                        devctl, &err);
+                       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+                                         devctl, &err);
                }
 
                /* Otherwise, wait here (polling) for HT Avail */
                timeout = jiffies +
                          msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000);
                while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
-                       clkctl = brcmf_sdio_regrb(bus->sdiodev,
-                                                 SBSDIO_FUNC1_CHIPCLKCSR,
-                                                 &err);
+                       clkctl = brcmf_sdiod_regrb(bus->sdiodev,
+                                                  SBSDIO_FUNC1_CHIPCLKCSR,
+                                                  &err);
                        if (time_after(jiffies, timeout))
                                break;
                        else
@@ -805,16 +807,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 
                if (bus->clkstate == CLK_PENDING) {
                        /* Cancel CA-only interrupt filter */
-                       devctl = brcmf_sdio_regrb(bus->sdiodev,
-                                                 SBSDIO_DEVICE_CTL, &err);
+                       devctl = brcmf_sdiod_regrb(bus->sdiodev,
+                                                  SBSDIO_DEVICE_CTL, &err);
                        devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-                       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-                                        devctl, &err);
+                       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+                                         devctl, &err);
                }
 
                bus->clkstate = CLK_SDONLY;
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-                                clkreq, &err);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+                                 clkreq, &err);
                brcmf_dbg(SDIO, "CLKCTL: turned OFF\n");
                if (err) {
                        brcmf_err("Failed access turning clock off: %d\n",
@@ -826,7 +828,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 }
 
 /* Change idle/active SD state */
-static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on)
+static int brcmf_sdio_sdclk(struct brcmf_sdio *bus, bool on)
 {
        brcmf_dbg(SDIO, "Enter\n");
 
@@ -839,7 +841,7 @@ static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on)
 }
 
 /* Transition SD and backplane clock readiness */
-static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
+static int brcmf_sdio_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
 {
 #ifdef DEBUG
        uint oldstate = bus->clkstate;
@@ -850,7 +852,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
        /* Early exit if we're already there */
        if (bus->clkstate == target) {
                if (target == CLK_AVAIL) {
-                       brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+                       brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
                        bus->activity = true;
                }
                return 0;
@@ -860,32 +862,32 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
        case CLK_AVAIL:
                /* Make sure SD clock is available */
                if (bus->clkstate == CLK_NONE)
-                       brcmf_sdbrcm_sdclk(bus, true);
+                       brcmf_sdio_sdclk(bus, true);
                /* Now request HT Avail on the backplane */
-               brcmf_sdbrcm_htclk(bus, true, pendok);
-               brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+               brcmf_sdio_htclk(bus, true, pendok);
+               brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
                bus->activity = true;
                break;
 
        case CLK_SDONLY:
                /* Remove HT request, or bring up SD clock */
                if (bus->clkstate == CLK_NONE)
-                       brcmf_sdbrcm_sdclk(bus, true);
+                       brcmf_sdio_sdclk(bus, true);
                else if (bus->clkstate == CLK_AVAIL)
-                       brcmf_sdbrcm_htclk(bus, false, false);
+                       brcmf_sdio_htclk(bus, false, false);
                else
                        brcmf_err("request for %d -> %d\n",
                                  bus->clkstate, target);
-               brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+               brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
                break;
 
        case CLK_NONE:
                /* Make sure to remove HT request */
                if (bus->clkstate == CLK_AVAIL)
-                       brcmf_sdbrcm_htclk(bus, false, false);
+                       brcmf_sdio_htclk(bus, false, false);
                /* Now remove the SD clock */
-               brcmf_sdbrcm_sdclk(bus, false);
-               brcmf_sdbrcm_wd_timer(bus, 0);
+               brcmf_sdio_sdclk(bus, false);
+               brcmf_sdio_wd_timer(bus, 0);
                break;
        }
 #ifdef DEBUG
@@ -896,7 +898,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
 }
 
 static int
-brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
+brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
 {
        int err = 0;
        brcmf_dbg(TRACE, "Enter\n");
@@ -919,13 +921,13 @@ brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
                            brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
                            data_ok(bus)))
                                 return -EBUSY;
-                       err = brcmf_sdbrcm_kso_control(bus, false);
+                       err = brcmf_sdio_kso_control(bus, false);
                        /* disable watchdog */
                        if (!err)
-                               brcmf_sdbrcm_wd_timer(bus, 0);
+                               brcmf_sdio_wd_timer(bus, 0);
                } else {
                        bus->idlecount = 0;
-                       err = brcmf_sdbrcm_kso_control(bus, true);
+                       err = brcmf_sdio_kso_control(bus, true);
                }
                if (!err) {
                        /* Change state */
@@ -943,16 +945,16 @@ end:
        /* control clocks */
        if (sleep) {
                if (!bus->sr_enabled)
-                       brcmf_sdbrcm_clkctl(bus, CLK_NONE, pendok);
+                       brcmf_sdio_clkctl(bus, CLK_NONE, pendok);
        } else {
-               brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, pendok);
+               brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok);
        }
 
        return err;
 
 }
 
-static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
+static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
 {
        u32 intstatus = 0;
        u32 hmb_data;
@@ -1028,7 +1030,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
        return intstatus;
 }
 
-static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
+static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
 {
        uint retries = 0;
        u16 lastrbc;
@@ -1040,18 +1042,18 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
                  rtx ? ", send NAK" : "");
 
        if (abort)
-               brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
+               brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
 
-       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
-                        SFC_RF_TERM, &err);
+       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
+                         SFC_RF_TERM, &err);
        bus->sdcnt.f1regdata++;
 
        /* Wait until the packet has been flushed (device/FIFO stable) */
        for (lastrbc = retries = 0xffff; retries > 0; retries--) {
-               hi = brcmf_sdio_regrb(bus->sdiodev,
-                                     SBSDIO_FUNC1_RFRAMEBCHI, &err);
-               lo = brcmf_sdio_regrb(bus->sdiodev,
-                                     SBSDIO_FUNC1_RFRAMEBCLO, &err);
+               hi = brcmf_sdiod_regrb(bus->sdiodev,
+                                      SBSDIO_FUNC1_RFRAMEBCHI, &err);
+               lo = brcmf_sdiod_regrb(bus->sdiodev,
+                                      SBSDIO_FUNC1_RFRAMEBCLO, &err);
                bus->sdcnt.f1regdata += 2;
 
                if ((hi == 0) && (lo == 0))
@@ -1088,7 +1090,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
 }
 
 /* return total length of buffer chain */
-static uint brcmf_sdbrcm_glom_len(struct brcmf_sdio *bus)
+static uint brcmf_sdio_glom_len(struct brcmf_sdio *bus)
 {
        struct sk_buff *p;
        uint total;
@@ -1099,7 +1101,7 @@ static uint brcmf_sdbrcm_glom_len(struct brcmf_sdio *bus)
        return total;
 }
 
-static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
+static void brcmf_sdio_free_glom(struct brcmf_sdio *bus)
 {
        struct sk_buff *cur, *next;
 
@@ -1187,7 +1189,7 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
        if ((u16)(~(len ^ checksum))) {
                brcmf_err("HW header checksum error\n");
                bus->sdcnt.rx_badhdr++;
-               brcmf_sdbrcm_rxfail(bus, false, false);
+               brcmf_sdio_rxfail(bus, false, false);
                return -EIO;
        }
        if (len < SDPCM_HDRLEN) {
@@ -1219,7 +1221,7 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
            type != BRCMF_SDIO_FT_SUPER) {
                brcmf_err("HW header length too long\n");
                bus->sdcnt.rx_toolong++;
-               brcmf_sdbrcm_rxfail(bus, false, false);
+               brcmf_sdio_rxfail(bus, false, false);
                rd->len = 0;
                return -EPROTO;
        }
@@ -1238,7 +1240,7 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
        if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) {
                brcmf_err("seq %d: bad data offset\n", rx_seq);
                bus->sdcnt.rx_badhdr++;
-               brcmf_sdbrcm_rxfail(bus, false, false);
+               brcmf_sdio_rxfail(bus, false, false);
                rd->len = 0;
                return -ENXIO;
        }
@@ -1311,7 +1313,7 @@ static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header,
        trace_brcmf_sdpcm_hdr(SDPCM_TX + !!(bus->txglom), header);
 }
 
-static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
+static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 {
        u16 dlen, totlen;
        u8 *dptr, num = 0;
@@ -1391,7 +1393,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
                        }
                        pfirst = pnext = NULL;
                } else {
-                       brcmf_sdbrcm_free_glom(bus);
+                       brcmf_sdio_free_glom(bus);
                        num = 0;
                }
 
@@ -1414,16 +1416,15 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
                }
 
                pfirst = skb_peek(&bus->glom);
-               dlen = (u16) brcmf_sdbrcm_glom_len(bus);
+               dlen = (u16) brcmf_sdio_glom_len(bus);
 
                /* Do an SDIO read for the superframe.  Configurable iovar to
                 * read directly into the chained packet, or allocate a large
                 * packet and and copy into the chain.
                 */
                sdio_claim_host(bus->sdiodev->func[1]);
-               errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
-                               bus->sdiodev->sbwad,
-                               SDIO_FUNC_2, F2SYNC, &bus->glom, dlen);
+               errcode = brcmf_sdiod_recv_chain(bus->sdiodev,
+                                                &bus->glom, dlen);
                sdio_release_host(bus->sdiodev->func[1]);
                bus->sdcnt.f2rxdata++;
 
@@ -1434,12 +1435,12 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 
                        sdio_claim_host(bus->sdiodev->func[1]);
                        if (bus->glomerr++ < 3) {
-                               brcmf_sdbrcm_rxfail(bus, true, true);
+                               brcmf_sdio_rxfail(bus, true, true);
                        } else {
                                bus->glomerr = 0;
-                               brcmf_sdbrcm_rxfail(bus, true, false);
+                               brcmf_sdio_rxfail(bus, true, false);
                                bus->sdcnt.rxglomfail++;
-                               brcmf_sdbrcm_free_glom(bus);
+                               brcmf_sdio_free_glom(bus);
                        }
                        sdio_release_host(bus->sdiodev->func[1]);
                        return 0;
@@ -1487,12 +1488,12 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
                        if (bus->glomerr++ < 3) {
                                /* Restore superframe header space */
                                skb_push(pfirst, sfdoff);
-                               brcmf_sdbrcm_rxfail(bus, true, true);
+                               brcmf_sdio_rxfail(bus, true, true);
                        } else {
                                bus->glomerr = 0;
-                               brcmf_sdbrcm_rxfail(bus, true, false);
+                               brcmf_sdio_rxfail(bus, true, false);
                                bus->sdcnt.rxglomfail++;
-                               brcmf_sdbrcm_free_glom(bus);
+                               brcmf_sdio_free_glom(bus);
                        }
                        sdio_release_host(bus->sdiodev->func[1]);
                        bus->cur_read.len = 0;
@@ -1536,8 +1537,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
        return num;
 }
 
-static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition,
-                                       bool *pending)
+static int brcmf_sdio_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition,
+                                    bool *pending)
 {
        DECLARE_WAITQUEUE(wait, current);
        int timeout = msecs_to_jiffies(DCMD_RESP_TIMEOUT);
@@ -1558,7 +1559,7 @@ static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition,
        return timeout;
 }
 
-static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_sdio *bus)
+static int brcmf_sdio_dcmd_resp_wake(struct brcmf_sdio *bus)
 {
        if (waitqueue_active(&bus->dcmd_resp_wait))
                wake_up_interruptible(&bus->dcmd_resp_wait);
@@ -1566,7 +1567,7 @@ static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_sdio *bus)
        return 0;
 }
 static void
-brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
+brcmf_sdio_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
 {
        uint rdlen, pad;
        u8 *buf = NULL, *rbuf;
@@ -1604,7 +1605,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
        if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) {
                brcmf_err("%d-byte control read exceeds %d-byte buffer\n",
                          rdlen, bus->sdiodev->bus_if->maxctl);
-               brcmf_sdbrcm_rxfail(bus, false, false);
+               brcmf_sdio_rxfail(bus, false, false);
                goto done;
        }
 
@@ -1612,15 +1613,12 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
                brcmf_err("%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
                          len, len - doff, bus->sdiodev->bus_if->maxctl);
                bus->sdcnt.rx_toolong++;
-               brcmf_sdbrcm_rxfail(bus, false, false);
+               brcmf_sdio_rxfail(bus, false, false);
                goto done;
        }
 
        /* Read remain of frame body */
-       sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
-                               bus->sdiodev->sbwad,
-                               SDIO_FUNC_2,
-                               F2SYNC, rbuf, rdlen);
+       sdret = brcmf_sdiod_recv_buf(bus->sdiodev, rbuf, rdlen);
        bus->sdcnt.f2rxdata++;
 
        /* Control frame failures need retransmission */
@@ -1628,7 +1626,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
                brcmf_err("read %d control bytes failed: %d\n",
                          rdlen, sdret);
                bus->sdcnt.rxc_errors++;
-               brcmf_sdbrcm_rxfail(bus, true, true);
+               brcmf_sdio_rxfail(bus, true, true);
                goto done;
        } else
                memcpy(buf + BRCMF_FIRSTREAD, rbuf, rdlen);
@@ -1653,11 +1651,11 @@ gotpkt:
 
 done:
        /* Awake any waiters */
-       brcmf_sdbrcm_dcmd_resp_wake(bus);
+       brcmf_sdio_dcmd_resp_wake(bus);
 }
 
 /* Pad read to blocksize for efficiency */
-static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen)
+static void brcmf_sdio_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen)
 {
        if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) {
                *pad = bus->blocksize - (*rdlen % bus->blocksize);
@@ -1694,7 +1692,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                        u8 cnt;
                        brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n",
                                  bus->glomd, skb_peek(&bus->glom));
-                       cnt = brcmf_sdbrcm_rxglom(bus, rd->seq_num);
+                       cnt = brcmf_sdio_rxglom(bus, rd->seq_num);
                        brcmf_dbg(GLOM, "rxglom returned %d\n", cnt);
                        rd->seq_num += cnt - 1;
                        rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
@@ -1705,17 +1703,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                /* read header first for unknow frame length */
                sdio_claim_host(bus->sdiodev->func[1]);
                if (!rd->len) {
-                       ret = brcmf_sdcard_recv_buf(bus->sdiodev,
-                                                     bus->sdiodev->sbwad,
-                                                     SDIO_FUNC_2, F2SYNC,
-                                                     bus->rxhdr,
-                                                     BRCMF_FIRSTREAD);
+                       ret = brcmf_sdiod_recv_buf(bus->sdiodev,
+                                                  bus->rxhdr, BRCMF_FIRSTREAD);
                        bus->sdcnt.f2rxhdrs++;
                        if (ret < 0) {
                                brcmf_err("RXHEADER FAILED: %d\n",
                                          ret);
                                bus->sdcnt.rx_hdrfail++;
-                               brcmf_sdbrcm_rxfail(bus, true, true);
+                               brcmf_sdio_rxfail(bus, true, true);
                                sdio_release_host(bus->sdiodev->func[1]);
                                continue;
                        }
@@ -1734,9 +1729,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                        }
 
                        if (rd->channel == SDPCM_CONTROL_CHANNEL) {
-                               brcmf_sdbrcm_read_control(bus, bus->rxhdr,
-                                                         rd->len,
-                                                         rd->dat_offset);
+                               brcmf_sdio_read_control(bus, bus->rxhdr,
+                                                       rd->len,
+                                                       rd->dat_offset);
                                /* prepare the descriptor for the next read */
                                rd->len = rd->len_nxtfrm << 4;
                                rd->len_nxtfrm = 0;
@@ -1750,14 +1745,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                        head_read = BRCMF_FIRSTREAD;
                }
 
-               brcmf_pad(bus, &pad, &rd->len_left);
+               brcmf_sdio_pad(bus, &pad, &rd->len_left);
 
                pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read +
                                            bus->head_align);
                if (!pkt) {
                        /* Give up on data, request rtx of events */
                        brcmf_err("brcmu_pkt_buf_get_skb failed\n");
-                       brcmf_sdbrcm_rxfail(bus, false,
+                       brcmf_sdio_rxfail(bus, false,
                                            RETRYCHAN(rd->channel));
                        sdio_release_host(bus->sdiodev->func[1]);
                        continue;
@@ -1765,8 +1760,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                skb_pull(pkt, head_read);
                pkt_align(pkt, rd->len_left, bus->head_align);
 
-               ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
-                                             SDIO_FUNC_2, F2SYNC, pkt);
+               ret = brcmf_sdiod_recv_pkt(bus->sdiodev, pkt);
                bus->sdcnt.f2rxdata++;
                sdio_release_host(bus->sdiodev->func[1]);
 
@@ -1775,7 +1769,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                                  rd->len, rd->channel, ret);
                        brcmu_pkt_buf_free_skb(pkt);
                        sdio_claim_host(bus->sdiodev->func[1]);
-                       brcmf_sdbrcm_rxfail(bus, true,
+                       brcmf_sdio_rxfail(bus, true,
                                            RETRYCHAN(rd->channel));
                        sdio_release_host(bus->sdiodev->func[1]);
                        continue;
@@ -1800,7 +1794,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                                          rd->len,
                                          roundup(rd_new.len, 16) >> 4);
                                rd->len = 0;
-                               brcmf_sdbrcm_rxfail(bus, true, true);
+                               brcmf_sdio_rxfail(bus, true, true);
                                sdio_release_host(bus->sdiodev->func[1]);
                                brcmu_pkt_buf_free_skb(pkt);
                                continue;
@@ -1822,7 +1816,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                                /* Force retry w/normal header read */
                                rd->len = 0;
                                sdio_claim_host(bus->sdiodev->func[1]);
-                               brcmf_sdbrcm_rxfail(bus, false, true);
+                               brcmf_sdio_rxfail(bus, false, true);
                                sdio_release_host(bus->sdiodev->func[1]);
                                brcmu_pkt_buf_free_skb(pkt);
                                continue;
@@ -1847,7 +1841,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                                brcmf_err("%s: glom superframe w/o "
                                          "descriptor!\n", __func__);
                                sdio_claim_host(bus->sdiodev->func[1]);
-                               brcmf_sdbrcm_rxfail(bus, false, false);
+                               brcmf_sdio_rxfail(bus, false, false);
                                sdio_release_host(bus->sdiodev->func[1]);
                        }
                        /* prepare the descriptor for the next read */
@@ -1891,7 +1885,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 }
 
 static void
-brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
+brcmf_sdio_wait_event_wakeup(struct brcmf_sdio *bus)
 {
        if (waitqueue_active(&bus->ctrl_wait))
                wake_up_interruptible(&bus->ctrl_wait);
@@ -2107,8 +2101,8 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq)
 
 /* Writes a HW/SW header into the packet and sends it. */
 /* Assumes: (a) header space already there, (b) caller holds lock */
-static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
-                             uint chan)
+static int brcmf_sdio_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
+                           uint chan)
 {
        int ret;
        int i;
@@ -2121,8 +2115,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
                goto done;
 
        sdio_claim_host(bus->sdiodev->func[1]);
-       ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
-                                   SDIO_FUNC_2, F2SYNC, pktq);
+       ret = brcmf_sdiod_send_pkt(bus->sdiodev, pktq);
        bus->sdcnt.f2txdata++;
 
        if (ret < 0) {
@@ -2131,17 +2124,17 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
                          ret);
                bus->sdcnt.tx_sderrs++;
 
-               brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
-                                SFC_WF_TERM, NULL);
+               brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
+                                 SFC_WF_TERM, NULL);
                bus->sdcnt.f1regdata++;
 
                for (i = 0; i < 3; i++) {
                        u8 hi, lo;
-                       hi = brcmf_sdio_regrb(bus->sdiodev,
-                                             SBSDIO_FUNC1_WFRAMEBCHI, NULL);
-                       lo = brcmf_sdio_regrb(bus->sdiodev,
-                                             SBSDIO_FUNC1_WFRAMEBCLO, NULL);
+                       hi = brcmf_sdiod_regrb(bus->sdiodev,
+                                              SBSDIO_FUNC1_WFRAMEBCHI, NULL);
+                       lo = brcmf_sdiod_regrb(bus->sdiodev,
+                                              SBSDIO_FUNC1_WFRAMEBCLO, NULL);
                        bus->sdcnt.f1regdata += 2;
                        if ((hi == 0) && (lo == 0))
                                break;
@@ -2160,7 +2153,7 @@ done:
        return ret;
 }
 
-static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
+static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes)
 {
        struct sk_buff *pkt;
        struct sk_buff_head pktq;
@@ -2194,7 +2187,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
                if (i == 0)
                        break;
 
-               ret = brcmf_sdbrcm_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL);
+               ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL);
                cnt += i;
 
                /* In poll mode, need to check for other events */
@@ -2223,7 +2216,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
        return cnt;
 }
 
-static void brcmf_sdbrcm_bus_stop(struct device *dev)
+static void brcmf_sdio_bus_stop(struct device *dev)
 {
        u32 local_hostintmask;
        u8 saveclk;
@@ -2243,7 +2236,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
        sdio_claim_host(bus->sdiodev->func[1]);
 
        /* Enable clock for device interrupts */
-       brcmf_sdbrcm_bus_sleep(bus, false, false);
+       brcmf_sdio_bus_sleep(bus, false, false);
 
        /* Disable and clear interrupts at the chip level also */
        w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
@@ -2254,26 +2247,25 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
        bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
 
        /* Force clocks on backplane to be sure F2 interrupt propagates */
-       saveclk = brcmf_sdio_regrb(bus->sdiodev,
-                                  SBSDIO_FUNC1_CHIPCLKCSR, &err);
+       saveclk = brcmf_sdiod_regrb(bus->sdiodev,
+                                   SBSDIO_FUNC1_CHIPCLKCSR, &err);
        if (!err) {
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-                                (saveclk | SBSDIO_FORCE_HT), &err);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+                                 (saveclk | SBSDIO_FORCE_HT), &err);
        }
        if (err)
                brcmf_err("Failed to force clock for F2: err %d\n", err);
 
        /* Turn off the bus (F2), free any pending packets */
        brcmf_dbg(INTR, "disable SDIO interrupts\n");
-       brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, SDIO_FUNC_ENABLE_1,
-                        NULL);
+       sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
 
        /* Clear any pending interrupts now that F2 is disabled */
        w_sdreg32(bus, local_hostintmask,
                  offsetof(struct sdpcmd_regs, intstatus));
 
        /* Turn off the backplane clock (only) */
-       brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+       brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
        sdio_release_host(bus->sdiodev->func[1]);
 
        /* Clear the data packet queues */
@@ -2282,20 +2274,20 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
        /* Clear any held glomming stuff */
        if (bus->glomd)
                brcmu_pkt_buf_free_skb(bus->glomd);
-       brcmf_sdbrcm_free_glom(bus);
+       brcmf_sdio_free_glom(bus);
 
        /* Clear rx control and wake any waiters */
        spin_lock_bh(&bus->rxctl_lock);
        bus->rxlen = 0;
        spin_unlock_bh(&bus->rxctl_lock);
-       brcmf_sdbrcm_dcmd_resp_wake(bus);
+       brcmf_sdio_dcmd_resp_wake(bus);
 
        /* Reset some F2 state stuff */
        bus->rxskip = false;
        bus->tx_seq = bus->rx_seq = 0;
 }
 
-static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
+static inline void brcmf_sdio_clrintr(struct brcmf_sdio *bus)
 {
        unsigned long flags;
 
@@ -2320,7 +2312,7 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
        addr = bus->ci->c_inf[idx].base +
               offsetof(struct sdpcmd_regs, intstatus);
 
-       ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, false);
+       val = brcmf_sdiod_regrl(bus->sdiodev, addr, &ret);
        bus->sdcnt.f1regdata++;
        if (ret != 0)
                val = 0;
@@ -2330,7 +2322,7 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
 
        /* Clear interrupts */
        if (val) {
-               ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, true);
+               brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret);
                bus->sdcnt.f1regdata++;
        }
 
@@ -2344,7 +2336,7 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
        return ret;
 }
 
-static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
+static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
 {
        u32 newstatus = 0;
        unsigned long intstatus;
@@ -2363,8 +2355,8 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 
 #ifdef DEBUG
                /* Check for inconsistent device control */
-               devctl = brcmf_sdio_regrb(bus->sdiodev,
-                                         SBSDIO_DEVICE_CTL, &err);
+               devctl = brcmf_sdiod_regrb(bus->sdiodev,
+                                          SBSDIO_DEVICE_CTL, &err);
                if (err) {
                        brcmf_err("error reading DEVCTL: %d\n", err);
                        bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
@@ -2372,8 +2364,8 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 #endif                         /* DEBUG */
 
                /* Read CSR, if clock on switch to AVAIL, else ignore */
-               clkctl = brcmf_sdio_regrb(bus->sdiodev,
-                                         SBSDIO_FUNC1_CHIPCLKCSR, &err);
+               clkctl = brcmf_sdiod_regrb(bus->sdiodev,
+                                          SBSDIO_FUNC1_CHIPCLKCSR, &err);
                if (err) {
                        brcmf_err("error reading CSR: %d\n",
                                  err);
@@ -2384,16 +2376,16 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                          devctl, clkctl);
 
                if (SBSDIO_HTAV(clkctl)) {
-                       devctl = brcmf_sdio_regrb(bus->sdiodev,
-                                                 SBSDIO_DEVICE_CTL, &err);
+                       devctl = brcmf_sdiod_regrb(bus->sdiodev,
+                                                  SBSDIO_DEVICE_CTL, &err);
                        if (err) {
                                brcmf_err("error reading DEVCTL: %d\n",
                                          err);
                                bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
                        }
                        devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-                       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-                                        devctl, &err);
+                       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+                                         devctl, &err);
                        if (err) {
                                brcmf_err("error writing DEVCTL: %d\n",
                                          err);
@@ -2404,7 +2396,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
        }
 
        /* Make sure backplane clock is on */
-       brcmf_sdbrcm_bus_sleep(bus, false, true);
+       brcmf_sdio_bus_sleep(bus, false, true);
 
        /* Pending interrupt indicates new device status */
        if (atomic_read(&bus->ipend) > 0) {
@@ -2435,7 +2427,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
        /* Handle host mailbox indication */
        if (intstatus & I_HMB_HOST_INT) {
                intstatus &= ~I_HMB_HOST_INT;
-               intstatus |= brcmf_sdbrcm_hostmail(bus);
+               intstatus |= brcmf_sdio_hostmail(bus);
        }
 
        sdio_release_host(bus->sdiodev->func[1]);
@@ -2480,16 +2472,15 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                        set_bit(n, (unsigned long *)&bus->intstatus.counter);
        }
 
-       brcmf_sdbrcm_clrintr(bus);
+       brcmf_sdio_clrintr(bus);
 
        if (data_ok(bus) && bus->ctrl_frame_stat &&
                (bus->clkstate == CLK_AVAIL)) {
                int i;
 
                sdio_claim_host(bus->sdiodev->func[1]);
-               err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
-                       SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf,
-                       (u32) bus->ctrl_frame_len);
+               err = brcmf_sdiod_send_buf(bus->sdiodev, bus->ctrl_frame_buf,
+                                          (u32)bus->ctrl_frame_len);
 
                if (err < 0) {
                        /* On failure, abort the command and
@@ -2498,20 +2489,20 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                                  err);
                        bus->sdcnt.tx_sderrs++;
 
-                       brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
+                       brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
 
-                       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
-                                        SFC_WF_TERM, &err);
+                       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
+                                         SFC_WF_TERM, &err);
                        bus->sdcnt.f1regdata++;
 
                        for (i = 0; i < 3; i++) {
                                u8 hi, lo;
-                               hi = brcmf_sdio_regrb(bus->sdiodev,
-                                                     SBSDIO_FUNC1_WFRAMEBCHI,
-                                                     &err);
-                               lo = brcmf_sdio_regrb(bus->sdiodev,
-                                                     SBSDIO_FUNC1_WFRAMEBCLO,
-                                                     &err);
+                               hi = brcmf_sdiod_regrb(bus->sdiodev,
+                                                      SBSDIO_FUNC1_WFRAMEBCHI,
+                                                      &err);
+                               lo = brcmf_sdiod_regrb(bus->sdiodev,
+                                                      SBSDIO_FUNC1_WFRAMEBCLO,
+                                                      &err);
                                bus->sdcnt.f1regdata += 2;
                                if ((hi == 0) && (lo == 0))
                                        break;
@@ -2522,7 +2513,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                }
                sdio_release_host(bus->sdiodev->func[1]);
                bus->ctrl_frame_stat = false;
-               brcmf_sdbrcm_wait_event_wakeup(bus);
+               brcmf_sdio_wait_event_wakeup(bus);
        }
        /* Send queued frames (limit 1 if rx may still be pending) */
        else if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) &&
@@ -2530,7 +2521,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                 && data_ok(bus)) {
                framecnt = bus->rxpending ? min(txlimit, bus->txminmax) :
                                            txlimit;
-               framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt);
+               framecnt = brcmf_sdio_sendfromq(bus, framecnt);
                txlimit -= framecnt;
        }
 
@@ -2552,12 +2543,12 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                bus->activity = false;
                brcmf_dbg(SDIO, "idle state\n");
                sdio_claim_host(bus->sdiodev->func[1]);
-               brcmf_sdbrcm_bus_sleep(bus, true, false);
+               brcmf_sdio_bus_sleep(bus, true, false);
                sdio_release_host(bus->sdiodev->func[1]);
        }
 }
 
-static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev)
+static struct pktq *brcmf_sdio_bus_gettxq(struct device *dev)
 {
        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
        struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
@@ -2566,7 +2557,7 @@ static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev)
        return &bus->txq;
 }
 
-static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
+static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt)
 {
        int ret = -EBADE;
        uint datalen, prec;
@@ -2622,7 +2613,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
 #ifdef DEBUG
 #define CONSOLE_LINE_MAX       192
 
-static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
+static int brcmf_sdio_readconsole(struct brcmf_sdio *bus)
 {
        struct brcmf_console *c = &bus->console;
        u8 line[CONSOLE_LINE_MAX], ch;
@@ -2635,8 +2626,8 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
 
        /* Read console log struct */
        addr = bus->console_addr + offsetof(struct rte_console, log_le);
-       rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le,
-                             sizeof(c->log_le));
+       rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le,
+                              sizeof(c->log_le));
        if (rv < 0)
                return rv;
 
@@ -2661,7 +2652,7 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
 
        /* Read the console buffer */
        addr = le32_to_cpu(c->log_le.buf);
-       rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize);
+       rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize);
        if (rv < 0)
                return rv;
 
@@ -2699,14 +2690,13 @@ break2:
 }
 #endif                         /* DEBUG */
 
-static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
+static int brcmf_sdio_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
 {
        int i;
        int ret;
 
        bus->ctrl_frame_stat = false;
-       ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
-                                   SDIO_FUNC_2, F2SYNC, frame, len);
+       ret = brcmf_sdiod_send_buf(bus->sdiodev, frame, len);
 
        if (ret < 0) {
                /* On failure, abort the command and terminate the frame */
@@ -2714,18 +2704,18 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
                          ret);
                bus->sdcnt.tx_sderrs++;
 
-               brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
+               brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
 
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
-                                SFC_WF_TERM, NULL);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
+                                 SFC_WF_TERM, NULL);
                bus->sdcnt.f1regdata++;
 
                for (i = 0; i < 3; i++) {
                        u8 hi, lo;
-                       hi = brcmf_sdio_regrb(bus->sdiodev,
-                                             SBSDIO_FUNC1_WFRAMEBCHI, NULL);
-                       lo = brcmf_sdio_regrb(bus->sdiodev,
-                                             SBSDIO_FUNC1_WFRAMEBCLO, NULL);
+                       hi = brcmf_sdiod_regrb(bus->sdiodev,
+                                              SBSDIO_FUNC1_WFRAMEBCHI, NULL);
+                       lo = brcmf_sdiod_regrb(bus->sdiodev,
+                                              SBSDIO_FUNC1_WFRAMEBCLO, NULL);
                        bus->sdcnt.f1regdata += 2;
                        if (hi == 0 && lo == 0)
                                break;
@@ -2739,7 +2729,7 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
 }
 
 static int
-brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
+brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 {
        u8 *frame;
        u16 len, pad;
@@ -2783,7 +2773,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 
        /* Make sure backplane clock is on */
        sdio_claim_host(bus->sdiodev->func[1]);
-       brcmf_sdbrcm_bus_sleep(bus, false, false);
+       brcmf_sdio_bus_sleep(bus, false, false);
        sdio_release_host(bus->sdiodev->func[1]);
 
        hd_info.len = (u16)msglen;
@@ -2827,7 +2817,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 
                do {
                        sdio_claim_host(bus->sdiodev->func[1]);
-                       ret = brcmf_tx_frame(bus, frame, len);
+                       ret = brcmf_sdio_tx_frame(bus, frame, len);
                        sdio_release_host(bus->sdiodev->func[1]);
                } while (ret < 0 && retries++ < TXRETRIES);
        }
@@ -2837,7 +2827,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
                bus->activity = false;
                sdio_claim_host(bus->sdiodev->func[1]);
                brcmf_dbg(INFO, "idle\n");
-               brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
+               brcmf_sdio_clkctl(bus, CLK_NONE, true);
                sdio_release_host(bus->sdiodev->func[1]);
        }
 
@@ -2871,8 +2861,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
         * address of sdpcm_shared structure
         */
        sdio_claim_host(bus->sdiodev->func[1]);
-       brcmf_sdbrcm_bus_sleep(bus, false, false);
-       rv = brcmf_sdio_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
+       brcmf_sdio_bus_sleep(bus, false, false);
+       rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
        sdio_release_host(bus->sdiodev->func[1]);
        if (rv < 0)
                return rv;
@@ -2892,8 +2882,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
        }
 
        /* Read hndrte_shared structure */
-       rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
-                             sizeof(struct sdpcm_shared_le));
+       rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
+                              sizeof(struct sdpcm_shared_le));
        if (rv < 0)
                return rv;
 
@@ -2929,22 +2919,22 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
 
        /* obtain console information from device memory */
        addr = sh->console_addr + offsetof(struct rte_console, log_le);
-       rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
-                             (u8 *)&sh_val, sizeof(u32));
+       rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr,
+                              (u8 *)&sh_val, sizeof(u32));
        if (rv < 0)
                return rv;
        console_ptr = le32_to_cpu(sh_val);
 
        addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size);
-       rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
-                             (u8 *)&sh_val, sizeof(u32));
+       rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr,
+                              (u8 *)&sh_val, sizeof(u32));
        if (rv < 0)
                return rv;
        console_size = le32_to_cpu(sh_val);
 
        addr = sh->console_addr + offsetof(struct rte_console, log_le.idx);
-       rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
-                             (u8 *)&sh_val, sizeof(u32));
+       rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr,
+                              (u8 *)&sh_val, sizeof(u32));
        if (rv < 0)
                return rv;
        console_index = le32_to_cpu(sh_val);
@@ -2958,8 +2948,8 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
 
        /* obtain the console data from device */
        conbuf[console_size] = '\0';
-       rv = brcmf_sdio_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf,
-                             console_size);
+       rv = brcmf_sdiod_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf,
+                              console_size);
        if (rv < 0)
                goto done;
 
@@ -2996,8 +2986,8 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
                return 0;
        }
 
-       error = brcmf_sdio_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr,
-                                sizeof(struct brcmf_trap_info));
+       error = brcmf_sdiod_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr,
+                                 sizeof(struct brcmf_trap_info));
        if (error < 0)
                return error;
 
@@ -3040,14 +3030,14 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
 
        sdio_claim_host(bus->sdiodev->func[1]);
        if (sh->assert_file_addr != 0) {
-               error = brcmf_sdio_ramrw(bus->sdiodev, false,
-                                        sh->assert_file_addr, (u8 *)file, 80);
+               error = brcmf_sdiod_ramrw(bus->sdiodev, false,
+                                         sh->assert_file_addr, (u8 *)file, 80);
                if (error < 0)
                        return error;
        }
        if (sh->assert_exp_addr != 0) {
-               error = brcmf_sdio_ramrw(bus->sdiodev, false,
-                                        sh->assert_exp_addr, (u8 *)expr, 80);
+               error = brcmf_sdiod_ramrw(bus->sdiodev, false,
+                                         sh->assert_exp_addr, (u8 *)expr, 80);
                if (error < 0)
                        return error;
        }
@@ -3059,7 +3049,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
        return simple_read_from_buffer(data, count, &pos, buf, res);
 }
 
-static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
+static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
 {
        int error;
        struct sdpcm_shared sh;
@@ -3080,8 +3070,8 @@ static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
        return 0;
 }
 
-static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
-                                 size_t count, loff_t *ppos)
+static int brcmf_sdio_died_dump(struct brcmf_sdio *bus, char __user *data,
+                               size_t count, loff_t *ppos)
 {
        int error = 0;
        struct sdpcm_shared sh;
@@ -3122,7 +3112,7 @@ static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data,
        struct brcmf_sdio *bus = f->private_data;
        int res;
 
-       res = brcmf_sdbrcm_died_dump(bus, data, count, ppos);
+       res = brcmf_sdio_died_dump(bus, data, count, ppos);
        if (res > 0)
                *ppos += res;
        return (ssize_t)res;
@@ -3147,7 +3137,7 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
        brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt);
 }
 #else
-static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
+static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
 {
        return 0;
 }
@@ -3158,7 +3148,7 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
 #endif /* DEBUG */
 
 static int
-brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
+brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
 {
        int timeleft;
        uint rxlen = 0;
@@ -3171,7 +3161,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
        brcmf_dbg(TRACE, "Enter\n");
 
        /* Wait until control frame is available */
-       timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending);
+       timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending);
 
        spin_lock_bh(&bus->rxctl_lock);
        rxlen = bus->rxlen;
@@ -3188,13 +3178,13 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
                          rxlen, msglen);
        } else if (timeleft == 0) {
                brcmf_err("resumed on timeout\n");
-               brcmf_sdbrcm_checkdied(bus);
+               brcmf_sdio_checkdied(bus);
        } else if (pending) {
                brcmf_dbg(CTL, "cancelled\n");
                return -ERESTARTSYS;
        } else {
                brcmf_dbg(CTL, "resumed for unknown reason?\n");
-               brcmf_sdbrcm_checkdied(bus);
+               brcmf_sdio_checkdied(bus);
        }
 
        if (rxlen)
@@ -3205,7 +3195,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
        return rxlen ? (int)rxlen : -ETIMEDOUT;
 }
 
-static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
+static bool brcmf_sdio_download_state(struct brcmf_sdio *bus, bool enter)
 {
        struct chip_info *ci = bus->ci;
 
@@ -3230,7 +3220,7 @@ static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
        return true;
 }
 
-static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
+static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
 {
        const struct firmware *fw;
        int err;
@@ -3238,7 +3228,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
        int address;
        int len;
 
-       fw = brcmf_sdbrcm_get_fw(bus, BRCMF_FIRMWARE_BIN);
+       fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
        if (fw == NULL)
                return -ENOENT;
 
@@ -3252,8 +3242,8 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
        while (offset < fw->size) {
                len = ((offset + MEMBLOCK) < fw->size) ? MEMBLOCK :
                      fw->size - offset;
-               err = brcmf_sdio_ramrw(bus->sdiodev, true, address,
-                                      (u8 *)&fw->data[offset], len);
+               err = brcmf_sdiod_ramrw(bus->sdiodev, true, address,
+                                       (u8 *)&fw->data[offset], len);
                if (err) {
                        brcmf_err("error %d on writing %d membytes at 0x%08x\n",
                                  err, len, address);
@@ -3278,8 +3268,8 @@ failure:
  * by two NULs.
 */
 
-static int brcmf_process_nvram_vars(struct brcmf_sdio *bus,
-                                   const struct firmware *nv)
+static int brcmf_sdio_strip_nvram(struct brcmf_sdio *bus,
+                                 const struct firmware *nv)
 {
        char *varbuf;
        char *dp;
@@ -3343,44 +3333,48 @@ err:
        return ret;
 }
 
-static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus)
+static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus)
 {
        const struct firmware *nv;
        int ret;
 
-       nv = brcmf_sdbrcm_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
+       nv = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
        if (nv == NULL)
                return -ENOENT;
 
-       ret = brcmf_process_nvram_vars(bus, nv);
+       ret = brcmf_sdio_strip_nvram(bus, nv);
 
        release_firmware(nv);
 
        return ret;
 }
 
-static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
+static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
 {
-       int bcmerror = -1;
+       int bcmerror = -EFAULT;
+
+
+       sdio_claim_host(bus->sdiodev->func[1]);
+       brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
 
        /* Keep arm in reset */
-       if (!brcmf_sdbrcm_download_state(bus, true)) {
+       if (!brcmf_sdio_download_state(bus, true)) {
                brcmf_err("error placing ARM core in reset\n");
                goto err;
        }
 
-       if (brcmf_sdbrcm_download_code_file(bus)) {
+       if (brcmf_sdio_download_code_file(bus)) {
                brcmf_err("dongle image file download failed\n");
                goto err;
        }
 
-       if (brcmf_sdbrcm_download_nvram(bus)) {
+       if (brcmf_sdio_download_nvram(bus)) {
                brcmf_err("dongle nvram file download failed\n");
                goto err;
        }
 
        /* Take arm out of reset */
-       if (!brcmf_sdbrcm_download_state(bus, false)) {
+       if (!brcmf_sdio_download_state(bus, false)) {
                brcmf_err("error getting out of ARM core reset\n");
                goto err;
        }
@@ -3388,12 +3382,15 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
        bcmerror = 0;
 
 err:
+       brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
+       sdio_release_host(bus->sdiodev->func[1]);
        return bcmerror;
 }
 
-static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus)
+static bool brcmf_sdio_sr_capable(struct brcmf_sdio *bus)
 {
-       u32 addr, reg;
+       u32 addr, reg, pmu_cc3_mask = ~0;
+       int err;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -3401,49 +3398,61 @@ static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus)
        if (bus->ci->pmurev < 17)
                return false;
 
-       /* read PMU chipcontrol register 3*/
-       addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr);
-       brcmf_sdio_regwl(bus->sdiodev, addr, 3, NULL);
-       addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data);
-       reg = brcmf_sdio_regrl(bus->sdiodev, addr, NULL);
+       switch (bus->ci->chip) {
+       case BCM43241_CHIP_ID:
+       case BCM4335_CHIP_ID:
+       case BCM4339_CHIP_ID:
+               /* read PMU chipcontrol register 3 */
+               addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr);
+               brcmf_sdiod_regwl(bus->sdiodev, addr, 3, NULL);
+               addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data);
+               reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL);
+               return (reg & pmu_cc3_mask) != 0;
+       default:
+               addr = CORE_CC_REG(bus->ci->c_inf[0].base, pmucapabilities_ext);
+               reg = brcmf_sdiod_regrl(bus->sdiodev, addr, &err);
+               if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
+                       return false;
 
-       return (bool)reg;
+               addr = CORE_CC_REG(bus->ci->c_inf[0].base, retention_ctl);
+               reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL);
+               return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
+                              PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
+       }
 }
 
-static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus)
+static void brcmf_sdio_sr_init(struct brcmf_sdio *bus)
 {
        int err = 0;
        u8 val;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
-                              &err);
+       val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err);
        if (err) {
                brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
                return;
        }
 
        val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
-       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
-                        val, &err);
+       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err);
        if (err) {
                brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
                return;
        }
 
        /* Add CMD14 Support */
-       brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
-                        (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
-                         SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
-                        &err);
+       brcmf_sdiod_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
+                         (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
+                          SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
+                         &err);
        if (err) {
                brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
                return;
        }
 
-       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-                        SBSDIO_FORCE_HT, &err);
+       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+                         SBSDIO_FORCE_HT, &err);
        if (err) {
                brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
                return;
@@ -3455,7 +3464,7 @@ static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus)
 }
 
 /* enable KSO bit */
-static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus)
+static int brcmf_sdio_kso_init(struct brcmf_sdio *bus)
 {
        u8 val;
        int err = 0;
@@ -3466,8 +3475,7 @@ static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus)
        if (bus->ci->c_inf[1].rev < 12)
                return 0;
 
-       val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-                              &err);
+       val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
        if (err) {
                brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n");
                return err;
@@ -3476,8 +3484,8 @@ static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus)
        if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
                val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN <<
                        SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-                                val, &err);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+                                 val, &err);
                if (err) {
                        brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n");
                        return err;
@@ -3488,25 +3496,7 @@ static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus)
 }
 
 
-static bool
-brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
-{
-       bool ret;
-
-       sdio_claim_host(bus->sdiodev->func[1]);
-
-       brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
-       ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
-
-       brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-
-       sdio_release_host(bus->sdiodev->func[1]);
-
-       return ret;
-}
-
-static int brcmf_sdbrcm_bus_preinit(struct device *dev)
+static int brcmf_sdio_bus_preinit(struct device *dev)
 {
        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
        struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
@@ -3565,13 +3555,11 @@ done:
        return err;
 }
 
-static int brcmf_sdbrcm_bus_init(struct device *dev)
+static int brcmf_sdio_bus_init(struct device *dev)
 {
        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
        struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
        struct brcmf_sdio *bus = sdiodev->bus;
-       unsigned long timeout;
-       u8 ready, enable;
        int err, ret = 0;
        u8 saveclk;
 
@@ -3579,8 +3567,9 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
 
        /* try to download image and nvram to the dongle */
        if (bus_if->state == BRCMF_BUS_DOWN) {
-               if (!(brcmf_sdbrcm_download_firmware(bus)))
-                       return -1;
+               err = brcmf_sdio_download_firmware(bus);
+               if (err)
+                       return err;
        }
 
        if (!bus->sdiodev->bus_if->drvr)
@@ -3588,21 +3577,21 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
 
        /* Start the watchdog timer */
        bus->sdcnt.tickcnt = 0;
-       brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+       brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
 
        sdio_claim_host(bus->sdiodev->func[1]);
 
        /* Make sure backplane clock is on, needed to generate F2 interrupt */
-       brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+       brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
        if (bus->clkstate != CLK_AVAIL)
                goto exit;
 
        /* Force clocks on backplane to be sure F2 interrupt propagates */
-       saveclk = brcmf_sdio_regrb(bus->sdiodev,
-                                  SBSDIO_FUNC1_CHIPCLKCSR, &err);
+       saveclk = brcmf_sdiod_regrb(bus->sdiodev,
+                                   SBSDIO_FUNC1_CHIPCLKCSR, &err);
        if (!err) {
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-                                (saveclk | SBSDIO_FORCE_HT), &err);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+                                 (saveclk | SBSDIO_FORCE_HT), &err);
        }
        if (err) {
                brcmf_err("Failed to force clock for F2: err %d\n", err);
@@ -3612,56 +3601,42 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
        /* Enable function 2 (frame transfers) */
        w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
                  offsetof(struct sdpcmd_regs, tosbmailboxdata));
-       enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
-
-       brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL);
+       err = sdio_enable_func(bus->sdiodev->func[SDIO_FUNC_2]);
 
-       timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY);
-       ready = 0;
-       while (enable != ready) {
-               ready = brcmf_sdio_regrb(bus->sdiodev,
-                                        SDIO_CCCR_IORx, NULL);
-               if (time_after(jiffies, timeout))
-                       break;
-               else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50))
-                       /* prevent busy waiting if it takes too long */
-                       msleep_interruptible(20);
-       }
 
-       brcmf_dbg(INFO, "enable 0x%02x, ready 0x%02x\n", enable, ready);
+       brcmf_dbg(INFO, "enable F2: err=%d\n", err);
 
        /* If F2 successfully enabled, set core and enable interrupts */
-       if (ready == enable) {
+       if (!err) {
                /* Set up the interrupt mask and enable interrupts */
                bus->hostintmask = HOSTINTMASK;
                w_sdreg32(bus, bus->hostintmask,
                          offsetof(struct sdpcmd_regs, hostintmask));
 
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_WATERMARK, 8, &err);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_WATERMARK, 8, &err);
        } else {
                /* Disable F2 again */
-               enable = SDIO_FUNC_ENABLE_1;
-               brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL);
+               sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
                ret = -ENODEV;
        }
 
-       if (brcmf_sdbrcm_sr_capable(bus)) {
-               brcmf_sdbrcm_sr_init(bus);
+       if (brcmf_sdio_sr_capable(bus)) {
+               brcmf_sdio_sr_init(bus);
        } else {
                /* Restore previous clock setting */
-               brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-                                saveclk, &err);
+               brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+                                 saveclk, &err);
        }
 
        if (ret == 0) {
-               ret = brcmf_sdio_intr_register(bus->sdiodev);
+               ret = brcmf_sdiod_intr_register(bus->sdiodev);
                if (ret != 0)
                        brcmf_err("intr register failed:%d\n", ret);
        }
 
        /* If we didn't come up, turn off backplane clock */
-       if (bus_if->state != BRCMF_BUS_DATA)
-               brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+       if (ret != 0)
+               brcmf_sdio_clkctl(bus, CLK_NONE, false);
 
 exit:
        sdio_release_host(bus->sdiodev->func[1]);
@@ -3669,10 +3644,8 @@ exit:
        return ret;
 }
 
-void brcmf_sdbrcm_isr(void *arg)
+void brcmf_sdio_isr(struct brcmf_sdio *bus)
 {
-       struct brcmf_sdio *bus = (struct brcmf_sdio *) arg;
-
        brcmf_dbg(TRACE, "Enter\n");
 
        if (!bus) {
@@ -3702,7 +3675,7 @@ void brcmf_sdbrcm_isr(void *arg)
        queue_work(bus->brcmf_wq, &bus->datawork);
 }
 
-static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
+static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
 {
 #ifdef DEBUG
        struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev);
@@ -3726,9 +3699,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
                                u8 devpend;
 
                                sdio_claim_host(bus->sdiodev->func[1]);
-                               devpend = brcmf_sdio_regrb(bus->sdiodev,
-                                                          SDIO_CCCR_INTx,
-                                                          NULL);
+                               devpend = brcmf_sdiod_regrb(bus->sdiodev,
+                                                           SDIO_CCCR_INTx,
+                                                           NULL);
                                sdio_release_host(bus->sdiodev->func[1]);
                                intstatus =
                                    devpend & (INTR_STATUS_FUNC1 |
@@ -3758,8 +3731,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
                        bus->console.count -= bus->console_interval;
                        sdio_claim_host(bus->sdiodev->func[1]);
                        /* Make sure backplane clock is on */
-                       brcmf_sdbrcm_bus_sleep(bus, false, false);
-                       if (brcmf_sdbrcm_readconsole(bus) < 0)
+                       brcmf_sdio_bus_sleep(bus, false, false);
+                       if (brcmf_sdio_readconsole(bus) < 0)
                                /* stop on error */
                                bus->console_interval = 0;
                        sdio_release_host(bus->sdiodev->func[1]);
@@ -3773,11 +3746,11 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
                        bus->idlecount = 0;
                        if (bus->activity) {
                                bus->activity = false;
-                               brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+                               brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
                        } else {
                                brcmf_dbg(SDIO, "idle\n");
                                sdio_claim_host(bus->sdiodev->func[1]);
-                               brcmf_sdbrcm_bus_sleep(bus, true, false);
+                               brcmf_sdio_bus_sleep(bus, true, false);
                                sdio_release_host(bus->sdiodev->func[1]);
                        }
                }
@@ -3792,38 +3765,13 @@ static void brcmf_sdio_dataworker(struct work_struct *work)
                                              datawork);
 
        while (atomic_read(&bus->dpc_tskcnt)) {
-               brcmf_sdbrcm_dpc(bus);
+               brcmf_sdio_dpc(bus);
                atomic_dec(&bus->dpc_tskcnt);
        }
 }
 
-static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus)
-{
-       brcmf_dbg(TRACE, "Enter\n");
-
-       kfree(bus->rxbuf);
-       bus->rxctl = bus->rxbuf = NULL;
-       bus->rxlen = 0;
-}
-
-static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus)
-{
-       brcmf_dbg(TRACE, "Enter\n");
-
-       if (bus->sdiodev->bus_if->maxctl) {
-               bus->rxblen =
-                   roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN),
-                           ALIGNMENT) + bus->head_align;
-               bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
-               if (!(bus->rxbuf))
-                       return false;
-       }
-
-       return true;
-}
-
 static bool
-brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
+brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 {
        u8 clkctl = 0;
        int err = 0;
@@ -3836,18 +3784,18 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
        sdio_claim_host(bus->sdiodev->func[1]);
 
        pr_debug("F1 signature read @0x18000000=0x%4x\n",
-                brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
+                brcmf_sdiod_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
 
        /*
         * Force PLL off until brcmf_sdio_chip_attach()
         * programs PLL control regs
         */
 
-       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-                        BRCMF_INIT_CLKCTL1, &err);
+       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+                         BRCMF_INIT_CLKCTL1, &err);
        if (!err)
-               clkctl = brcmf_sdio_regrb(bus->sdiodev,
-                                         SBSDIO_FUNC1_CHIPCLKCSR, &err);
+               clkctl = brcmf_sdiod_regrb(bus->sdiodev,
+                                          SBSDIO_FUNC1_CHIPCLKCSR, &err);
 
        if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
                brcmf_err("ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
@@ -3855,12 +3803,12 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
                goto fail;
        }
 
-       if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci, regsva)) {
+       if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci)) {
                brcmf_err("brcmf_sdio_chip_attach failed!\n");
                goto fail;
        }
 
-       if (brcmf_sdbrcm_kso_init(bus)) {
+       if (brcmf_sdio_kso_init(bus)) {
                brcmf_err("error enabling KSO\n");
                goto fail;
        }
@@ -3879,33 +3827,33 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
        }
 
        /* Set card control so an SDIO card reset does a WLAN backplane reset */
-       reg_val = brcmf_sdio_regrb(bus->sdiodev,
-                                  SDIO_CCCR_BRCM_CARDCTRL, &err);
+       reg_val = brcmf_sdiod_regrb(bus->sdiodev,
+                                   SDIO_CCCR_BRCM_CARDCTRL, &err);
        if (err)
                goto fail;
 
        reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
 
-       brcmf_sdio_regwb(bus->sdiodev,
-                        SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
+       brcmf_sdiod_regwb(bus->sdiodev,
+                         SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
        if (err)
                goto fail;
 
        /* set PMUControl so a backplane reset does PMU state reload */
        reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base,
                               pmucontrol);
-       reg_val = brcmf_sdio_regrl(bus->sdiodev,
-                                  reg_addr,
-                                  &err);
+       reg_val = brcmf_sdiod_regrl(bus->sdiodev,
+                                   reg_addr,
+                                   &err);
        if (err)
                goto fail;
 
        reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
 
-       brcmf_sdio_regwl(bus->sdiodev,
-                        reg_addr,
-                        reg_val,
-                        &err);
+       brcmf_sdiod_regwl(bus->sdiodev,
+                         reg_addr,
+                         reg_val,
+                         &err);
        if (err)
                goto fail;
 
@@ -3935,42 +3883,8 @@ fail:
        return false;
 }
 
-static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
-{
-       brcmf_dbg(TRACE, "Enter\n");
-
-       sdio_claim_host(bus->sdiodev->func[1]);
-
-       /* Disable F2 to clear any intermediate frame state on the dongle */
-       brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx,
-                        SDIO_FUNC_ENABLE_1, NULL);
-
-       bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
-       bus->rxflow = false;
-
-       /* Done with backplane-dependent accesses, can drop clock... */
-       brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
-
-       sdio_release_host(bus->sdiodev->func[1]);
-
-       /* ...and initialize clock/power states */
-       bus->clkstate = CLK_SDONLY;
-       bus->idletime = BRCMF_IDLE_INTERVAL;
-       bus->idleclock = BRCMF_IDLE_ACTIVE;
-
-       /* Query the F2 block size, set roundup accordingly */
-       bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
-       bus->roundup = min(max_roundup, bus->blocksize);
-
-       /* SR state */
-       bus->sleeping = false;
-       bus->sr_enabled = false;
-
-       return true;
-}
-
 static int
-brcmf_sdbrcm_watchdog_thread(void *data)
+brcmf_sdio_watchdog_thread(void *data)
 {
        struct brcmf_sdio *bus = (struct brcmf_sdio *)data;
 
@@ -3980,7 +3894,7 @@ brcmf_sdbrcm_watchdog_thread(void *data)
                if (kthread_should_stop())
                        break;
                if (!wait_for_completion_interruptible(&bus->watchdog_wait)) {
-                       brcmf_sdbrcm_bus_watchdog(bus);
+                       brcmf_sdio_bus_watchdog(bus);
                        /* Count the tick for reference */
                        bus->sdcnt.tickcnt++;
                } else
@@ -3990,7 +3904,7 @@ brcmf_sdbrcm_watchdog_thread(void *data)
 }
 
 static void
-brcmf_sdbrcm_watchdog(unsigned long data)
+brcmf_sdio_watchdog(unsigned long data)
 {
        struct brcmf_sdio *bus = (struct brcmf_sdio *)data;
 
@@ -4003,71 +3917,23 @@ brcmf_sdbrcm_watchdog(unsigned long data)
        }
 }
 
-static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus)
-{
-       brcmf_dbg(TRACE, "Enter\n");
-
-       if (bus->ci) {
-               sdio_claim_host(bus->sdiodev->func[1]);
-               brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-               brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
-               sdio_release_host(bus->sdiodev->func[1]);
-               brcmf_sdio_chip_detach(&bus->ci);
-               if (bus->vars && bus->varsz)
-                       kfree(bus->vars);
-               bus->vars = NULL;
-       }
-
-       brcmf_dbg(TRACE, "Disconnected\n");
-}
-
-/* Detach and free everything */
-static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
-{
-       brcmf_dbg(TRACE, "Enter\n");
-
-       if (bus) {
-               /* De-register interrupt handler */
-               brcmf_sdio_intr_unregister(bus->sdiodev);
-
-               cancel_work_sync(&bus->datawork);
-               if (bus->brcmf_wq)
-                       destroy_workqueue(bus->brcmf_wq);
-
-               if (bus->sdiodev->bus_if->drvr) {
-                       brcmf_detach(bus->sdiodev->dev);
-                       brcmf_sdbrcm_release_dongle(bus);
-               }
-
-               brcmu_pkt_buf_free_skb(bus->txglom_sgpad);
-               brcmf_sdbrcm_release_malloc(bus);
-               kfree(bus->hdrbuf);
-               kfree(bus);
-       }
-
-       brcmf_dbg(TRACE, "Disconnected\n");
-}
-
 static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
-       .stop = brcmf_sdbrcm_bus_stop,
-       .preinit = brcmf_sdbrcm_bus_preinit,
-       .init = brcmf_sdbrcm_bus_init,
-       .txdata = brcmf_sdbrcm_bus_txdata,
-       .txctl = brcmf_sdbrcm_bus_txctl,
-       .rxctl = brcmf_sdbrcm_bus_rxctl,
-       .gettxq = brcmf_sdbrcm_bus_gettxq,
+       .stop = brcmf_sdio_bus_stop,
+       .preinit = brcmf_sdio_bus_preinit,
+       .init = brcmf_sdio_bus_init,
+       .txdata = brcmf_sdio_bus_txdata,
+       .txctl = brcmf_sdio_bus_txctl,
+       .rxctl = brcmf_sdio_bus_rxctl,
+       .gettxq = brcmf_sdio_bus_gettxq,
 };
 
-void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
+struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
 {
        int ret;
        struct brcmf_sdio *bus;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       /* We make an assumption about address window mappings:
-        * regsva == SI_ENUM_BASE*/
-
        /* Allocate private bus interface state */
        bus = kzalloc(sizeof(struct brcmf_sdio), GFP_ATOMIC);
        if (!bus)
@@ -4101,8 +3967,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        }
 
        /* attempt to attach to the dongle */
-       if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) {
-               brcmf_err("brcmf_sdbrcm_probe_attach failed\n");
+       if (!(brcmf_sdio_probe_attach(bus))) {
+               brcmf_err("brcmf_sdio_probe_attach failed\n");
                goto fail;
        }
 
@@ -4114,11 +3980,11 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        /* Set up the watchdog timer */
        init_timer(&bus->timer);
        bus->timer.data = (unsigned long)bus;
-       bus->timer.function = brcmf_sdbrcm_watchdog;
+       bus->timer.function = brcmf_sdio_watchdog;
 
        /* Initialize watchdog thread */
        init_completion(&bus->watchdog_wait);
-       bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
+       bus->watchdog_tsk = kthread_run(brcmf_sdio_watchdog_thread,
                                        bus, "brcmf_watchdog");
        if (IS_ERR(bus->watchdog_tsk)) {
                pr_warn("brcmf_watchdog thread failed to start\n");
@@ -4144,15 +4010,42 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        }
 
        /* Allocate buffers */
-       if (!(brcmf_sdbrcm_probe_malloc(bus))) {
-               brcmf_err("brcmf_sdbrcm_probe_malloc failed\n");
-               goto fail;
+       if (bus->sdiodev->bus_if->maxctl) {
+               bus->rxblen =
+                   roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN),
+                           ALIGNMENT) + bus->head_align;
+               bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
+               if (!(bus->rxbuf)) {
+                       brcmf_err("rxbuf allocation failed\n");
+                       goto fail;
+               }
        }
 
-       if (!(brcmf_sdbrcm_probe_init(bus))) {
-               brcmf_err("brcmf_sdbrcm_probe_init failed\n");
-               goto fail;
-       }
+       sdio_claim_host(bus->sdiodev->func[1]);
+
+       /* Disable F2 to clear any intermediate frame state on the dongle */
+       sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
+
+       bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
+       bus->rxflow = false;
+
+       /* Done with backplane-dependent accesses, can drop clock... */
+       brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+
+       sdio_release_host(bus->sdiodev->func[1]);
+
+       /* ...and initialize clock/power states */
+       bus->clkstate = CLK_SDONLY;
+       bus->idletime = BRCMF_IDLE_INTERVAL;
+       bus->idleclock = BRCMF_IDLE_ACTIVE;
+
+       /* Query the F2 block size, set roundup accordingly */
+       bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
+       bus->roundup = min(max_roundup, bus->blocksize);
+
+       /* SR state */
+       bus->sleeping = false;
+       bus->sr_enabled = false;
 
        brcmf_sdio_debugfs_create(bus);
        brcmf_dbg(INFO, "completed!!\n");
@@ -4167,24 +4060,46 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        return bus;
 
 fail:
-       brcmf_sdbrcm_release(bus);
+       brcmf_sdio_remove(bus);
        return NULL;
 }
 
-void brcmf_sdbrcm_disconnect(void *ptr)
+/* Detach and free everything */
+void brcmf_sdio_remove(struct brcmf_sdio *bus)
 {
-       struct brcmf_sdio *bus = (struct brcmf_sdio *)ptr;
-
        brcmf_dbg(TRACE, "Enter\n");
 
-       if (bus)
-               brcmf_sdbrcm_release(bus);
+       if (bus) {
+               /* De-register interrupt handler */
+               brcmf_sdiod_intr_unregister(bus->sdiodev);
+
+               cancel_work_sync(&bus->datawork);
+               if (bus->brcmf_wq)
+                       destroy_workqueue(bus->brcmf_wq);
+
+               if (bus->sdiodev->bus_if->drvr) {
+                       brcmf_detach(bus->sdiodev->dev);
+               }
+
+               if (bus->ci) {
+                       sdio_claim_host(bus->sdiodev->func[1]);
+                       brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+                       brcmf_sdio_clkctl(bus, CLK_NONE, false);
+                       sdio_release_host(bus->sdiodev->func[1]);
+                       brcmf_sdio_chip_detach(&bus->ci);
+               }
+
+               brcmu_pkt_buf_free_skb(bus->txglom_sgpad);
+               kfree(bus->rxbuf);
+               kfree(bus->hdrbuf);
+               kfree(bus->vars);
+               kfree(bus);
+       }
 
        brcmf_dbg(TRACE, "Disconnected\n");
 }
 
-void
-brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick)
+void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick)
 {
        /* Totally stop the timer */
        if (!wdtick && bus->wd_timer_valid) {
@@ -4195,7 +4110,7 @@ brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick)
        }
 
        /* don't start the wd until fw is loaded */
-       if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN)
+       if (bus->sdiodev->bus_if->state != BRCMF_BUS_DATA)
                return;
 
        if (wdtick) {
index b72d3395499a3c1e713af54a4379f86e93ca407a..22adbe311d206df979a592419d7d247280474ec6 100644 (file)
@@ -68,7 +68,7 @@ brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
 
        brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
        brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
-                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
        err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
        mutex_unlock(&ifp->drvr->proto_block);
@@ -86,7 +86,7 @@ brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
 
        brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
        brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
-                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
        mutex_unlock(&ifp->drvr->proto_block);
 
@@ -155,7 +155,7 @@ brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
 
        brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
        brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
-                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
        buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
                                    sizeof(drvr->proto_buf));
@@ -195,7 +195,7 @@ brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
 
        brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
        brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
-                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
        mutex_unlock(&drvr->proto_block);
        return err;
@@ -278,7 +278,7 @@ brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
 
        brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
        brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
-                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
        buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
                                     drvr->proto_buf, sizeof(drvr->proto_buf));
@@ -317,7 +317,7 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
        }
        brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
        brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
-                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
        mutex_unlock(&drvr->proto_block);
        return err;
index e9bdfdb95d8f06915fc734dd27053a3e092c046e..c3e7d76dbf35f508e33a1e1d88164ede54b1967a 100644 (file)
@@ -838,7 +838,7 @@ static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx)
        brcmf_fws_hanger_cleanup(fws, matchfn, ifidx);
 }
 
-static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
+static u8 brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
 {
        struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
        u8 *wlh;
@@ -887,9 +887,7 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
        if (fillers)
                memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers);
 
-       brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX),
-                           data_offset >> 2, skb);
-       return 0;
+       return (u8)(data_offset >> 2);
 }
 
 static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
@@ -897,10 +895,11 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
                                 int fifo, bool send_immediately)
 {
        struct sk_buff *skb;
-       struct brcmf_bus *bus;
        struct brcmf_skbuff_cb *skcb;
        s32 err;
        u32 len;
+       u8 data_offset;
+       int ifidx;
 
        /* check delayedQ and suppressQ in one call using bitmap */
        if (brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0)
@@ -928,13 +927,11 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
                skcb->state = BRCMF_FWS_SKBSTATE_TIM;
                skcb->htod = 0;
                skcb->htod_seq = 0;
-               bus = fws->drvr->bus_if;
-               err = brcmf_fws_hdrpush(fws, skb);
-               if (err == 0) {
-                       brcmf_fws_unlock(fws);
-                       err = brcmf_bus_txdata(bus, skb);
-                       brcmf_fws_lock(fws);
-               }
+               data_offset = brcmf_fws_hdrpush(fws, skb);
+               ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
+               brcmf_fws_unlock(fws);
+               err = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
+               brcmf_fws_lock(fws);
                if (err)
                        brcmu_pkt_buf_free_skb(skb);
                return true;
@@ -1393,7 +1390,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
        entry->generation = genbit;
 
        ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
-       if (ret == 0)
+       if (ret == 0) {
                brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
                brcmf_skbcb(skb)->htod_seq = seq;
                if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
@@ -1404,6 +1401,8 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
                }
                ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo,
                                    skb);
+       }
+
        if (ret != 0) {
                /* suppress q is full or hdrpull failed, drop this packet */
                brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
@@ -1717,7 +1716,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
        return 0;
 }
 
-static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
+static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
                                   struct sk_buff *p)
 {
        struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
@@ -1735,7 +1734,7 @@ static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
                flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
        }
        brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
-       brcmf_fws_hdrpush(fws, p);
+       return brcmf_fws_hdrpush(fws, p);
 }
 
 static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
@@ -1803,20 +1802,21 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
 {
        struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
        struct brcmf_fws_mac_descriptor *entry;
-       struct brcmf_bus *bus = fws->drvr->bus_if;
        int rc;
        u8 ifidx;
+       u8 data_offset;
 
        entry = skcb->mac;
        if (IS_ERR(entry))
                return PTR_ERR(entry);
 
-       brcmf_fws_precommit_skb(fws, fifo, skb);
+       data_offset = brcmf_fws_precommit_skb(fws, fifo, skb);
        entry->transit_count++;
        if (entry->suppressed)
                entry->suppr_transit_count++;
+       ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
        brcmf_fws_unlock(fws);
-       rc = brcmf_bus_txdata(bus, skb);
+       rc = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
        brcmf_fws_lock(fws);
        brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
                  skcb->if_flags, skcb->htod, rc);
@@ -1873,7 +1873,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
        brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
        /* determine the priority */
        if (!skb->priority)
-               skb->priority = cfg80211_classify8021d(skb);
+               skb->priority = cfg80211_classify8021d(skb, NULL);
 
        drvr->tx_multicast += !!multicast;
        if (pae)
@@ -1977,10 +1977,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
                                                        &skb, true);
                                ifidx = brcmf_skb_if_flags_get_field(skb,
                                                                     INDEX);
-                               brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
-                               /* Use bus module to send data frame */
+                               /* Use proto layer to send data frame */
                                brcmf_fws_unlock(fws);
-                               ret = brcmf_bus_txdata(drvr->bus_if, skb);
+                               ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
                                brcmf_fws_lock(fws);
                                if (ret < 0)
                                        brcmf_txfinalize(drvr, skb, false);
index d3180360725925c40f6e59bf09bdfb28e18a4300..fc4f98b275d7db6a8519b7c05dcddeb7aa2e2bf1 100644 (file)
@@ -1243,7 +1243,7 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
                                            IEEE80211_P2P_ATTR_DEVICE_ID,
                                            p2p_dev_addr, sizeof(p2p_dev_addr));
        if ((err >= 0) &&
-           (!memcmp(p2p_dev_addr, afx_hdl->tx_dst_addr, ETH_ALEN))) {
+           (ether_addr_equal(p2p_dev_addr, afx_hdl->tx_dst_addr))) {
                if (!bi->ctl_ch) {
                        ch.chspec = le16_to_cpu(bi->chanspec);
                        cfg->d11inf.decchspec(&ch);
@@ -1380,8 +1380,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
                    (brcmf_p2p_gon_req_collision(p2p, (u8 *)e->addr))) {
                        if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
                                     &p2p->status) &&
-                           (memcmp(afx_hdl->tx_dst_addr, e->addr,
-                                   ETH_ALEN) == 0)) {
+                           (ether_addr_equal(afx_hdl->tx_dst_addr, e->addr))) {
                                afx_hdl->peer_chan = ch.chnum;
                                brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n",
                                          afx_hdl->peer_chan);
@@ -1865,7 +1864,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
        cfg->d11inf.decchspec(&ch);
 
        if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) &&
-           (memcmp(afx_hdl->tx_dst_addr, e->addr, ETH_ALEN) == 0)) {
+           (ether_addr_equal(afx_hdl->tx_dst_addr, e->addr))) {
                afx_hdl->peer_chan = ch.chnum;
                brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n",
                          afx_hdl->peer_chan);
@@ -1956,21 +1955,21 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
                err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
                if (err < 0) {
                        brcmf_err("set p2p_disc error\n");
-                       brcmf_free_vif(cfg, p2p_vif);
+                       brcmf_free_vif(p2p_vif);
                        goto exit;
                }
                /* obtain bsscfg index for P2P discovery */
                err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
                if (err < 0) {
                        brcmf_err("retrieving discover bsscfg index failed\n");
-                       brcmf_free_vif(cfg, p2p_vif);
+                       brcmf_free_vif(p2p_vif);
                        goto exit;
                }
                /* Verify that firmware uses same bssidx as driver !! */
                if (p2p_ifp->bssidx != bssidx) {
                        brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
                                  bssidx, p2p_ifp->bssidx);
-                       brcmf_free_vif(cfg, p2p_vif);
+                       brcmf_free_vif(p2p_vif);
                        goto exit;
                }
 
@@ -1998,7 +1997,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
                brcmf_p2p_cancel_remain_on_channel(vif->ifp);
                brcmf_p2p_deinit_discovery(p2p);
                /* remove discovery interface */
-               brcmf_free_vif(p2p->cfg, vif);
+               brcmf_free_vif(vif);
                p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
        }
        /* just set it all to zero */
@@ -2223,7 +2222,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
        return &p2p_vif->wdev;
 
 fail:
-       brcmf_free_vif(p2p->cfg, p2p_vif);
+       brcmf_free_vif(p2p_vif);
        return ERR_PTR(err);
 }
 
@@ -2232,31 +2231,12 @@ fail:
  *
  * @vif: virtual interface object to delete.
  */
-static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_info *cfg,
+static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p,
                                    struct brcmf_cfg80211_vif *vif)
 {
        cfg80211_unregister_wdev(&vif->wdev);
-       cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
-       brcmf_free_vif(cfg, vif);
-}
-
-/**
- * brcmf_p2p_free_p2p_if() - free up net device related data.
- *
- * @ndev: net device that needs to be freed.
- */
-static void brcmf_p2p_free_p2p_if(struct net_device *ndev)
-{
-       struct brcmf_cfg80211_info *cfg;
-       struct brcmf_cfg80211_vif *vif;
-       struct brcmf_if *ifp;
-
-       ifp = netdev_priv(ndev);
-       cfg = ifp->drvr->config;
-       vif = ifp->vif;
-
-       brcmf_free_vif(cfg, vif);
-       free_netdev(ifp->ndev);
+       p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+       brcmf_free_vif(vif);
 }
 
 /**
@@ -2336,8 +2316,6 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
                brcmf_err("Registering netdevice failed\n");
                goto fail;
        }
-       /* override destructor */
-       ifp->ndev->destructor = brcmf_p2p_free_p2p_if;
 
        cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif;
        /* Disable firmware roaming for P2P interface  */
@@ -2350,7 +2328,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
        return &ifp->vif->wdev;
 
 fail:
-       brcmf_free_vif(cfg, vif);
+       brcmf_free_vif(vif);
        return ERR_PTR(err);
 }
 
@@ -2359,8 +2337,6 @@ fail:
  *
  * @wiphy: wiphy device of interface.
  * @wdev: wireless device of interface.
- *
- * TODO: not yet supported.
  */
 int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
 {
@@ -2386,7 +2362,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
                break;
 
        case NL80211_IFTYPE_P2P_DEVICE:
-               brcmf_p2p_delete_p2pdev(cfg, vif);
+               brcmf_p2p_delete_p2pdev(p2p, vif);
                return 0;
        default:
                return -ENOTSUPP;
index 87eb2bd4c072077d8b234cd1b17abcdd54142aa2..b6b4641849463a9e383946c8a482072de9cd21fe 100644 (file)
@@ -39,7 +39,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
        if (brcmf_proto_bcdc_attach(drvr))
                goto fail;
 
-       if ((proto->hdrpush == NULL) || (proto->hdrpull == NULL) ||
+       if ((proto->txdata == NULL) || (proto->hdrpull == NULL) ||
            (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) {
                brcmf_err("Not all proto handlers have been installed\n");
                goto fail;
index 8de1b3bce228fbd61906bc201289eb855b434fc0..482fb0ba4a30f3b8afd7958fd65a1b485344014a 100644 (file)
 #define BRCMFMAC_PROTO_H
 
 struct brcmf_proto {
-       void (*hdrpush)(struct brcmf_pub *drvr, int ifidx, u8 offset,
-                       struct sk_buff *skb);
        int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
                       struct sk_buff *skb);
        int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
                          void *buf, uint len);
        int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
                        uint len);
+       int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
+                     struct sk_buff *skb);
        void *pd;
 };
 
@@ -32,11 +32,6 @@ struct brcmf_proto {
 int brcmf_proto_attach(struct brcmf_pub *drvr);
 void brcmf_proto_detach(struct brcmf_pub *drvr);
 
-static inline void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
-                                      u8 offset, struct sk_buff *skb)
-{
-       drvr->proto->hdrpush(drvr, ifidx, offset, skb);
-}
 static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
                                      u8 *ifidx, struct sk_buff *skb)
 {
@@ -52,6 +47,11 @@ static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
 {
        return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
 }
+static inline int brcmf_proto_txdata(struct brcmf_pub *drvr, int ifidx,
+                                      u8 offset, struct sk_buff *skb)
+{
+       return drvr->proto->txdata(drvr, ifidx, offset, skb);
+}
 
 
 #endif /* BRCMFMAC_PROTO_H */
index 2096a14ef1fba5fcaf156140a64b2f52f4b67757..9fd40675f18e013036d9c49d9e7db0d4a891e810 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/netdevice.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
 #include <linux/ssb/ssb_regs.h>
 #include <linux/bcma/bcma.h>
 
@@ -83,6 +84,24 @@ static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
        {0, 0x1}
 };
 
+/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
+static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8[] = {
+        {6, 0x7},
+        {5, 0x6},
+        {4, 0x5},
+        {3, 0x4},
+        {2, 0x2},
+        {1, 0x1},
+        {0, 0x0}
+};
+
+/* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
+static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8[] = {
+       {3, 0x3},
+       {2, 0x2},
+       {1, 0x1},
+       {0, 0x0} };
+
 /* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
 static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
        {16, 0x7},
@@ -112,9 +131,9 @@ brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
 
        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
 
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  CORE_SB(ci->c_inf[idx].base, sbidhigh),
-                                  NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   CORE_SB(ci->c_inf[idx].base, sbidhigh),
+                                   NULL);
        return SBCOREREV(regdata);
 }
 
@@ -140,9 +159,9 @@ brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
        if (idx == BRCMF_MAX_CORENUM)
                return false;
 
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-                                  NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
+                                   NULL);
        regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
                    SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
        return (SSB_TMSLOW_CLOCK == regdata);
@@ -160,13 +179,13 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
        if (idx == BRCMF_MAX_CORENUM)
                return false;
 
-       regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
-                                  NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+                                   NULL);
        ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
 
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
-                                  NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
+                                   NULL);
        ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
 
        return ret;
@@ -182,79 +201,79 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
        base = ci->c_inf[idx].base;
 
-       regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
        if (regdata & SSB_TMSLOW_RESET)
                return;
 
-       regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
        if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
                /*
                 * set target reject and spin until busy is clear
                 * (preserve core-specific bits)
                 */
-               regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
-                                          NULL);
-               brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
-                                regdata | SSB_TMSLOW_REJECT, NULL);
+               regdata = brcmf_sdiod_regrl(sdiodev,
+                                           CORE_SB(base, sbtmstatelow), NULL);
+               brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
+                                 regdata | SSB_TMSLOW_REJECT, NULL);
 
-               regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
-                                          NULL);
+               regdata = brcmf_sdiod_regrl(sdiodev,
+                                           CORE_SB(base, sbtmstatelow), NULL);
                udelay(1);
-               SPINWAIT((brcmf_sdio_regrl(sdiodev,
-                                          CORE_SB(base, sbtmstatehigh),
-                                          NULL) &
-                       SSB_TMSHIGH_BUSY), 100000);
-
-               regdata = brcmf_sdio_regrl(sdiodev,
-                                          CORE_SB(base, sbtmstatehigh),
-                                          NULL);
+               SPINWAIT((brcmf_sdiod_regrl(sdiodev,
+                                           CORE_SB(base, sbtmstatehigh),
+                                           NULL) &
+                         SSB_TMSHIGH_BUSY), 100000);
+
+               regdata = brcmf_sdiod_regrl(sdiodev,
+                                           CORE_SB(base, sbtmstatehigh),
+                                           NULL);
                if (regdata & SSB_TMSHIGH_BUSY)
                        brcmf_err("core state still busy\n");
 
-               regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
-                                          NULL);
+               regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
+                                           NULL);
                if (regdata & SSB_IDLOW_INITIATOR) {
-                       regdata = brcmf_sdio_regrl(sdiodev,
-                                                  CORE_SB(base, sbimstate),
-                                                  NULL);
+                       regdata = brcmf_sdiod_regrl(sdiodev,
+                                                   CORE_SB(base, sbimstate),
+                                                   NULL);
                        regdata |= SSB_IMSTATE_REJECT;
-                       brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
-                                        regdata, NULL);
-                       regdata = brcmf_sdio_regrl(sdiodev,
-                                                  CORE_SB(base, sbimstate),
-                                                  NULL);
+                       brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
+                                         regdata, NULL);
+                       regdata = brcmf_sdiod_regrl(sdiodev,
+                                                   CORE_SB(base, sbimstate),
+                                                   NULL);
                        udelay(1);
-                       SPINWAIT((brcmf_sdio_regrl(sdiodev,
-                                                  CORE_SB(base, sbimstate),
-                                                  NULL) &
-                               SSB_IMSTATE_BUSY), 100000);
+                       SPINWAIT((brcmf_sdiod_regrl(sdiodev,
+                                                   CORE_SB(base, sbimstate),
+                                                   NULL) &
+                                 SSB_IMSTATE_BUSY), 100000);
                }
 
                /* set reset and reject while enabling the clocks */
                regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
                          SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
-               brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
-                                regdata, NULL);
-               regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
-                                          NULL);
+               brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
+                                 regdata, NULL);
+               regdata = brcmf_sdiod_regrl(sdiodev,
+                                           CORE_SB(base, sbtmstatelow), NULL);
                udelay(10);
 
                /* clear the initiator reject bit */
-               regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
-                                          NULL);
+               regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
+                                           NULL);
                if (regdata & SSB_IDLOW_INITIATOR) {
-                       regdata = brcmf_sdio_regrl(sdiodev,
-                                                  CORE_SB(base, sbimstate),
-                                                  NULL);
+                       regdata = brcmf_sdiod_regrl(sdiodev,
+                                                   CORE_SB(base, sbimstate),
+                                                   NULL);
                        regdata &= ~SSB_IMSTATE_REJECT;
-                       brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
-                                        regdata, NULL);
+                       brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
+                                         regdata, NULL);
                }
        }
 
        /* leave reset and reject asserted */
-       brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
-                        (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
+       brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
+                         (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
        udelay(1);
 }
 
@@ -270,9 +289,9 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
                return;
 
        /* if core is already in reset, just return */
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
-                                  NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
+                                   NULL);
        if ((regdata & BCMA_RESET_CTL_RESET) != 0)
                return;
 
@@ -281,24 +300,24 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
         * extra 10ms is taken into account for firmware load stage
         * after 10300us carry on disabling the core anyway
         */
-       SPINWAIT(brcmf_sdio_regrl(sdiodev,
-                                 ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
-                                 NULL), 10300);
-       regdata = brcmf_sdio_regrl(sdiodev,
+       SPINWAIT(brcmf_sdiod_regrl(sdiodev,
                                   ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
-                                  NULL);
+                                  NULL), 10300);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
+                                   NULL);
        if (regdata)
                brcmf_err("disabling core 0x%x with reset status %x\n",
                          coreid, regdata);
 
-       brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
-                        BCMA_RESET_CTL_RESET, NULL);
+       brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
+                         BCMA_RESET_CTL_RESET, NULL);
        udelay(1);
 
-       brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
-                        core_bits, NULL);
-       regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
-                                  NULL);
+       brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+                         core_bits, NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+                                   NULL);
        usleep_range(10, 20);
 
 }
@@ -325,47 +344,47 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
         * set reset while enabling the clock and
         * forcing them on throughout the core
         */
-       brcmf_sdio_regwl(sdiodev,
-                        CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-                        SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET,
-                        NULL);
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-                                  NULL);
+       brcmf_sdiod_regwl(sdiodev,
+                         CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
+                         SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET,
+                         NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
+                                   NULL);
        udelay(1);
 
        /* clear any serror */
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
-                                  NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
+                                   NULL);
        if (regdata & SSB_TMSHIGH_SERR)
-               brcmf_sdio_regwl(sdiodev,
-                                CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
-                                0, NULL);
+               brcmf_sdiod_regwl(sdiodev,
+                                 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
+                                 0, NULL);
 
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  CORE_SB(ci->c_inf[idx].base, sbimstate),
-                                  NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   CORE_SB(ci->c_inf[idx].base, sbimstate),
+                                   NULL);
        if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
-               brcmf_sdio_regwl(sdiodev,
-                                CORE_SB(ci->c_inf[idx].base, sbimstate),
-                                regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO),
-                                NULL);
+               brcmf_sdiod_regwl(sdiodev,
+                                 CORE_SB(ci->c_inf[idx].base, sbimstate),
+                                 regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO),
+                                 NULL);
 
        /* clear reset and allow it to propagate throughout the core */
-       brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-                        SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL);
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-                                  NULL);
+       brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
+                         SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
+                                   NULL);
        udelay(1);
 
        /* leave clock enabled */
-       brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-                        SSB_TMSLOW_CLOCK, NULL);
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
-                                  NULL);
+       brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
+                         SSB_TMSLOW_CLOCK, NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
+                                   NULL);
        udelay(1);
 }
 
@@ -384,21 +403,21 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
        brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits);
 
        /* now do initialization sequence */
-       brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
-                        core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
-       regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
-                                  NULL);
-       brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
-                        0, NULL);
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
-                                  NULL);
+       brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+                         core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+                                   NULL);
+       brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
+                         0, NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
+                                   NULL);
        udelay(1);
 
-       brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
-                        core_bits | BCMA_IOCTL_CLK, NULL);
-       regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
-                                  NULL);
+       brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+                         core_bits | BCMA_IOCTL_CLK, NULL);
+       regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+                                   NULL);
        udelay(1);
 }
 
@@ -438,7 +457,7 @@ static inline int brcmf_sdio_chip_cichk(struct chip_info *ci)
 #endif
 
 static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
-                                      struct chip_info *ci, u32 regs)
+                                      struct chip_info *ci)
 {
        u32 regdata;
        int ret;
@@ -449,10 +468,10 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
         * other ways of recognition should be added here.
         */
        ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
-       ci->c_inf[0].base = regs;
-       regdata = brcmf_sdio_regrl(sdiodev,
-                                  CORE_CC_REG(ci->c_inf[0].base, chipid),
-                                  NULL);
+       ci->c_inf[0].base = SI_ENUM_BASE;
+       regdata = brcmf_sdiod_regrl(sdiodev,
+                                   CORE_CC_REG(ci->c_inf[0].base, chipid),
+                                   NULL);
        ci->chip = regdata & CID_ID_MASK;
        ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
        if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
@@ -569,6 +588,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
                ci->ramsize = 0xc0000;
                ci->rambase = 0x180000;
                break;
+       case BCM43362_CHIP_ID:
+               ci->c_inf[0].wrapbase = 0x18100000;
+               ci->c_inf[0].cib = 0x27004211;
+               ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+               ci->c_inf[1].base = 0x18002000;
+               ci->c_inf[1].wrapbase = 0x18102000;
+               ci->c_inf[1].cib = 0x0a004211;
+               ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+               ci->c_inf[2].base = 0x18004000;
+               ci->c_inf[2].wrapbase = 0x18104000;
+               ci->c_inf[2].cib = 0x08080401;
+               ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+               ci->c_inf[3].base = 0x18003000;
+               ci->c_inf[3].wrapbase = 0x18103000;
+               ci->c_inf[3].cib = 0x03004211;
+               ci->ramsize = 0x3C000;
+               break;
        default:
                brcmf_err("chipid 0x%x is not supported\n", ci->chip);
                return -ENODEV;
@@ -607,7 +643,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
 
        /* Try forcing SDIO core to do ALPAvail request only */
        clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
-       brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+       brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
        if (err) {
                brcmf_err("error writing for HT off\n");
                return err;
@@ -615,8 +651,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
 
        /* If register supported, wait for ALPAvail and then force ALP */
        /* This may take up to 15 milliseconds */
-       clkval = brcmf_sdio_regrb(sdiodev,
-                                 SBSDIO_FUNC1_CHIPCLKCSR, NULL);
+       clkval = brcmf_sdiod_regrb(sdiodev,
+                                  SBSDIO_FUNC1_CHIPCLKCSR, NULL);
 
        if ((clkval & ~SBSDIO_AVBITS) != clkset) {
                brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
@@ -624,8 +660,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
                return -EACCES;
        }
 
-       SPINWAIT(((clkval = brcmf_sdio_regrb(sdiodev,
-                                            SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
+       SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev,
+                                             SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
                        !SBSDIO_ALPAV(clkval)),
                        PMU_MAX_TRANSITION_DLY);
        if (!SBSDIO_ALPAV(clkval)) {
@@ -635,11 +671,11 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
        }
 
        clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
-       brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+       brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
        udelay(65);
 
        /* Also, disable the extra SDIO pull-ups */
-       brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
+       brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
 
        return 0;
 }
@@ -654,16 +690,16 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
        ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
 
        /* get chipcommon capabilites */
-       ci->c_inf[0].caps = brcmf_sdio_regrl(sdiodev,
-                                            CORE_CC_REG(base, capabilities),
-                                            NULL);
+       ci->c_inf[0].caps = brcmf_sdiod_regrl(sdiodev,
+                                             CORE_CC_REG(base, capabilities),
+                                             NULL);
 
        /* get pmu caps & rev */
        if (ci->c_inf[0].caps & CC_CAP_PMU) {
                ci->pmucaps =
-                       brcmf_sdio_regrl(sdiodev,
-                                        CORE_CC_REG(base, pmucapabilities),
-                                        NULL);
+                       brcmf_sdiod_regrl(sdiodev,
+                                         CORE_CC_REG(base, pmucapabilities),
+                                         NULL);
                ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
        }
 
@@ -681,7 +717,7 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
 }
 
 int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
-                          struct chip_info **ci_ptr, u32 regs)
+                          struct chip_info **ci_ptr)
 {
        int ret;
        struct chip_info *ci;
@@ -697,16 +733,16 @@ int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
        if (ret != 0)
                goto err;
 
-       ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
+       ret = brcmf_sdio_chip_recognition(sdiodev, ci);
        if (ret != 0)
                goto err;
 
        brcmf_sdio_chip_buscoresetup(sdiodev, ci);
 
-       brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
-                        0, NULL);
-       brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
-                        0, NULL);
+       brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
+                         0, NULL);
+       brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
+                         0, NULL);
 
        *ci_ptr = ci;
        return 0;
@@ -757,6 +793,11 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
                str_mask = 0x00003800;
                str_shift = 11;
                break;
+       case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
+               str_tab = sdiod_drvstr_tab6_1v8;
+               str_mask = 0x00001800;
+               str_shift = 11;
+               break;
        case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
                /* note: 43143 does not support tristate */
                i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
@@ -769,6 +810,11 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
                                  brcmf_sdio_chip_name(ci->chip, chn, 8),
                                  drivestrength);
                break;
+       case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
+               str_tab = sdiod_drive_strength_tab5_1v8;
+               str_mask = 0x00003800;
+               str_shift = 11;
+               break;
        default:
                brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
                          brcmf_sdio_chip_name(ci->chip, chn, 8),
@@ -784,12 +830,12 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
                        }
                }
                addr = CORE_CC_REG(base, chipcontrol_addr);
-               brcmf_sdio_regwl(sdiodev, addr, 1, NULL);
-               cc_data_temp = brcmf_sdio_regrl(sdiodev, addr, NULL);
+               brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
+               cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
                cc_data_temp &= ~str_mask;
                drivestrength_sel <<= str_shift;
                cc_data_temp |= drivestrength_sel;
-               brcmf_sdio_regwl(sdiodev, addr, cc_data_temp, NULL);
+               brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL);
 
                brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
                          str_tab[i].strength, drivestrength, cc_data_temp);
@@ -816,8 +862,8 @@ brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
        memset(nvram_ularray, 0xaa, nvram_sz);
 
        /* Read the vars list to temp buffer for comparison */
-       err = brcmf_sdio_ramrw(sdiodev, false, nvram_addr, nvram_ularray,
-                              nvram_sz);
+       err = brcmf_sdiod_ramrw(sdiodev, false, nvram_addr, nvram_ularray,
+                               nvram_sz);
        if (err) {
                brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
                          err, nvram_sz, nvram_addr);
@@ -850,7 +896,7 @@ static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev,
        nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase;
 
        /* Write the vars list */
-       err = brcmf_sdio_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz);
+       err = brcmf_sdiod_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz);
        if (err) {
                brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
                          err, nvram_sz, nvram_addr);
@@ -874,8 +920,8 @@ static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev,
                  nvram_addr, nvram_sz, token);
 
        /* Write the length token to the last word */
-       if (brcmf_sdio_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase),
-                            (u8 *)&token_le, 4))
+       if (brcmf_sdiod_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase),
+                             (u8 *)&token_le, 4))
                return false;
 
        return true;
@@ -891,7 +937,7 @@ brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
        ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0);
 
        /* clear length token */
-       brcmf_sdio_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4);
+       brcmf_sdiod_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4);
 }
 
 static bool
@@ -913,7 +959,7 @@ brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
        core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
        reg_addr = ci->c_inf[core_idx].base;
        reg_addr += offsetof(struct sdpcmd_regs, intstatus);
-       brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
+       brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
 
        ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
 
@@ -942,11 +988,11 @@ brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
        core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
        reg_addr = ci->c_inf[core_idx].base;
        reg_addr += offsetof(struct sdpcmd_regs, intstatus);
-       brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
+       brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
 
        /* Write reset vector to address 0 */
-       brcmf_sdio_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
-                        sizeof(ci->rst_vec));
+       brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
+                         sizeof(ci->rst_vec));
 
        /* restore ARM */
        ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0);
index 507c61c991fa06c96b6adb1a0f99acefa5f74068..7ea424e207736a527b72237a62f077d5ecf572ea 100644 (file)
 
 #define BRCMF_MAX_CORENUM      6
 
-/* SDIO device ID */
-#define SDIO_DEVICE_ID_BROADCOM_43143          43143
-#define SDIO_DEVICE_ID_BROADCOM_43241          0x4324
-#define SDIO_DEVICE_ID_BROADCOM_4329           0x4329
-#define SDIO_DEVICE_ID_BROADCOM_4330           0x4330
-#define SDIO_DEVICE_ID_BROADCOM_4334           0x4334
-#define SDIO_DEVICE_ID_BROADCOM_4335_4339      0x4335
-
 struct chip_core_info {
        u16 id;
        u16 rev;
@@ -224,7 +216,7 @@ struct sdpcmd_regs {
 };
 
 int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
-                          struct chip_info **ci_ptr, u32 regs);
+                          struct chip_info **ci_ptr);
 void brcmf_sdio_chip_detach(struct chip_info **ci_ptr);
 void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
                                       struct chip_info *ci, u32 drivestrength);
index fc0d4f0129db269dd7d7139c286fa90063c3bab3..092e9c8249926ac80a6831f75ec72c818ff86c43 100644 (file)
@@ -164,11 +164,9 @@ struct brcmf_sdio;
 struct brcmf_sdio_dev {
        struct sdio_func *func[SDIO_MAX_FUNCS];
        u8 num_funcs;                   /* Supported funcs on client */
-       u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
        u32 sbwad;                      /* Save backplane window address */
-       void *bus;
+       struct brcmf_sdio *bus;
        atomic_t suspend;               /* suspend flag */
-       wait_queue_head_t request_byte_wait;
        wait_queue_head_t request_word_wait;
        wait_queue_head_t request_buffer_wait;
        struct device *dev;
@@ -185,22 +183,19 @@ struct brcmf_sdio_dev {
 };
 
 /* Register/deregister interrupt handler. */
-int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev);
-int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev);
+int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev);
+int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev);
 
 /* sdio device register access interface */
-u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
-u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
-void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data,
-                     int *ret);
-void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
-                     int *ret);
-int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
-                           void *data, bool write);
+u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
+u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
+void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data,
+                      int *ret);
+void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
+                      int *ret);
 
 /* Buffer transfer to/from device (client) core via cmd53.
  *   fn:       function number
- *   addr:     backplane address (i.e. >= regsva from attach)
  *   flags:    backplane width, address increment, sync/async
  *   buf:      pointer to memory data buffer
  *   nbytes:   number of bytes to transfer to/from buf
@@ -210,17 +205,14 @@ int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
  * Returns 0 or error code.
  * NOTE: Async operation is not currently supported.
  */
-int brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                         uint flags, struct sk_buff_head *pktq);
-int brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                         uint flags, u8 *buf, uint nbytes);
-
-int brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                         uint flags, struct sk_buff *pkt);
-int brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                         uint flags, u8 *buf, uint nbytes);
-int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-                           uint flags, struct sk_buff_head *pktq, uint totlen);
+int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
+                        struct sk_buff_head *pktq);
+int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes);
+
+int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt);
+int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes);
+int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
+                          struct sk_buff_head *pktq, uint totlen);
 
 /* Flags bits */
 
@@ -236,43 +228,16 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
  *   nbytes:   number of bytes to transfer to/from buf
  * Returns 0 or error code.
  */
-int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
-                       u8 *buf, uint nbytes);
-int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
-                    u8 *data, uint size);
+int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
+                     u8 *data, uint size);
 
 /* Issue an abort to the specified function */
-int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
-
-/* platform specific/high level functions */
-int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
-int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev);
-
-/* attach, return handler on success, NULL if failed.
- *  The handler shall be provided by all subsequent calls. No local cache
- *  cfghdl points to the starting address of pci device mapped memory
- */
-int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev);
-void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev);
-
-/* read or write one byte using cmd52 */
-int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint fnc,
-                            uint addr, u8 *byte);
-
-/* read or write 2/4 bytes using cmd53 */
-int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, uint rw, uint fnc,
-                            uint addr, u32 *word, uint nbyte);
-
-/* Watchdog timer interface for pm ops */
-void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable);
+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
 
-void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev);
-void brcmf_sdbrcm_disconnect(void *ptr);
-void brcmf_sdbrcm_isr(void *arg);
+struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
+void brcmf_sdio_remove(struct brcmf_sdio *bus);
+void brcmf_sdio_isr(struct brcmf_sdio *bus);
 
-void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick);
+void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick);
 
-void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev,
-                         wait_queue_head_t *wq);
-bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev);
 #endif                         /* _BRCM_SDH_H_ */
index 51c4de054b15e9c89c154acb93e3fff79e0c4ffa..c345c32eb6311cc528f4261375ac53b555b3a0f4 100644 (file)
@@ -1253,6 +1253,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
        bus->ops = &brcmf_usb_bus_ops;
        bus->chip = bus_pub->devid;
        bus->chiprev = bus_pub->chiprev;
+       bus->proto_type = BRCMF_PROTO_BCDC;
 
        /* Attach to the common driver interface */
        ret = brcmf_attach(dev);
index 3966fe0fcfd971418fb3ca22bfc9fcaddf7afaf7..aad83aef7d93cc7014b7bf0cec97505add3c7b90 100644 (file)
@@ -1095,10 +1095,10 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
                                             BRCMF_C_DISASSOC, NULL, 0);
                if (err) {
                        brcmf_err("WLC_DISASSOC failed (%d)\n", err);
-                       cfg80211_disconnected(vif->wdev.netdev, 0,
-                                             NULL, 0, GFP_KERNEL);
                }
                clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
+               cfg80211_disconnected(vif->wdev.netdev, 0, NULL, 0, GFP_KERNEL);
+
        }
        clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
        clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
@@ -1758,6 +1758,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
                return -EIO;
 
        clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
+       cfg80211_disconnected(ndev, reason_code, NULL, 0, GFP_KERNEL);
 
        memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
        scbval.val = cpu_to_le32(reason_code);
@@ -4359,9 +4360,6 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
 {
        struct brcmf_cfg80211_vif *vif;
 
-       if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
-               return ERR_PTR(-ENOSPC);
-
        brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n",
                  sizeof(*vif));
        vif = kzalloc(sizeof(*vif), GFP_KERNEL);
@@ -4378,21 +4376,25 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
        brcmf_init_prof(&vif->profile);
 
        list_add_tail(&vif->list, &cfg->vif_list);
-       cfg->vif_cnt++;
        return vif;
 }
 
-void brcmf_free_vif(struct brcmf_cfg80211_info *cfg,
-                   struct brcmf_cfg80211_vif *vif)
+void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
 {
        list_del(&vif->list);
-       cfg->vif_cnt--;
-
        kfree(vif);
-       if (!cfg->vif_cnt) {
-               wiphy_unregister(cfg->wiphy);
-               wiphy_free(cfg->wiphy);
-       }
+}
+
+void brcmf_cfg80211_free_netdev(struct net_device *ndev)
+{
+       struct brcmf_cfg80211_vif *vif;
+       struct brcmf_if *ifp;
+
+       ifp = netdev_priv(ndev);
+       vif = ifp->vif;
+
+       brcmf_free_vif(vif);
+       free_netdev(ndev);
 }
 
 static bool brcmf_is_linkup(const struct brcmf_event_msg *e)
@@ -4979,20 +4981,20 @@ cfg80211_p2p_attach_out:
        wl_deinit_priv(cfg);
 
 cfg80211_attach_out:
-       brcmf_free_vif(cfg, vif);
+       brcmf_free_vif(vif);
        return NULL;
 }
 
 void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
 {
-       struct brcmf_cfg80211_vif *vif;
-       struct brcmf_cfg80211_vif *tmp;
+       if (!cfg)
+               return;
 
-       wl_deinit_priv(cfg);
+       WARN_ON(!list_empty(&cfg->vif_list));
+       wiphy_unregister(cfg->wiphy);
        brcmf_btcoex_detach(cfg);
-       list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
-               brcmf_free_vif(cfg, vif);
-       }
+       wl_deinit_priv(cfg);
+       wiphy_free(cfg->wiphy);
 }
 
 static s32
@@ -5087,7 +5089,8 @@ dongle_scantime_out:
 }
 
 
-static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
+static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
+                                  u32 bw_cap[])
 {
        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
        struct ieee80211_channel *band_chan_arr;
@@ -5100,7 +5103,6 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
        enum ieee80211_band band;
        u32 channel;
        u32 *n_cnt;
-       bool ht40_allowed;
        u32 index;
        u32 ht40_flag;
        bool update;
@@ -5133,18 +5135,17 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
                        array_size = ARRAY_SIZE(__wl_2ghz_channels);
                        n_cnt = &__wl_band_2ghz.n_channels;
                        band = IEEE80211_BAND_2GHZ;
-                       ht40_allowed = (bw_cap == WLC_N_BW_40ALL);
                } else if (ch.band == BRCMU_CHAN_BAND_5G) {
                        band_chan_arr = __wl_5ghz_a_channels;
                        array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
                        n_cnt = &__wl_band_5ghz_a.n_channels;
                        band = IEEE80211_BAND_5GHZ;
-                       ht40_allowed = !(bw_cap == WLC_N_BW_20ALL);
                } else {
-                       brcmf_err("Invalid channel Sepc. 0x%x.\n", ch.chspec);
+                       brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
                        continue;
                }
-               if (!ht40_allowed && ch.bw == BRCMU_CHAN_BW_40)
+               if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) &&
+                   ch.bw == BRCMU_CHAN_BW_40)
                        continue;
                update = false;
                for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
@@ -5162,7 +5163,10 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
                                ieee80211_channel_to_frequency(ch.chnum, band);
                        band_chan_arr[index].hw_value = ch.chnum;
 
-                       if (ch.bw == BRCMU_CHAN_BW_40 && ht40_allowed) {
+                       brcmf_err("channel %d: f=%d bw=%d sb=%d\n",
+                                 ch.chnum, band_chan_arr[index].center_freq,
+                                 ch.bw, ch.sb);
+                       if (ch.bw == BRCMU_CHAN_BW_40) {
                                /* assuming the order is HT20, HT40 Upper,
                                 * HT40 lower from chanspecs
                                 */
@@ -5213,6 +5217,46 @@ exit:
        return err;
 }
 
+static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
+{
+       u32 band, mimo_bwcap;
+       int err;
+
+       band = WLC_BAND_2G;
+       err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band);
+       if (!err) {
+               bw_cap[IEEE80211_BAND_2GHZ] = band;
+               band = WLC_BAND_5G;
+               err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band);
+               if (!err) {
+                       bw_cap[IEEE80211_BAND_5GHZ] = band;
+                       return;
+               }
+               WARN_ON(1);
+               return;
+       }
+       brcmf_dbg(INFO, "fallback to mimo_bw_cap info\n");
+       mimo_bwcap = 0;
+       err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &mimo_bwcap);
+       if (err)
+               /* assume 20MHz if firmware does not give a clue */
+               mimo_bwcap = WLC_N_BW_20ALL;
+
+       switch (mimo_bwcap) {
+       case WLC_N_BW_40ALL:
+               bw_cap[IEEE80211_BAND_2GHZ] |= WLC_BW_40MHZ_BIT;
+               /* fall-thru */
+       case WLC_N_BW_20IN2G_40IN5G:
+               bw_cap[IEEE80211_BAND_5GHZ] |= WLC_BW_40MHZ_BIT;
+               /* fall-thru */
+       case WLC_N_BW_20ALL:
+               bw_cap[IEEE80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT;
+               bw_cap[IEEE80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT;
+               break;
+       default:
+               brcmf_err("invalid mimo_bw_cap value\n");
+       }
+}
 
 static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
 {
@@ -5221,13 +5265,13 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
        s32 phy_list;
        u32 band_list[3];
        u32 nmode;
-       u32 bw_cap = 0;
+       u32 bw_cap[2] = { 0, 0 };
        s8 phy;
        s32 err;
        u32 nband;
        s32 i;
-       struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
-       s32 index;
+       struct ieee80211_supported_band *bands[2] = { NULL, NULL };
+       struct ieee80211_supported_band *band;
 
        err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
                                     &phy_list, sizeof(phy_list));
@@ -5253,11 +5297,10 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
        if (err) {
                brcmf_err("nmode error (%d)\n", err);
        } else {
-               err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &bw_cap);
-               if (err)
-                       brcmf_err("mimo_bw_cap error (%d)\n", err);
+               brcmf_get_bwcap(ifp, bw_cap);
        }
-       brcmf_dbg(INFO, "nmode=%d, mimo_bw_cap=%d\n", nmode, bw_cap);
+       brcmf_dbg(INFO, "nmode=%d, bw_cap=(%d, %d)\n", nmode,
+                 bw_cap[IEEE80211_BAND_2GHZ], bw_cap[IEEE80211_BAND_5GHZ]);
 
        err = brcmf_construct_reginfo(cfg, bw_cap);
        if (err) {
@@ -5266,40 +5309,33 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
        }
 
        nband = band_list[0];
-       memset(bands, 0, sizeof(bands));
 
        for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) {
-               index = -1;
+               band = NULL;
                if ((band_list[i] == WLC_BAND_5G) &&
-                   (__wl_band_5ghz_a.n_channels > 0)) {
-                       index = IEEE80211_BAND_5GHZ;
-                       bands[index] = &__wl_band_5ghz_a;
-                       if ((bw_cap == WLC_N_BW_40ALL) ||
-                           (bw_cap == WLC_N_BW_20IN2G_40IN5G))
-                               bands[index]->ht_cap.cap |=
-                                                       IEEE80211_HT_CAP_SGI_40;
-               } else if ((band_list[i] == WLC_BAND_2G) &&
-                          (__wl_band_2ghz.n_channels > 0)) {
-                       index = IEEE80211_BAND_2GHZ;
-                       bands[index] = &__wl_band_2ghz;
-                       if (bw_cap == WLC_N_BW_40ALL)
-                               bands[index]->ht_cap.cap |=
-                                                       IEEE80211_HT_CAP_SGI_40;
-               }
+                   (__wl_band_5ghz_a.n_channels > 0))
+                       band = &__wl_band_5ghz_a;
+               else if ((band_list[i] == WLC_BAND_2G) &&
+                        (__wl_band_2ghz.n_channels > 0))
+                       band = &__wl_band_2ghz;
+               else
+                       continue;
 
-               if ((index >= 0) && nmode) {
-                       bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
-                       bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
-                       bands[index]->ht_cap.ht_supported = true;
-                       bands[index]->ht_cap.ampdu_factor =
-                                               IEEE80211_HT_MAX_AMPDU_64K;
-                       bands[index]->ht_cap.ampdu_density =
-                                               IEEE80211_HT_MPDU_DENSITY_16;
-                       /* An HT shall support all EQM rates for one spatial
-                        * stream
-                        */
-                       bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
+               if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
+                       band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+                       band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
                }
+               band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+               band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
+               band->ht_cap.ht_supported = true;
+               band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+               band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
+               /* An HT shall support all EQM rates for one spatial
+                * stream
+                */
+               band->ht_cap.mcs.rx_mask[0] = 0xff;
+               band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+               bands[band->band] = band;
        }
 
        wiphy = cfg_to_wiphy(cfg);
index d9bdaf9a72d0fd2d606a5ab041a6e283aec5770e..2dc6a074e8ede14c4d3709a2d899c390e1bd421c 100644 (file)
@@ -412,7 +412,6 @@ struct brcmf_cfg80211_info {
        struct work_struct escan_timeout_work;
        u8 *escan_ioctl_buf;
        struct list_head vif_list;
-       u8 vif_cnt;
        struct brcmf_cfg80211_vif_event vif_event;
        struct completion vif_disabled;
        struct brcmu_d11inf d11inf;
@@ -487,8 +486,7 @@ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
 struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
                                           enum nl80211_iftype type,
                                           bool pm_block);
-void brcmf_free_vif(struct brcmf_cfg80211_info *cfg,
-                   struct brcmf_cfg80211_vif *vif);
+void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
 
 s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
                          const u8 *vndr_ie_buf, u32 vndr_ie_len);
@@ -507,5 +505,6 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
                                bool fw_abort);
 void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
 void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
+void brcmf_cfg80211_free_netdev(struct net_device *ndev);
 
 #endif                         /* _wl_cfg80211_h_ */
index 84113ea16f8434fcd0ee4383aeea18c0dfe9c480..6fa5d4863782ea2575089583270186c015b810fa 100644 (file)
@@ -41,6 +41,7 @@
 #define BCM4331_CHIP_ID                0x4331
 #define BCM4334_CHIP_ID                0x4334
 #define BCM4335_CHIP_ID                0x4335
+#define BCM43362_CHIP_ID       43362
 #define BCM4339_CHIP_ID                0x4339
 
 #endif                         /* _BRCM_HW_IDS_H_ */
index 0505cc065e0d6d18ae3c292ab234a7e8b9761ba8..7ca2aa1035b2101d1d8129c1ca480724863dd507 100644 (file)
 #define WLC_N_BW_40ALL                 1
 #define WLC_N_BW_20IN2G_40IN5G         2
 
+#define WLC_BW_20MHZ_BIT               BIT(0)
+#define WLC_BW_40MHZ_BIT               BIT(1)
+#define WLC_BW_80MHZ_BIT               BIT(2)
+#define WLC_BW_160MHZ_BIT              BIT(3)
+
+/* Bandwidth capabilities */
+#define WLC_BW_CAP_20MHZ               (WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_40MHZ               (WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_80MHZ               (WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT| \
+                                        WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_160MHZ              (WLC_BW_160MHZ_BIT|WLC_BW_80MHZ_BIT| \
+                                        WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_UNRESTRICTED                0xFF
+
 /* band types */
 #define        WLC_BAND_AUTO                   0       /* auto-select */
 #define        WLC_BAND_5G                     1       /* 5 Ghz */
index acdff0f7f952e03fa25b51b47a9e83eda37d85c6..5a9ffd3a6a6caa0d1c98a27cc238de4e8e5047cb 100644 (file)
@@ -14,7 +14,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/sched.h>
 #include <linux/firmware.h>
index 090f01577dd25314651156c551a8f48299f9a852..d1270da4dfeae0ee869de0a9f3d612a9c7ac757f 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/firmware.h>
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
index b37abb9f0453b1ca530fd3f11e746b8558cc3054..6907c8fd4578d001293eaf77d4c1dbad6b96177f 100644 (file)
@@ -225,7 +225,7 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
                cw1200_set_pm(priv, &priv->powersave_mode);
                if (wait_event_interruptible_timeout(priv->ps_mode_switch_done,
                                                     !priv->ps_mode_switch_in_progress, 1*HZ) <= 0) {
-                       goto revert3;
+                       goto revert4;
                }
        }
 
@@ -254,11 +254,11 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 
        /* Stop serving thread */
        if (cw1200_bh_suspend(priv))
-               goto revert4;
+               goto revert5;
 
        ret = timer_pending(&priv->mcast_timeout);
        if (ret)
-               goto revert5;
+               goto revert6;
 
        /* Store suspend state */
        pm_state->suspend_state = state;
@@ -280,9 +280,9 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 
        return 0;
 
-revert5:
+revert6:
        WARN_ON(cw1200_bh_resume(priv));
-revert4:
+revert5:
        cw1200_resume_work(priv, &priv->bss_loss_work,
                           state->bss_loss_tmo);
        cw1200_resume_work(priv, &priv->join_timeout,
@@ -291,6 +291,7 @@ revert4:
                           state->direct_probe);
        cw1200_resume_work(priv, &priv->link_id_gc_work,
                           state->link_id_gc);
+revert4:
        kfree(state);
 revert3:
        wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_off);
index 010b252be584237c7f6b4e71f5d375332176f586..103f7bce893208c30eb692cca9aa9adf51b8d8b9 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/firmware.h>
 #include <linux/module.h>
+#include <linux/etherdevice.h>
 
 #include "cw1200.h"
 #include "sta.h"
@@ -555,8 +556,8 @@ u64 cw1200_prepare_multicast(struct ieee80211_hw *hw,
                pr_debug("[STA] multicast: %pM\n", ha->addr);
                memcpy(&priv->multicast_filter.macaddrs[count],
                       ha->addr, ETH_ALEN);
-               if (memcmp(ha->addr, broadcast_ipv4, ETH_ALEN) &&
-                   memcmp(ha->addr, broadcast_ipv6, ETH_ALEN))
+               if (!ether_addr_equal(ha->addr, broadcast_ipv4) &&
+                   !ether_addr_equal(ha->addr, broadcast_ipv6))
                        priv->has_multicast_subscription = true;
                count++;
        }
index e824d4d4a18d7e1d385d9d95f8fea195766a3ae8..0bd541175ecda7d9277e4abd33b6b6b4148bdd8c 100644 (file)
@@ -1166,8 +1166,7 @@ void cw1200_rx_cb(struct cw1200_common *priv,
                        return;
        } else if (ieee80211_is_beacon(frame->frame_control) &&
                   !arg->status && priv->vif &&
-                  !memcmp(ieee80211_get_SA(frame), priv->vif->bss_conf.bssid,
-                          ETH_ALEN)) {
+                  ether_addr_equal(ieee80211_get_SA(frame), priv->vif->bss_conf.bssid)) {
                const u8 *tim_ie;
                u8 *ies = ((struct ieee80211_mgmt *)
                          (skb->data))->u.beacon.variable;
index d39e3e24077b1dca873f0ffe0dbce6a221dbaaea..599f30f22841f9e665a485f675ad449d105c448a 100644 (file)
@@ -563,7 +563,7 @@ hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr, u16 fc,
 
        /* Possible WDS frame: either IEEE 802.11 compliant (if FromDS)
         * or own non-standard frame with 4th address after payload */
-       if (memcmp(hdr->addr1, local->dev->dev_addr, ETH_ALEN) != 0 &&
+       if (!ether_addr_equal(hdr->addr1, local->dev->dev_addr) &&
            (hdr->addr1[0] != 0xff || hdr->addr1[1] != 0xff ||
             hdr->addr1[2] != 0xff || hdr->addr1[3] != 0xff ||
             hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) {
@@ -622,12 +622,12 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
        /* check that the frame is unicast frame to us */
        if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
            IEEE80211_FCTL_TODS &&
-           memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
-           memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
+           ether_addr_equal(hdr->addr1, dev->dev_addr) &&
+           ether_addr_equal(hdr->addr3, dev->dev_addr)) {
                /* ToDS frame with own addr BSSID and DA */
        } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
                   IEEE80211_FCTL_FROMDS &&
-                  memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+                  ether_addr_equal(hdr->addr1, dev->dev_addr)) {
                /* FromDS frame with own addr as DA */
        } else
                return 0;
index 344a981a052e630a4daf5c6e6630d8703a2fb617..8bde776894695effab540ae5ee7e0f2e3abee691 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/etherdevice.h>
 
 #include "hostap_80211.h"
 #include "hostap_common.h"
@@ -103,8 +104,7 @@ netdev_tx_t hostap_data_start_xmit(struct sk_buff *skb,
                        return NETDEV_TX_OK;
                } else if (local->iw_mode == IW_MODE_INFRA &&
                           (local->wds_type & HOSTAP_WDS_AP_CLIENT) &&
-                          memcmp(skb->data + ETH_ALEN, dev->dev_addr,
-                                 ETH_ALEN) != 0) {
+                          !ether_addr_equal(skb->data + ETH_ALEN, dev->dev_addr)) {
                        /* AP client mode: send frames with foreign src addr
                         * using 4-addr WDS frames */
                        use_wds = WDS_COMPLIANT_FRAME;
index d6033a8e5deaf16319d6ab6688b99544dc1f1a0c..d36e252d2ccbc0041a5b0c1669fe396c2c18db73 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <linux/moduleparam.h>
+#include <linux/etherdevice.h>
 
 #include "hostap_wlan.h"
 #include "hostap.h"
@@ -106,13 +107,12 @@ static void ap_sta_hash_del(struct ap_data *ap, struct sta_info *sta)
 
        s = ap->sta_hash[STA_HASH(sta->addr)];
        if (s == NULL) return;
-       if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) {
+       if (ether_addr_equal(s->addr, sta->addr)) {
                ap->sta_hash[STA_HASH(sta->addr)] = s->hnext;
                return;
        }
 
-       while (s->hnext != NULL && memcmp(s->hnext->addr, sta->addr, ETH_ALEN)
-              != 0)
+       while (s->hnext != NULL && !ether_addr_equal(s->hnext->addr, sta->addr))
                s = s->hnext;
        if (s->hnext != NULL)
                s->hnext = s->hnext->hnext;
@@ -435,7 +435,7 @@ int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
             ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
                entry = list_entry(ptr, struct mac_entry, list);
 
-               if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
+               if (ether_addr_equal(entry->addr, mac)) {
                        list_del(ptr);
                        kfree(entry);
                        mac_restrictions->entries--;
@@ -459,7 +459,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
 
        spin_lock_bh(&mac_restrictions->lock);
        list_for_each_entry(entry, &mac_restrictions->mac_list, list) {
-               if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
+               if (ether_addr_equal(entry->addr, mac)) {
                        found = 1;
                        break;
                }
@@ -957,7 +957,7 @@ static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta)
        struct sta_info *s;
 
        s = ap->sta_hash[STA_HASH(sta)];
-       while (s != NULL && memcmp(s->addr, sta, ETH_ALEN) != 0)
+       while (s != NULL && !ether_addr_equal(s->addr, sta))
                s = s->hnext;
        return s;
 }
@@ -1391,7 +1391,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
        status_code = __le16_to_cpu(*pos);
        pos++;
 
-       if (memcmp(dev->dev_addr, hdr->addr2, ETH_ALEN) == 0 ||
+       if (ether_addr_equal(dev->dev_addr, hdr->addr2) ||
            ap_control_mac_deny(&ap->mac_restrictions, hdr->addr2)) {
                txt = "authentication denied";
                resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -1935,7 +1935,7 @@ static void handle_pspoll(local_info_t *local,
        PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=%pM, TA=%pM PWRMGT=%d\n",
               hdr->addr1, hdr->addr2, !!ieee80211_has_pm(hdr->frame_control));
 
-       if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+       if (!ether_addr_equal(hdr->addr1, dev->dev_addr)) {
                PDEBUG(DEBUG_AP,
                       "handle_pspoll - addr1(BSSID)=%pM not own MAC\n",
                       hdr->addr1);
@@ -2230,7 +2230,7 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
                        goto done;
                }
 
-               if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+               if (!ether_addr_equal(hdr->addr1, dev->dev_addr)) {
                        PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)=%pM"
                               " not own MAC\n", hdr->addr1);
                        goto done;
@@ -2267,13 +2267,13 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
                goto done;
        }
 
-       if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+       if (!ether_addr_equal(hdr->addr1, dev->dev_addr)) {
                PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=%pM"
                       " not own MAC\n", hdr->addr1);
                goto done;
        }
 
-       if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) {
+       if (!ether_addr_equal(hdr->addr3, dev->dev_addr)) {
                PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=%pM"
                       " not own MAC\n", hdr->addr3);
                goto done;
@@ -3035,7 +3035,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
                if (!wds) {
                        /* FromDS frame - not for us; probably
                         * broadcast/multicast in another BSS - drop */
-                       if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+                       if (ether_addr_equal(hdr->addr1, dev->dev_addr)) {
                                printk(KERN_DEBUG "Odd.. FromDS packet "
                                       "received with own BSSID\n");
                                hostap_dump_rx_80211(dev->name, skb, rx_stats);
@@ -3044,7 +3044,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
                        goto out;
                }
        } else if (stype == IEEE80211_STYPE_NULLFUNC && sta == NULL &&
-                  memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+                  ether_addr_equal(hdr->addr1, dev->dev_addr)) {
 
                if (local->hostapd) {
                        prism2_rx_80211(local->apdev, skb, rx_stats,
@@ -3073,7 +3073,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
                /* If BSSID (Addr3) is foreign, this frame is a normal
                 * broadcast frame from an IBSS network. Drop it silently.
                 * If BSSID is own, report the dropping of this frame. */
-               if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
+               if (ether_addr_equal(hdr->addr3, dev->dev_addr)) {
                        printk(KERN_DEBUG "%s: dropped received packet from %pM"
                               " with no ToDS flag "
                               "(type=0x%02x, subtype=0x%02x)\n", dev->name,
index 56cd01ca8ad0b15394017a8f298760e769ed8043..9f825f2620da749ca2d8090c55171eb021bcf77a 100644 (file)
@@ -1,7 +1,6 @@
 #define PRISM2_PCCARD
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/if.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
index c275dc1623fedeedc68025a3eec62f4f219df6c2..6df3ee561d5214725c3c881895a6056861df74e1 100644 (file)
@@ -2175,7 +2175,7 @@ static void hostap_tx_callback(local_info_t *local,
        struct hostap_tx_callback_info *cb;
 
        /* Make sure that frame was from us. */
-       if (memcmp(txdesc->addr2, local->dev->dev_addr, ETH_ALEN)) {
+       if (!ether_addr_equal(txdesc->addr2, local->dev->dev_addr)) {
                printk(KERN_DEBUG "%s: TX callback - foreign frame\n",
                       local->dev->name);
                return;
index e5090309824e53c04d1961c0fd6993e80c5aa61e..3e5fa7872b64324310593c87029fdd46c7f54fd9 100644 (file)
@@ -655,7 +655,7 @@ static int hostap_join_ap(struct net_device *dev)
                if (!local->last_scan_results)
                        break;
                entry = &local->last_scan_results[i];
-               if (memcmp(local->preferred_ap, entry->bssid, ETH_ALEN) == 0) {
+               if (ether_addr_equal(local->preferred_ap, entry->bssid)) {
                        req.channel = entry->chid;
                        break;
                }
@@ -1978,7 +1978,7 @@ static inline int prism2_translate_scan(local_info_t *local,
                list_for_each(ptr, &local->bss_list) {
                        struct hostap_bss_info *bss;
                        bss = list_entry(ptr, struct hostap_bss_info, list);
-                       if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) {
+                       if (ether_addr_equal(bss->bssid, scan->bssid)) {
                                bss->included = 1;
                                current_ev = __prism2_translate_scan(
                                        local, info, scan, bss, current_ev,
@@ -2567,7 +2567,7 @@ static int prism2_ioctl_priv_prism2_param(struct net_device *dev,
                local->passive_scan_interval = value;
                if (timer_pending(&local->passive_scan_timer))
                        del_timer(&local->passive_scan_timer);
-               if (value > 0) {
+               if (value > 0 && value < INT_MAX / HZ) {
                        local->passive_scan_timer.expires = jiffies +
                                local->passive_scan_interval * HZ;
                        add_timer(&local->passive_scan_timer);
index a1257c92afc4be8e9e35c33639edc539fd8b7e8a..67db34e56d7eb0765c5e75025e02470cae01da64 100644 (file)
@@ -155,8 +155,7 @@ int prism2_wds_add(local_info_t *local, u8 *remote_addr,
 
                if (prism2_wds_special_addr(iface->u.wds.remote_addr))
                        empty = iface;
-               else if (memcmp(iface->u.wds.remote_addr, remote_addr,
-                               ETH_ALEN) == 0) {
+               else if (ether_addr_equal(iface->u.wds.remote_addr, remote_addr)) {
                        match = iface;
                        break;
                }
@@ -214,8 +213,7 @@ int prism2_wds_del(local_info_t *local, u8 *remote_addr,
                if (iface->type != HOSTAP_INTERFACE_WDS)
                        continue;
 
-               if (memcmp(iface->u.wds.remote_addr, remote_addr,
-                          ETH_ALEN) == 0) {
+               if (ether_addr_equal(iface->u.wds.remote_addr, remote_addr)) {
                        selected = iface;
                        break;
                }
@@ -1085,7 +1083,7 @@ int prism2_sta_deauth(local_info_t *local, u16 reason)
 
        if (local->iw_mode != IW_MODE_INFRA ||
            is_zero_ether_addr(local->bssid) ||
-           memcmp(local->bssid, "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 0)
+           ether_addr_equal(local->bssid, "\x44\x44\x44\x44\x44\x44"))
                return 0;
 
        ret = prism2_sta_send_mgmt(local, local->bssid, IEEE80211_STYPE_DEAUTH,
index 05ca3402dca707d8cca9eb9f1d5432fdc44b3b7b..91158e2e961c62a96ceb8c28aaa2bef09cde8017 100644 (file)
@@ -5,7 +5,6 @@
  * Andy Warner <andyw@pobox.com> */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/if.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
index c3d067ee4db9cdbd2f34e3d5ede9461abe28f59c..3bf530d9a40f1bb2c80c877ee35ac42a76a337b0 100644 (file)
@@ -8,7 +8,6 @@
 
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/if.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
index 9244b3661d343d8908bb72ec3a4516391d1d9900..139326065bd923aad89a867774168480f7a83d0c 100644 (file)
@@ -3012,7 +3012,7 @@ static void ipw_remove_current_network(struct ipw_priv *priv)
        spin_lock_irqsave(&priv->ieee->lock, flags);
        list_for_each_safe(element, safe, &priv->ieee->network_list) {
                network = list_entry(element, struct libipw_network, list);
-               if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
+               if (ether_addr_equal(network->bssid, priv->bssid)) {
                        list_del(element);
                        list_add_tail(&network->list,
                                      &priv->ieee->network_free_list);
@@ -3921,7 +3921,7 @@ static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
        int i;
 
        for (i = 0; i < priv->num_stations; i++) {
-               if (!memcmp(priv->stations[i], bssid, ETH_ALEN)) {
+               if (ether_addr_equal(priv->stations[i], bssid)) {
                        /* Another node is active in network */
                        priv->missed_adhoc_beacons = 0;
                        if (!(priv->config & CFG_STATIC_CHANNEL))
@@ -3953,7 +3953,7 @@ static u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid)
        int i;
 
        for (i = 0; i < priv->num_stations; i++)
-               if (!memcmp(priv->stations[i], bssid, ETH_ALEN))
+               if (ether_addr_equal(priv->stations[i], bssid))
                        return i;
 
        return IPW_INVALID_STATION;
@@ -5622,7 +5622,7 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
                return 0;
        }
 
-       if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
+       if (ether_addr_equal(network->bssid, priv->bssid)) {
                IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
                                "because of the same BSSID match: %pM"
                                ".\n", print_ssid(ssid, network->ssid,
@@ -5849,7 +5849,7 @@ static int ipw_best_network(struct ipw_priv *priv,
        }
 
        if ((priv->config & CFG_STATIC_BSSID) &&
-           memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
+           !ether_addr_equal(network->bssid, priv->bssid)) {
                IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
                                "because of BSSID mismatch: %pM.\n",
                                print_ssid(ssid, network->ssid,
@@ -6988,7 +6988,7 @@ static int ipw_qos_handle_probe_response(struct ipw_priv *priv,
        }
        if ((priv->status & STATUS_ASSOCIATED) &&
            (priv->ieee->iw_mode == IW_MODE_ADHOC) && (active_network == 0)) {
-               if (memcmp(network->bssid, priv->bssid, ETH_ALEN))
+               if (!ether_addr_equal(network->bssid, priv->bssid))
                        if (network->capability & WLAN_CAPABILITY_IBSS)
                                if ((network->ssid_len ==
                                     priv->assoc_network->ssid_len) &&
@@ -8210,29 +8210,29 @@ static int is_network_packet(struct ipw_priv *priv,
        switch (priv->ieee->iw_mode) {
        case IW_MODE_ADHOC:     /* Header: Dest. | Source    | BSSID */
                /* packets from our adapter are dropped (echo) */
-               if (!memcmp(header->addr2, priv->net_dev->dev_addr, ETH_ALEN))
+               if (ether_addr_equal(header->addr2, priv->net_dev->dev_addr))
                        return 0;
 
                /* {broad,multi}cast packets to our BSSID go through */
                if (is_multicast_ether_addr(header->addr1))
-                       return !memcmp(header->addr3, priv->bssid, ETH_ALEN);
+                       return ether_addr_equal(header->addr3, priv->bssid);
 
                /* packets to our adapter go through */
-               return !memcmp(header->addr1, priv->net_dev->dev_addr,
-                              ETH_ALEN);
+               return ether_addr_equal(header->addr1,
+                                       priv->net_dev->dev_addr);
 
        case IW_MODE_INFRA:     /* Header: Dest. | BSSID | Source */
                /* packets from our adapter are dropped (echo) */
-               if (!memcmp(header->addr3, priv->net_dev->dev_addr, ETH_ALEN))
+               if (ether_addr_equal(header->addr3, priv->net_dev->dev_addr))
                        return 0;
 
                /* {broad,multi}cast packets to our BSS go through */
                if (is_multicast_ether_addr(header->addr1))
-                       return !memcmp(header->addr2, priv->bssid, ETH_ALEN);
+                       return ether_addr_equal(header->addr2, priv->bssid);
 
                /* packets to our adapter go through */
-               return !memcmp(header->addr1, priv->net_dev->dev_addr,
-                              ETH_ALEN);
+               return ether_addr_equal(header->addr1,
+                                       priv->net_dev->dev_addr);
        }
 
        return 1;
@@ -8260,7 +8260,7 @@ static  int is_duplicate_packet(struct ipw_priv *priv,
                        list_for_each(p, &priv->ibss_mac_hash[index]) {
                                entry =
                                    list_entry(p, struct ipw_ibss_seq, list);
-                               if (!memcmp(entry->mac, mac, ETH_ALEN))
+                               if (ether_addr_equal(entry->mac, mac))
                                        break;
                        }
                        if (p == &priv->ibss_mac_hash[index]) {
@@ -8329,7 +8329,7 @@ static void ipw_handle_mgmt_packet(struct ipw_priv *priv,
              IEEE80211_STYPE_PROBE_RESP) ||
             (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) ==
              IEEE80211_STYPE_BEACON))) {
-               if (!memcmp(header->addr3, priv->bssid, ETH_ALEN))
+               if (ether_addr_equal(header->addr3, priv->bssid))
                        ipw_add_station(priv, header->addr2);
        }
 
@@ -9045,7 +9045,7 @@ static int ipw_wx_set_wap(struct net_device *dev,
        }
 
        priv->config |= CFG_STATIC_BSSID;
-       if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) {
+       if (ether_addr_equal(priv->bssid, wrqu->ap_addr.sa_data)) {
                IPW_DEBUG_WX("BSSID set to current BSSID.\n");
                mutex_unlock(&priv->mutex);
                return 0;
index 570d6fb889671b514a996bc468eab1ac39efcb31..aa301d1eee3cbe50435e48f6fdf5ba84ed7f22d4 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 
index 9ffe65931b293e4d6e4dd1f685dd75376e8dce96..a586a85bfcfe88ccd6378ad476caca6b9aa10a15 100644 (file)
@@ -874,13 +874,13 @@ void libipw_rx_any(struct libipw_device *ieee,
        switch (ieee->iw_mode) {
        case IW_MODE_ADHOC:
                /* our BSS and not from/to DS */
-               if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0)
+               if (ether_addr_equal(hdr->addr3, ieee->bssid))
                if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
                        /* promisc: get all */
                        if (ieee->dev->flags & IFF_PROMISC)
                                is_packet_for_us = 1;
                        /* to us */
-                       else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
+                       else if (ether_addr_equal(hdr->addr1, ieee->dev->dev_addr))
                                is_packet_for_us = 1;
                        /* mcast */
                        else if (is_multicast_ether_addr(hdr->addr1))
@@ -889,18 +889,18 @@ void libipw_rx_any(struct libipw_device *ieee,
                break;
        case IW_MODE_INFRA:
                /* our BSS (== from our AP) and from DS */
-               if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0)
+               if (ether_addr_equal(hdr->addr2, ieee->bssid))
                if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
                        /* promisc: get all */
                        if (ieee->dev->flags & IFF_PROMISC)
                                is_packet_for_us = 1;
                        /* to us */
-                       else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
+                       else if (ether_addr_equal(hdr->addr1, ieee->dev->dev_addr))
                                is_packet_for_us = 1;
                        /* mcast */
                        else if (is_multicast_ether_addr(hdr->addr1)) {
                                /* not our own packet bcasted from AP */
-                               if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))
+                               if (!ether_addr_equal(hdr->addr3, ieee->dev->dev_addr))
                                        is_packet_for_us = 1;
                        }
                }
@@ -1468,7 +1468,7 @@ static inline int is_same_network(struct libipw_network *src,
         * as one network */
        return ((src->ssid_len == dst->ssid_len) &&
                (src->channel == dst->channel) &&
-               ether_addr_equal(src->bssid, dst->bssid) &&
+               ether_addr_equal_64bits(src->bssid, dst->bssid) &&
                !memcmp(src->ssid, dst->ssid, src->ssid_len));
 }
 
index aea667b430c3ac7e70295562f33de2227813a198..9a45f6f626f69633c938bd386242cdacff6496e7 100644 (file)
@@ -25,7 +25,6 @@
  *****************************************************************************/
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <net/mac80211.h>
index f09e257759d5a930cfdaa1c2a69484355677403f..d37a6fd90d400a6dfd90d20cdf02d73e7e536d42 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
@@ -466,10 +465,10 @@ il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header)
        switch (il->iw_mode) {
        case NL80211_IFTYPE_ADHOC:      /* Header: Dest. | Source    | BSSID */
                /* packets to our IBSS update information */
-               return ether_addr_equal(header->addr3, il->bssid);
+               return ether_addr_equal_64bits(header->addr3, il->bssid);
        case NL80211_IFTYPE_STATION:    /* Header: Dest. | AP{BSSID} | Source */
                /* packets to our IBSS update information */
-               return ether_addr_equal(header->addr2, il->bssid);
+               return ether_addr_equal_64bits(header->addr2, il->bssid);
        default:
                return 1;
        }
index 3ccbaf791b48bfea34d3053d4d7d3cce6e165b22..4d5e33259ca894d66fe2edc997b8d3ed6580467b 100644 (file)
@@ -24,7 +24,6 @@
  *
  *****************************************************************************/
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <net/mac80211.h>
index 777a578294bdc3ff35712b1a83261de7c46c24ce..fe47db9c20cd2428549b6c520920abed84140487 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
index a27b14cfeaec05753bb64fe8708ec7c25065995c..02e8233ccf29865e988eed0be9036c7dfc2179c8 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/lockdep.h>
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -3746,10 +3745,10 @@ il_full_rxon_required(struct il_priv *il)
 
        /* These items are only settable from the full RXON command */
        CHK(!il_is_associated(il));
-       CHK(!ether_addr_equal(staging->bssid_addr, active->bssid_addr));
-       CHK(!ether_addr_equal(staging->node_addr, active->node_addr));
-       CHK(!ether_addr_equal(staging->wlap_bssid_addr,
-                             active->wlap_bssid_addr));
+       CHK(!ether_addr_equal_64bits(staging->bssid_addr, active->bssid_addr));
+       CHK(!ether_addr_equal_64bits(staging->node_addr, active->node_addr));
+       CHK(!ether_addr_equal_64bits(staging->wlap_bssid_addr,
+                                    active->wlap_bssid_addr));
        CHK_NEQ(staging->dev_type, active->dev_type);
        CHK_NEQ(staging->channel, active->channel);
        CHK_NEQ(staging->air_propagation, active->air_propagation);
index 23d5f0275ce98e1cde6c05e7b9a1654c870774ea..562772d851021e390575868ece4f3fbf04068ede 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 1b0f0d502568700d096215b92fc1a1dce1afeb19..be1086c87157c158834d622546e8bfc2b25b7dff 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index cfddde194940e2a183c1685bf4eb445a4550f9b9..aeae4e80ea402d475c5df89481a8e377ccf10397 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index ebdac909f0cd750bffbe2b46bd49ea4975079340..751ae1d10b7f6d27650e1a1a966a65651dd2ca30 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f69301e505ee0e8968d5a9b90f9dcb3404c1f843..d2fe2596d54ec4525a7661a9b381f3e5352bae61 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index 7434d9edf3b773566530b79eb542a8431bbfb24c..3441f70d0ff911594dfd4066e782f0ca042e02d6 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index 352c6cb7b4f17d5b85facf619839f93beaec5ade..7b140e487deb8da42a19d669e4428830516470c6 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index 33c7e15d24f5c64584e1f3c870a6d3a851258751..ca4d6692cc4eb94907cfe32acd227df07f57046a 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -27,7 +27,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
index 8749dcfe695fd22407fbeb653a5fa249c9832e36..6a0817d9c4fa05f15e1ceffd4272925451994f80 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index 3d5bdc4217a8901a3c4fb46ad6ffc091809bf9b4..576f7ee38ca5894150cba0e54eff4bcc5ff2f079 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -29,7 +29,6 @@
 #include <linux/etherdevice.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/sched.h>
 #include <net/mac80211.h>
 
index 217f1ca321a0fecb7aaa876a5a22b5ec214b5818..40eb5e691475c5280c718893ec084fa2454e4d1c 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
@@ -28,7 +28,6 @@
  *****************************************************************************/
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -322,12 +321,6 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
 
        flush_workqueue(priv->workqueue);
 
-       /* User space software may expect getting rfkill changes
-        * even if interface is down, trans->down will leave the RF
-        * kill interrupt enabled
-        */
-       iwl_trans_stop_hw(priv->trans, false);
-
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
index 7aad766865cf5d09fb5f0ab7b150189039bccd53..ba1b1ea54252c8d1ce9018263c42ef88fca9d50f 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
@@ -1313,7 +1313,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
        }
 
        /* Reset chip to save power until we load uCode during "up". */
-       iwl_trans_stop_hw(priv->trans, false);
+       iwl_trans_stop_device(priv->trans);
 
        priv->nvm_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg,
                                                  priv->eeprom_blob,
@@ -1458,7 +1458,7 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
 
        dev_kfree_skb(priv->beacon_skb);
 
-       iwl_trans_stop_hw(priv->trans, true);
+       iwl_trans_op_mode_leave(priv->trans);
        ieee80211_free_hw(priv->hw);
 }
 
index 77cb59712235035c689034575bfd58794b933245..b4e61417013aff585bf8dcfa33b8fa9e3c5c84c6 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
@@ -30,7 +30,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <net/mac80211.h>
 #include "iwl-io.h"
 #include "iwl-debug.h"
index 7b03e1342d47076aa0ad8cf662e543c45b1e8be1..570d3a5e4670058dbb68b278e0b682e2a008ce9c 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
index b647e506564cb78cd6117a70c0e09a3036c69d7b..0977d93b529d3ce11fde93ac1e1c4ff626415a13 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -24,7 +24,6 @@
  *
  *****************************************************************************/
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <net/mac80211.h>
index 41988f4b8a5add9ec1c2f87617f8cc64913cd8dc..bdd5644a400bc780a2c7fed99dca5b482a1cdcd9 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index d71776dd1e6adcc16a0a9baa7e557588b2e1b27c..b68bb2f4d2c22c08c3590ca2839f7912550bfa6a 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portionhelp of the ieee80211 subsystem header files.
index d7ce2f12a90724a4e4b046908311c3ff1a35a1f4..503a81e581855729fde646408a8ae33b0195539f 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index 928f8640a0a7965aebfb5c429265ac71a4970f88..be98b913ed582046d6598d0cf7454cf3bd8278cc 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index c3c13ce96eb0f6217ae3971a389d0bcc7e041528..c0d070c5df5ed73e14a64e141d6a7d2f2a3133b6 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
index fbeee081ee2fccde51f0a227f6d9053f472722af..058c5892c427afdf3df48038bf8e715017d379c6 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
@@ -30,7 +30,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <net/mac80211.h>
 #include "iwl-io.h"
 #include "iwl-modparams.h"
index 9356c4b908ca58b55652843e6b7c7e5a43895f9e..507726534b845674655be7469f4f8ca85ee29a87 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
index e12b1a63c484635f64a23f0e27904045a8185cc2..a6839dfcb82dd75029c1e377bbebb078464a8792 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -29,7 +29,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ieee80211.h>
 #include "iwl-io.h"
index 63637949a146d65246f9d2da0381ec8697e6e4a9..f59709a9b79d6ba95ac26e6a8a1f9ee51586e3d5 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -28,7 +28,6 @@
  *****************************************************************************/
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 
 #include "iwl-io.h"
 #include "iwl-agn-hw.h"
index 0d2afe098afce81d1000d658bee9f788b632f797..854ba84ccb730995f0d786d26a85a1c2fc14c0dc 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index c727ec7c90a65ec1f760c6e0cc53b3af026850e4..3e63323637f3f593dd895528dac4e5fb794fdb4c 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index ecc01e1a61a1d14107ca523c6fd7339fe380c5d8..6674f2c4541c183fbae6c2a1bb0861d9eb3a966f 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index 8ac305be68f489be533606cb8260dbfd4dc5cfda..8048de90233fa038545e9d752eaaffbfc3968c72 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index 3c34a72a5d64769b8bbf156f9a74d4748fcb0228..2a59da2ff87aaf278b65983e1735cbc1eeb49d2d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -108,7 +108,7 @@ static const struct iwl_base_params iwl7000_base_params = {
 };
 
 static const struct iwl_ht_params iwl7000_ht_params = {
-       .use_rts_for_aggregation = true, /* use rts/cts protection */
+       .stbc = true,
        .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
 };
 
index 6d73f943cefafb2dfb2489b4f1b31a846f833230..7f37fb86837b7a46569ba74f90df0a7bdb8d0271 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 0b916249669ed25139db177649e5adcd98f74b7b..1ced525157dc20b6c5ed0546a4ee762cfbcd6784 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -162,12 +162,14 @@ struct iwl_base_params {
 };
 
 /*
+ * @stbc: support Tx STBC and 1*SS Rx STBC
  * @use_rts_for_aggregation: use rts/cts protection for HT traffic
  * @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40
  */
 struct iwl_ht_params {
        enum ieee80211_smps_mode smps_mode;
        const bool ht_greenfield_support; /* if used set to true */
+       const bool stbc;
        bool use_rts_for_aggregation;
        u8 ht40_bands;
 };
index da4eca8b3007feabb267a1710c95a70306224455..9d325516c42d80111eb2336c2ffe1a4b1f2c3d99 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
                                 CSR_INT_BIT_RF_KILL | \
                                 CSR_INT_BIT_SW_RX   | \
                                 CSR_INT_BIT_WAKEUP  | \
-                                CSR_INT_BIT_ALIVE)
+                                CSR_INT_BIT_ALIVE   | \
+                                CSR_INT_BIT_RX_PERIODIC)
 
 /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
 #define CSR_FH_INT_BIT_ERR       (1 << 31) /* Error */
index b2bb32a781ddd9675efe77da6e4d164de45d0b60..a75aac986a23ebd80872f9164ee45d1b1e96e4bd 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project.
  *
index 8f61c717f619c4fc0e979c6c57c005529550529e..23e7351e02decaa49026b8f628c67990f1607d2a 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2009 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index 684c416d34936c5ecdb6451f2d3707babae6b180..78bd41bf34b0f04dac4d056d470ac30a80b212c8 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2009 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
index ff570027e9dd9fa02f3e8360af6966b480c68069..c3728163be463224b4e3eb38b5573aa85370e193 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -322,6 +322,41 @@ static void set_sec_offset(struct iwl_firmware_pieces *pieces,
        pieces->img[type].sec[sec].offset = offset;
 }
 
+static int iwl_store_cscheme(struct iwl_fw *fw, const u8 *data, const u32 len)
+{
+       int i, j;
+       struct iwl_fw_cscheme_list *l = (struct iwl_fw_cscheme_list *)data;
+       struct iwl_fw_cipher_scheme *fwcs;
+       struct ieee80211_cipher_scheme *cs;
+       u32 cipher;
+
+       if (len < sizeof(*l) ||
+           len < sizeof(l->size) + l->size * sizeof(l->cs[0]))
+               return -EINVAL;
+
+       for (i = 0, j = 0; i < IWL_UCODE_MAX_CS && i < l->size; i++) {
+               fwcs = &l->cs[j];
+               cipher = le32_to_cpu(fwcs->cipher);
+
+               /* we skip schemes with zero cipher suite selector */
+               if (!cipher)
+                       continue;
+
+               cs = &fw->cs[j++];
+               cs->cipher = cipher;
+               cs->iftype = BIT(NL80211_IFTYPE_STATION);
+               cs->hdr_len = fwcs->hdr_len;
+               cs->pn_len = fwcs->pn_len;
+               cs->pn_off = fwcs->pn_off;
+               cs->key_idx_off = fwcs->key_idx_off;
+               cs->key_idx_mask = fwcs->key_idx_mask;
+               cs->key_idx_shift = fwcs->key_idx_shift;
+               cs->mic_len = fwcs->mic_len;
+       }
+
+       return 0;
+}
+
 /*
  * Gets uCode section from tlv.
  */
@@ -729,6 +764,10 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
                                return -EINVAL;
                        }
                        break;
+               case IWL_UCODE_TLV_CSCHEME:
+                       if (iwl_store_cscheme(&drv->fw, tlv_data, tlv_len))
+                               goto invalid_tlv_len;
+                       break;
                default:
                        IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
                        break;
index 429337a2b9a15189c0c0fefc94389a884e3b43f3..592c01e11013c3ce74264f49951c29eff84610c4 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -67,7 +67,7 @@
 /* for all modules */
 #define DRV_NAME        "iwlwifi"
 #define IWLWIFI_VERSION "in-tree:"
-#define DRV_COPYRIGHT  "Copyright(c) 2003-2013 Intel Corporation"
+#define DRV_COPYRIGHT  "Copyright(c) 2003- 2014 Intel Corporation"
 #define DRV_AUTHOR     "<ilw@linux.intel.com>"
 
 
index f4a6d317a023aad241ac4f15351a1cc2deae7a2c..c44cf1149648860e4e8faa4630140e8bb76ae6b3 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -751,6 +751,13 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
        ht_info->ht_supported = true;
        ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40;
 
+       if (cfg->ht_params->stbc) {
+               ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+
+               if (tx_chains > 1)
+                       ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
+       }
+
        if (iwlwifi_mod_params.amsdu_size_8K)
                ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
 
index d73304a23ec203dbdf1df8cc65e7092b2d5aaa37..e3c7deafabe6e71abd012751a59655aa977ef980 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index e5f2e362ab0b293665636aad41f844e29dfbf34e..25d0105741dbee2b1a292d10c1b6cc56ce3f41d5 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 8e941f8bd7d62158dc92e5a102b54b71b047e174..a6d3bdf82cdd47133686f647450dab3cd437c0cd 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 484d318245fb91e21705a7c11dad7c30d66d69d7..9564ae173d060a46bd34c60970ce77d6eb483a73 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 6c6c35c5228cabd71d1520f533af7bd3adf8ad26..88e2d6eb569f4f23ba7696178ffe96135dfdb508 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -125,6 +125,7 @@ enum iwl_ucode_tlv_type {
        IWL_UCODE_TLV_SECURE_SEC_INIT   = 25,
        IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26,
        IWL_UCODE_TLV_NUM_OF_CPU        = 27,
+       IWL_UCODE_TLV_CSCHEME           = 28,
 };
 
 struct iwl_ucode_tlv {
index 75db087120c30fc8f2201f1f4de1be4d3e8e270c..5f1493c44097c5fc0543e0c886a96b9180522841 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -92,6 +92,9 @@
  * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
  * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
  *     containing CAM (Continuous Active Mode) indication.
+ * @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a
+ *     single bound interface).
+ * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
  */
 enum iwl_ucode_tlv_flag {
        IWL_UCODE_TLV_FLAGS_PAN                 = BIT(0),
@@ -113,7 +116,9 @@ enum iwl_ucode_tlv_flag {
        IWL_UCODE_TLV_FLAGS_SCHED_SCAN          = BIT(17),
        IWL_UCODE_TLV_FLAGS_STA_KEY_CMD         = BIT(19),
        IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD       = BIT(20),
+       IWL_UCODE_TLV_FLAGS_P2P_PS              = BIT(21),
        IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT       = BIT(24),
+       IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD        = BIT(26),
 };
 
 /* The default calibrate table size if not specified by firmware file */
@@ -209,6 +214,44 @@ enum iwl_fw_phy_cfg {
        FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
 };
 
+#define IWL_UCODE_MAX_CS               1
+
+/**
+ * struct iwl_fw_cipher_scheme - a cipher scheme supported by FW.
+ * @cipher: a cipher suite selector
+ * @flags: cipher scheme flags (currently reserved for a future use)
+ * @hdr_len: a size of MPDU security header
+ * @pn_len: a size of PN
+ * @pn_off: an offset of pn from the beginning of the security header
+ * @key_idx_off: an offset of key index byte in the security header
+ * @key_idx_mask: a bit mask of key_idx bits
+ * @key_idx_shift: bit shift needed to get key_idx
+ * @mic_len: mic length in bytes
+ * @hw_cipher: a HW cipher index used in host commands
+ */
+struct iwl_fw_cipher_scheme {
+       __le32 cipher;
+       u8 flags;
+       u8 hdr_len;
+       u8 pn_len;
+       u8 pn_off;
+       u8 key_idx_off;
+       u8 key_idx_mask;
+       u8 key_idx_shift;
+       u8 mic_len;
+       u8 hw_cipher;
+} __packed;
+
+/**
+ * struct iwl_fw_cscheme_list - a cipher scheme list
+ * @size: a number of entries
+ * @cs: cipher scheme entries
+ */
+struct iwl_fw_cscheme_list {
+       u8 size;
+       struct iwl_fw_cipher_scheme cs[];
+} __packed;
+
 /**
  * struct iwl_fw - variables associated with the firmware
  *
@@ -224,6 +267,7 @@ enum iwl_fw_phy_cfg {
  * @inst_evtlog_size: event log size for runtime ucode.
  * @inst_errlog_ptr: error log offfset for runtime ucode.
  * @mvm_fw: indicates this is MVM firmware
+ * @cipher_scheme: optional external cipher scheme.
  */
 struct iwl_fw {
        u32 ucode_ver;
@@ -243,6 +287,8 @@ struct iwl_fw {
        u32 phy_config;
 
        bool mvm_fw;
+
+       struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
 };
 
 static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw)
index ad8e19a56eca034bf231c001ba16c0775fa047a3..f98175a0d35b7e508c0e71b7fa10c8c0fc7c22e1 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project.
  *
index 63d10ec08dbc2f894ea769169d17d0be2027a4c4..c339c1bed08056fe217c54c0825404d9618b2768 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project.
  *
index a1f580c0c6c6e9e80164421e157eb82b67fa007c..0a84ade7edac25b01d28df63158669083c442b8c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 940b8a9d5285ad7a54ecd3cce7623bc19e59a0b6..b5bc959b1dfe0bed54cf9423c6f01c23e332062e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 2e2f1c8c99f989023ab80a1244eb5b5b55164810..95af97a6c2cfa3886b6aa4fa5f1bb1213854cdf7 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 94aef22df73a9f772429f536aa11e71ca98d51d2..1b61cb5299484d79aee36d27e9a4647b05bd1866 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -263,13 +263,20 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
                                  struct iwl_nvm_data *data,
                                  struct ieee80211_sta_vht_cap *vht_cap)
 {
+       int num_ants = num_of_ant(data->valid_rx_ant);
+       int bf_sts_cap = num_ants - 1;
+
        vht_cap->vht_supported = true;
 
        vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 |
                       IEEE80211_VHT_CAP_RXSTBC_1 |
                       IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+                      bf_sts_cap << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
                       7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
 
+       if (num_ants > 1)
+               vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
+
        if (iwlwifi_mod_params.amsdu_size_8K)
                vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
 
@@ -283,16 +290,22 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
 
-       if (num_of_ant(data->valid_rx_ant) == 1 ||
+       /* Max rate for Long GI NSS=2 80Mhz is 780Mbps */
+       vht_cap->vht_mcs.rx_highest = cpu_to_le16(780);
+
+       if (num_ants == 1 ||
            cfg->rx_with_siso_diversity) {
                vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
                                IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
                /* this works because NOT_SUPPORTED == 3 */
                vht_cap->vht_mcs.rx_mcs_map |=
                        cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2);
+               /* Max rate for Long GI NSS=1 80Mhz is 390Mbps */
+               vht_cap->vht_mcs.rx_highest = cpu_to_le16(390);
        }
 
        vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
+       vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest;
 }
 
 static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
index 3325059c52d49d97c289fab319946fddd0a40c57..0c4399aba8c6bfcbbee990f964296543563dfbe1 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 976448a57d02649a7263b499bcc4974a5a1db18c..b5be51f3cd3d15c669e92e9de2ef95749cdb33aa 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -155,14 +155,12 @@ void iwl_opmode_deregister(const char *name);
 
 /**
  * struct iwl_op_mode - operational mode
+ * @ops - pointer to its own ops
  *
  * This holds an implementation of the mac80211 / fw API.
- *
- * @ops - pointer to its own ops
  */
 struct iwl_op_mode {
        const struct iwl_op_mode_ops *ops;
-       const struct iwl_trans *trans;
 
        char op_mode_specific[0] __aligned(sizeof(void *));
 };
index 1a405ae6a9c59a00f95936f25bb2602abf1751d7..fa77d63a277a393e913e154a1323237801496cee 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index ce983af79644310050a11297813927e3ece3fecf..9ee18d0d2d01ab40693410cacfff9f50cc8dcff7 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index f6412dae26590cbf2f66ae774b11aaf402721179..d69b0fb0a434086eff6cf0a5cb8ea34f69c81e6b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 143292b4dbbffeac763f86d5c9d9b1badae1aecc..8d1b5ed3502a486258b8e4bc384e07effb834b33 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,7 @@
 #include "iwl-debug.h"
 #include "iwl-config.h"
 #include "iwl-fw.h"
+#include "iwl-op-mode.h"
 
 /**
  * DOC: Transport layer - what is it ?
  *        start_fw
  *
  *     5) Then when finished (or reset):
- *        stop_fw (a.k.a. stop device for the moment)
- *        stop_hw
+ *        stop_device
  *
  *     6) Eventually, the free function will be called.
  */
@@ -317,6 +317,24 @@ enum iwl_d3_status {
        IWL_D3_STATUS_RESET,
 };
 
+/**
+ * enum iwl_trans_status: transport status flags
+ * @STATUS_SYNC_HCMD_ACTIVE: a SYNC command is being processed
+ * @STATUS_DEVICE_ENABLED: APM is enabled
+ * @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up)
+ * @STATUS_INT_ENABLED: interrupts are enabled
+ * @STATUS_RFKILL: the HW RFkill switch is in KILL position
+ * @STATUS_FW_ERROR: the fw is in error state
+ */
+enum iwl_trans_status {
+       STATUS_SYNC_HCMD_ACTIVE,
+       STATUS_DEVICE_ENABLED,
+       STATUS_TPOWER_PMI,
+       STATUS_INT_ENABLED,
+       STATUS_RFKILL,
+       STATUS_FW_ERROR,
+};
+
 /**
  * struct iwl_trans_config - transport configuration
  *
@@ -361,9 +379,7 @@ struct iwl_trans;
  *
  * @start_hw: starts the HW- from that point on, the HW can send interrupts
  *     May sleep
- * @stop_hw: stops the HW- from that point on, the HW will be in low power but
- *     will still issue interrupt if the HW RF kill is triggered unless
- *     op_mode_leaving is true.
+ * @op_mode_leave: Turn off the HW RF kill indication if on
  *     May sleep
  * @start_fw: allocates and inits all the resources for the transport
  *     layer. Also kick a fw image.
@@ -371,8 +387,11 @@ struct iwl_trans;
  * @fw_alive: called when the fw sends alive notification. If the fw provides
  *     the SCD base address in SRAM, then provide it here, or 0 otherwise.
  *     May sleep
- * @stop_device:stops the whole device (embedded CPU put to reset)
- *     May sleep
+ * @stop_device: stops the whole device (embedded CPU put to reset) and stops
+ *     the HW. From that point on, the HW will be in low power but will still
+ *     issue interrupt if the HW RF kill is triggered. This callback must do
+ *     the right thing and not crash even if start_hw() was called but not
+ *     start_fw(). May sleep
  * @d3_suspend: put the device into the correct mode for WoWLAN during
  *     suspend. This is optional, if not implemented WoWLAN will not be
  *     supported. This callback may sleep.
@@ -418,7 +437,7 @@ struct iwl_trans;
 struct iwl_trans_ops {
 
        int (*start_hw)(struct iwl_trans *iwl_trans);
-       void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving);
+       void (*op_mode_leave)(struct iwl_trans *iwl_trans);
        int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw,
                        bool run_in_rfkill);
        void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
@@ -479,6 +498,7 @@ enum iwl_trans_state {
  * @ops - pointer to iwl_trans_ops
  * @op_mode - pointer to the op_mode
  * @cfg - pointer to the configuration
+ * @status: a bit-mask of transport status flags
  * @dev - pointer to struct device * that represents the device
  * @hw_id: a u32 with the ID of the device / subdevice.
  *     Set during transport allocation.
@@ -499,6 +519,7 @@ struct iwl_trans {
        struct iwl_op_mode *op_mode;
        const struct iwl_cfg *cfg;
        enum iwl_trans_state state;
+       unsigned long status;
 
        struct device *dev;
        u32 hw_rev;
@@ -540,15 +561,14 @@ static inline int iwl_trans_start_hw(struct iwl_trans *trans)
        return trans->ops->start_hw(trans);
 }
 
-static inline void iwl_trans_stop_hw(struct iwl_trans *trans,
-                                    bool op_mode_leaving)
+static inline void iwl_trans_op_mode_leave(struct iwl_trans *trans)
 {
        might_sleep();
 
-       trans->ops->stop_hw(trans, op_mode_leaving);
+       if (trans->ops->op_mode_leave)
+               trans->ops->op_mode_leave(trans);
 
-       if (op_mode_leaving)
-               trans->op_mode = NULL;
+       trans->op_mode = NULL;
 
        trans->state = IWL_TRANS_NO_FW;
 }
@@ -570,6 +590,7 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
 
        WARN_ON_ONCE(!trans->rx_mpdu_cmd);
 
+       clear_bit(STATUS_FW_ERROR, &trans->status);
        return trans->ops->start_fw(trans, fw, run_in_rfkill);
 }
 
@@ -601,6 +622,13 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
 {
        int ret;
 
+       if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) &&
+                    test_bit(STATUS_RFKILL, &trans->status)))
+               return -ERFKILL;
+
+       if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
+               return -EIO;
+
        if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) {
                IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
                return -EIO;
@@ -640,6 +668,9 @@ static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
 static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
                               struct iwl_device_cmd *dev_cmd, int queue)
 {
+       if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
+               return -EIO;
+
        if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
                IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
 
@@ -657,9 +688,6 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
 
 static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue)
 {
-       if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
-               IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
        trans->ops->txq_disable(trans, queue);
 }
 
@@ -760,7 +788,8 @@ static inline u32 iwl_trans_write_mem32(struct iwl_trans *trans, u32 addr,
 
 static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
 {
-       trans->ops->set_pmi(trans, state);
+       if (trans->ops->set_pmi)
+               trans->ops->set_pmi(trans, state);
 }
 
 static inline void
@@ -780,6 +809,16 @@ iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags)
        __release(nic_access);
 }
 
+static inline void iwl_trans_fw_error(struct iwl_trans *trans)
+{
+       if (WARN_ON_ONCE(!trans->op_mode))
+               return;
+
+       /* prevent double restarts due to the same erroneous FW */
+       if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status))
+               iwl_op_mode_nic_error(trans->op_mode);
+}
+
 /*****************************************************
 * driver (transport) register/unregister functions
 ******************************************************/
index 285d8c7486f5a8262209f641d704424036fecce7..f98ec2b238989da818cb1b4af67f6c6a319c8de4 100644 (file)
@@ -1,10 +1,9 @@
 obj-$(CONFIG_IWLMVM)   += iwlmvm.o
 iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
-iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
+iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
 iwlmvm-y += scan.o time-event.o rs.o
 iwlmvm-y += power.o power_legacy.o bt-coex.o
 iwlmvm-y += led.o tt.o
-iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
 iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
 iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
 
index 93fd1457954bcd43cc5f833de4f8b1b188b84d96..a1376539d2dc7a0af9563ff3716745e693f4384e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -183,15 +183,29 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
        if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
                return -EINVAL;
 
+       /*
+        * Update SF - Disable if needed. if this fails, SF might still be on
+        * while many macs are bound, which is forbidden - so fail the binding.
+        */
+       if (iwl_mvm_sf_update(mvm, vif, false))
+               return -EINVAL;
+
        return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
 }
 
 int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       int ret;
 
        if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
                return -EINVAL;
 
-       return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
+       ret = iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
+
+       if (!ret)
+               if (iwl_mvm_sf_update(mvm, vif, true))
+                       IWL_ERR(mvm, "Failed to update SF state\n");
+
+       return ret;
 }
index d126245c48dea219d2161221a56dd0709cfd35f8..76cde6ce6551dc0a9996a91edc36cad5b40e5588 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -294,9 +294,9 @@ static const __le64 iwl_ci_mask[][3] = {
                cpu_to_le64(0x0)
        },
        {
-               cpu_to_le64(0xFE00000000ULL),
+               cpu_to_le64(0xFFC0000000ULL),
                cpu_to_le64(0x0ULL),
-               cpu_to_le64(0x0)
+               cpu_to_le64(0x0ULL)
        },
 };
 
index 4b6d670c35092d18679e8437ce5dbeb14ecf7702..036857698565809b302b6043032cf0793c45d171 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 665f87e788d6ec2a78e9ab1ba6a3af8795c2c752..f04d2f4d80cde5bccf2a12b0ce000e15633dc16d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 67f6a207165315d709cda315c9205de286c88789..0e29cd83a06a83c158860a5523549edf7e3c44db 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include "mvm.h"
 #include "debugfs.h"
 
+static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
+                                struct ieee80211_vif *vif,
+                                enum iwl_dbgfs_pm_mask param, int val)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm;
+
+       dbgfs_pm->mask |= param;
+
+       switch (param) {
+       case MVM_DEBUGFS_PM_KEEP_ALIVE: {
+               struct ieee80211_hw *hw = mvm->hw;
+               int dtimper = hw->conf.ps_dtim_period ?: 1;
+               int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
+
+               IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
+               if (val * MSEC_PER_SEC < 3 * dtimper_msec)
+                       IWL_WARN(mvm,
+                                "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
+                                val * MSEC_PER_SEC, 3 * dtimper_msec);
+               dbgfs_pm->keep_alive_seconds = val;
+               break;
+       }
+       case MVM_DEBUGFS_PM_SKIP_OVER_DTIM:
+               IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n",
+                               val ? "enabled" : "disabled");
+               dbgfs_pm->skip_over_dtim = val;
+               break;
+       case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS:
+               IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val);
+               dbgfs_pm->skip_dtim_periods = val;
+               break;
+       case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT:
+               IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val);
+               dbgfs_pm->rx_data_timeout = val;
+               break;
+       case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT:
+               IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
+               dbgfs_pm->tx_data_timeout = val;
+               break;
+       case MVM_DEBUGFS_PM_DISABLE_POWER_OFF:
+               IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val);
+               dbgfs_pm->disable_power_off = val;
+               break;
+       case MVM_DEBUGFS_PM_LPRX_ENA:
+               IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
+               dbgfs_pm->lprx_ena = val;
+               break;
+       case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
+               IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
+               dbgfs_pm->lprx_rssi_threshold = val;
+               break;
+       case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
+               IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
+               dbgfs_pm->snooze_ena = val;
+               break;
+       case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING:
+               IWL_DEBUG_POWER(mvm, "uapsd_misbehaving_enable=%d\n", val);
+               dbgfs_pm->uapsd_misbehaving = val;
+               break;
+       }
+}
+
+static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm *mvm = mvmvif->mvm;
+       enum iwl_dbgfs_pm_mask param;
+       int val, ret;
+
+       if (!strncmp("keep_alive=", buf, 11)) {
+               if (sscanf(buf + 11, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_KEEP_ALIVE;
+       } else if (!strncmp("skip_over_dtim=", buf, 15)) {
+               if (sscanf(buf + 15, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM;
+       } else if (!strncmp("skip_dtim_periods=", buf, 18)) {
+               if (sscanf(buf + 18, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS;
+       } else if (!strncmp("rx_data_timeout=", buf, 16)) {
+               if (sscanf(buf + 16, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT;
+       } else if (!strncmp("tx_data_timeout=", buf, 16)) {
+               if (sscanf(buf + 16, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
+       } else if (!strncmp("disable_power_off=", buf, 18) &&
+                  !(mvm->fw->ucode_capa.flags &
+                    IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) {
+               if (sscanf(buf + 18, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF;
+       } else if (!strncmp("lprx=", buf, 5)) {
+               if (sscanf(buf + 5, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_LPRX_ENA;
+       } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
+               if (sscanf(buf + 20, "%d", &val) != 1)
+                       return -EINVAL;
+               if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
+                   POWER_LPRX_RSSI_THRESHOLD_MIN)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
+       } else if (!strncmp("snooze_enable=", buf, 14)) {
+               if (sscanf(buf + 14, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
+       } else if (!strncmp("uapsd_misbehaving=", buf, 18)) {
+               if (sscanf(buf + 18, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_UAPSD_MISBEHAVING;
+       } else {
+               return -EINVAL;
+       }
+
+       mutex_lock(&mvm->mutex);
+       iwl_dbgfs_update_pm(mvm, vif, param, val);
+       ret = iwl_mvm_power_update_mode(mvm, vif);
+       mutex_unlock(&mvm->mutex);
+
+       return ret ?: count;
+}
+
+static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
+                                       char __user *user_buf,
+                                       size_t count, loff_t *ppos)
+{
+       struct ieee80211_vif *vif = file->private_data;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm *mvm = mvmvif->mvm;
+       char buf[512];
+       int bufsz = sizeof(buf);
+       int pos;
+
+       pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
 static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
                                         char __user *user_buf,
                                         size_t count, loff_t *ppos)
@@ -98,14 +242,17 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
        if (vif->type == NL80211_IFTYPE_STATION &&
            ap_sta_id != IWL_MVM_STATION_COUNT) {
                struct ieee80211_sta *sta;
-               struct iwl_mvm_sta *mvm_sta;
 
                sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
                                                lockdep_is_held(&mvm->mutex));
-               mvm_sta = (void *)sta->drv_priv;
-               pos += scnprintf(buf+pos, bufsz-pos,
-                                "ap_sta_id %d - reduced Tx power %d\n",
-                                ap_sta_id, mvm_sta->bt_reduced_txpower);
+               if (!IS_ERR_OR_NULL(sta)) {
+                       struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
+
+                       pos += scnprintf(buf+pos, bufsz-pos,
+                                        "ap_sta_id %d - reduced Tx power %d\n",
+                                        ap_sta_id,
+                                        mvm_sta->bt_reduced_txpower);
+               }
        }
 
        rcu_read_lock();
@@ -122,6 +269,201 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
+static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
+                               enum iwl_dbgfs_bf_mask param, int value)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
+
+       dbgfs_bf->mask |= param;
+
+       switch (param) {
+       case MVM_DEBUGFS_BF_ENERGY_DELTA:
+               dbgfs_bf->bf_energy_delta = value;
+               break;
+       case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA:
+               dbgfs_bf->bf_roaming_energy_delta = value;
+               break;
+       case MVM_DEBUGFS_BF_ROAMING_STATE:
+               dbgfs_bf->bf_roaming_state = value;
+               break;
+       case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
+               dbgfs_bf->bf_temp_threshold = value;
+               break;
+       case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
+               dbgfs_bf->bf_temp_fast_filter = value;
+               break;
+       case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
+               dbgfs_bf->bf_temp_slow_filter = value;
+               break;
+       case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
+               dbgfs_bf->bf_enable_beacon_filter = value;
+               break;
+       case MVM_DEBUGFS_BF_DEBUG_FLAG:
+               dbgfs_bf->bf_debug_flag = value;
+               break;
+       case MVM_DEBUGFS_BF_ESCAPE_TIMER:
+               dbgfs_bf->bf_escape_timer = value;
+               break;
+       case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT:
+               dbgfs_bf->ba_enable_beacon_abort = value;
+               break;
+       case MVM_DEBUGFS_BA_ESCAPE_TIMER:
+               dbgfs_bf->ba_escape_timer = value;
+               break;
+       }
+}
+
+static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm *mvm = mvmvif->mvm;
+       enum iwl_dbgfs_bf_mask param;
+       int value, ret = 0;
+
+       if (!strncmp("bf_energy_delta=", buf, 16)) {
+               if (sscanf(buf+16, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < IWL_BF_ENERGY_DELTA_MIN ||
+                   value > IWL_BF_ENERGY_DELTA_MAX)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BF_ENERGY_DELTA;
+       } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) {
+               if (sscanf(buf+24, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN ||
+                   value > IWL_BF_ROAMING_ENERGY_DELTA_MAX)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA;
+       } else if (!strncmp("bf_roaming_state=", buf, 17)) {
+               if (sscanf(buf+17, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < IWL_BF_ROAMING_STATE_MIN ||
+                   value > IWL_BF_ROAMING_STATE_MAX)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BF_ROAMING_STATE;
+       } else if (!strncmp("bf_temp_threshold=", buf, 18)) {
+               if (sscanf(buf+18, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
+                   value > IWL_BF_TEMP_THRESHOLD_MAX)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
+       } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
+               if (sscanf(buf+20, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
+                   value > IWL_BF_TEMP_FAST_FILTER_MAX)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
+       } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
+               if (sscanf(buf+20, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
+                   value > IWL_BF_TEMP_SLOW_FILTER_MAX)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
+       } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
+               if (sscanf(buf+24, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < 0 || value > 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER;
+       } else if (!strncmp("bf_debug_flag=", buf, 14)) {
+               if (sscanf(buf+14, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < 0 || value > 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BF_DEBUG_FLAG;
+       } else if (!strncmp("bf_escape_timer=", buf, 16)) {
+               if (sscanf(buf+16, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < IWL_BF_ESCAPE_TIMER_MIN ||
+                   value > IWL_BF_ESCAPE_TIMER_MAX)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BF_ESCAPE_TIMER;
+       } else if (!strncmp("ba_escape_timer=", buf, 16)) {
+               if (sscanf(buf+16, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < IWL_BA_ESCAPE_TIMER_MIN ||
+                   value > IWL_BA_ESCAPE_TIMER_MAX)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BA_ESCAPE_TIMER;
+       } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) {
+               if (sscanf(buf+23, "%d", &value) != 1)
+                       return -EINVAL;
+               if (value < 0 || value > 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT;
+       } else {
+               return -EINVAL;
+       }
+
+       mutex_lock(&mvm->mutex);
+       iwl_dbgfs_update_bf(vif, param, value);
+       if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
+               ret = iwl_mvm_disable_beacon_filter(mvm, vif);
+       else
+               ret = iwl_mvm_enable_beacon_filter(mvm, vif);
+       mutex_unlock(&mvm->mutex);
+
+       return ret ?: count;
+}
+
+static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
+                                       char __user *user_buf,
+                                       size_t count, loff_t *ppos)
+{
+       struct ieee80211_vif *vif = file->private_data;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       char buf[256];
+       int pos = 0;
+       const size_t bufsz = sizeof(buf);
+       struct iwl_beacon_filter_cmd cmd = {
+               IWL_BF_CMD_CONFIG_DEFAULTS,
+               .bf_enable_beacon_filter =
+                       cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
+               .ba_enable_beacon_abort =
+                       cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
+       };
+
+       iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
+       if (mvmvif->bf_data.bf_enabled)
+               cmd.bf_enable_beacon_filter = cpu_to_le32(1);
+       else
+               cmd.bf_enable_beacon_filter = 0;
+
+       pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
+                        le32_to_cpu(cmd.bf_energy_delta));
+       pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
+                        le32_to_cpu(cmd.bf_roaming_energy_delta));
+       pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
+                        le32_to_cpu(cmd.bf_roaming_state));
+       pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
+                        le32_to_cpu(cmd.bf_temp_threshold));
+       pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
+                        le32_to_cpu(cmd.bf_temp_fast_filter));
+       pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
+                        le32_to_cpu(cmd.bf_temp_slow_filter));
+       pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
+                        le32_to_cpu(cmd.bf_enable_beacon_filter));
+       pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
+                        le32_to_cpu(cmd.bf_debug_flag));
+       pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
+                        le32_to_cpu(cmd.bf_escape_timer));
+       pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
+                        le32_to_cpu(cmd.ba_escape_timer));
+       pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
+                        le32_to_cpu(cmd.ba_enable_beacon_abort));
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
+       _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
+#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
+       _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do {              \
                if (!debugfs_create_file(#name, mode, parent, vif,      \
                                         &iwl_dbgfs_##name##_ops))      \
@@ -129,6 +471,8 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
        } while (0)
 
 MVM_DEBUGFS_READ_FILE_OPS(mac_params);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
 
 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
@@ -152,9 +496,21 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
                return;
        }
 
+       if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
+           ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
+            (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
+             mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS)))
+               MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
+                                        S_IRUSR);
+
        MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir,
                                 S_IRUSR);
 
+       if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
+           mvmvif == mvm->bf_allowed_vif)
+               MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir,
+                                        S_IRUSR | S_IWUSR);
+
        /*
         * Create symlink for convenience pointing to interface specific
         * debugfs entries for the driver. For example, under
index e8f62a6a1b57098a3f456e9beff974f7caa3493c..76cdce9edf55de251eebf46b30d5d605de0cc250 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -123,51 +123,31 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
 {
        struct iwl_mvm *mvm = file->private_data;
        const struct fw_img *img;
-       int ofs, len, pos = 0;
-       size_t bufsz, ret;
-       char *buf;
+       unsigned int ofs, len;
+       size_t ret;
        u8 *ptr;
 
        if (!mvm->ucode_loaded)
                return -EINVAL;
 
        /* default is to dump the entire data segment */
+       img = &mvm->fw->img[mvm->cur_ucode];
+       ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
+       len = img->sec[IWL_UCODE_SECTION_DATA].len;
+
        if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) {
-               img = &mvm->fw->img[mvm->cur_ucode];
-               ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
-               len = img->sec[IWL_UCODE_SECTION_DATA].len;
-       } else {
                ofs = mvm->dbgfs_sram_offset;
                len = mvm->dbgfs_sram_len;
        }
 
-       bufsz = len * 4 + 256;
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
        ptr = kzalloc(len, GFP_KERNEL);
-       if (!ptr) {
-               kfree(buf);
+       if (!ptr)
                return -ENOMEM;
-       }
-
-       pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", len);
-       pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", ofs);
 
        iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
-       for (ofs = 0; ofs < len; ofs += 16) {
-               pos += scnprintf(buf + pos, bufsz - pos, "0x%.4x ", ofs);
-               hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos,
-                                  bufsz - pos, false);
-               pos += strlen(buf + pos);
-               if (bufsz - pos > 0)
-                       buf[pos++] = '\n';
-       }
 
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
 
-       kfree(buf);
        kfree(ptr);
 
        return ret;
@@ -176,11 +156,24 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
 static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
                                    size_t count, loff_t *ppos)
 {
+       const struct fw_img *img;
        u32 offset, len;
+       u32 img_offset, img_len;
+
+       if (!mvm->ucode_loaded)
+               return -EINVAL;
+
+       img = &mvm->fw->img[mvm->cur_ucode];
+       img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
+       img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
 
        if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
                if ((offset & 0x3) || (len & 0x3))
                        return -EINVAL;
+
+               if (offset + len > img_offset + img_len)
+                       return -EINVAL;
+
                mvm->dbgfs_sram_offset = offset;
                mvm->dbgfs_sram_len = len;
        } else {
index 85f9f958bfd2d1d0ee7bdb807c6b71b134a468fd..e3a9774af495d3ac814f24e923d10e124afbf2ca 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index af500996bbf140e8422f7e6b17e4cf12253c3f8f..1b4e54d416b044e2563e9e810f3a07b12ffee262 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 4e7dd8cf87dce738cbe062d931dcabe49ce67a51..8415ff312d0eec8139bae02fcdb1e45e1ee49284 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 39c3148bdfa8eff2a09a7641b317f8a8a1648da9..c405cda1025fa4b745b541d65b679bca1dd01253 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 5cb93ae5cd2f73bfff7a1daf5d381f6e9ccc987b..884c0872530883ae55646b0c177d9d2ae172e1da 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -85,6 +85,8 @@
  *             PBW Snoozing enabled
  * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
  * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
+ * @POWER_FLAGS_AP_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving
+ *             detection enablement
 */
 enum iwl_power_flags {
        POWER_FLAGS_POWER_SAVE_ENA_MSK          = BIT(0),
@@ -94,6 +96,7 @@ enum iwl_power_flags {
        POWER_FLAGS_BT_SCO_ENA                  = BIT(8),
        POWER_FLAGS_ADVANCE_PM_ENA_MSK          = BIT(9),
        POWER_FLAGS_LPRX_ENA_MSK                = BIT(11),
+       POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK   = BIT(12),
 };
 
 #define IWL_POWER_VEC_SIZE 5
@@ -228,6 +231,19 @@ struct iwl_mac_power_cmd {
        u8 reserved;
 } __packed;
 
+/*
+ * struct iwl_uapsd_misbehaving_ap_notif - FW sends this notification when
+ * associated AP is identified as improperly implementing uAPSD protocol.
+ * PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78
+ * @sta_id: index of station in uCode's station table - associated AP ID in
+ *         this context.
+ */
+struct iwl_uapsd_misbehaving_ap_notif {
+       __le32 sta_id;
+       u8 mac_id;
+       u8 reserved[3];
+} __packed;
+
 /**
  * struct iwl_beacon_filter_cmd
  * REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
index 532312c7b93718d3c3a245b893c999459ea90834..85057219cc43ff4c4edbd3e606a9254dae9772e5 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index b3ed59237cbadfca46f609daec46812ee72ff7e3..73cbba7424f2be42e5278f85c4e3f54289d06280 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 4aca5933a65d1619fc3e2e419ced4ddddc3d44c1..6bbbad453a3b78359a8f2c435ca63cb6a685ba91 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -138,7 +138,14 @@ enum iwl_sta_flags {
 
 /**
  * enum iwl_sta_key_flag - key flags for the ADD_STA host command
- * @STA_KEY_FLG_EN_MSK: mask for encryption algorithm
+ * @STA_KEY_FLG_NO_ENC: no encryption
+ * @STA_KEY_FLG_WEP: WEP encryption algorithm
+ * @STA_KEY_FLG_CCM: CCMP encryption algorithm
+ * @STA_KEY_FLG_TKIP: TKIP encryption algorithm
+ * @STA_KEY_FLG_EXT: extended cipher algorithm (depends on the FW support)
+ * @STA_KEY_FLG_CMAC: CMAC encryption algorithm
+ * @STA_KEY_FLG_ENC_UNKNOWN: unknown encryption algorithm
+ * @STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value
  * @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from
  *     station info array (1 - n 1X mode)
  * @STA_KEY_FLG_KEYID_MSK: the index of the key
@@ -152,6 +159,7 @@ enum iwl_sta_key_flag {
        STA_KEY_FLG_WEP                 = (1 << 0),
        STA_KEY_FLG_CCM                 = (2 << 0),
        STA_KEY_FLG_TKIP                = (3 << 0),
+       STA_KEY_FLG_EXT                 = (4 << 0),
        STA_KEY_FLG_CMAC                = (6 << 0),
        STA_KEY_FLG_ENC_UNKNOWN         = (7 << 0),
        STA_KEY_FLG_EN_MSK              = (7 << 0),
index d606197bde8f41aeba9c7580b9c9f4d8dc8dd959..b674c2a2b51c8910b47811ad73ed876a58fb22f2 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -132,6 +132,7 @@ enum iwl_tx_flags {
 #define TX_CMD_SEC_WEP                 0x01
 #define TX_CMD_SEC_CCM                 0x02
 #define TX_CMD_SEC_TKIP                        0x03
+#define TX_CMD_SEC_EXT                 0x04
 #define TX_CMD_SEC_MSK                 0x07
 #define TX_CMD_SEC_WEP_KEY_IDX_POS     6
 #define TX_CMD_SEC_WEP_KEY_IDX_MSK     0xc0
index bad5a552dd8d10412f5d9d874026215d6c6e9359..989d7dbdca6c31f4a13bb9e70a6cf9a669cf9d33 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -141,6 +141,7 @@ enum {
 
        /* Power - legacy power table command */
        POWER_TABLE_CMD = 0x77,
+       PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78,
 
        /* Thermal Throttling*/
        REPLY_THERMAL_MNG_BACKOFF = 0x7e,
@@ -183,6 +184,7 @@ enum {
        BT_PROFILE_NOTIFICATION = 0xce,
        BT_COEX_CI = 0x5d,
 
+       REPLY_SF_CFG_CMD = 0xd1,
        REPLY_BEACON_FILTERING_CMD = 0xd2,
 
        REPLY_DEBUG_CMD = 0xf0,
@@ -1052,6 +1054,7 @@ enum iwl_mvm_rx_status {
        RX_MPDU_RES_STATUS_SEC_WEP_ENC                  = (1 << 8),
        RX_MPDU_RES_STATUS_SEC_CCM_ENC                  = (2 << 8),
        RX_MPDU_RES_STATUS_SEC_TKIP_ENC                 = (3 << 8),
+       RX_MPDU_RES_STATUS_SEC_EXT_ENC                  = (4 << 8),
        RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC             = (6 << 8),
        RX_MPDU_RES_STATUS_SEC_ENC_ERR                  = (7 << 8),
        RX_MPDU_RES_STATUS_SEC_ENC_MSK                  = (7 << 8),
@@ -1131,6 +1134,7 @@ struct iwl_set_calib_default_cmd {
 } __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */
 
 #define MAX_PORT_ID_NUM        2
+#define MAX_MCAST_FILTERING_ADDRESSES 256
 
 /**
  * struct iwl_mcast_filter_cmd - configure multicast filter.
@@ -1363,4 +1367,65 @@ struct iwl_notif_statistics { /* STATISTICS_NTFY_API_S_VER_8 */
        struct mvm_statistics_general general;
 } __packed;
 
+/***********************************
+ * Smart Fifo API
+ ***********************************/
+/* Smart Fifo state */
+enum iwl_sf_state {
+       SF_LONG_DELAY_ON = 0, /* should never be called by driver */
+       SF_FULL_ON,
+       SF_UNINIT,
+       SF_INIT_OFF,
+       SF_HW_NUM_STATES
+};
+
+/* Smart Fifo possible scenario */
+enum iwl_sf_scenario {
+       SF_SCENARIO_SINGLE_UNICAST,
+       SF_SCENARIO_AGG_UNICAST,
+       SF_SCENARIO_MULTICAST,
+       SF_SCENARIO_BA_RESP,
+       SF_SCENARIO_TX_RESP,
+       SF_NUM_SCENARIO
+};
+
+#define SF_TRANSIENT_STATES_NUMBER 2   /* SF_LONG_DELAY_ON and SF_FULL_ON */
+#define SF_NUM_TIMEOUT_TYPES 2         /* Aging timer and Idle timer */
+
+/* smart FIFO default values */
+#define SF_W_MARK_SISO 4096
+#define SF_W_MARK_MIMO2 8192
+#define SF_W_MARK_MIMO3 6144
+#define SF_W_MARK_LEGACY 4096
+#define SF_W_MARK_SCAN 4096
+
+/* SF Scenarios timers for FULL_ON state (aligned to 32 uSec) */
+#define SF_SINGLE_UNICAST_IDLE_TIMER 320       /* 300 uSec  */
+#define SF_SINGLE_UNICAST_AGING_TIMER 2016     /* 2 mSec */
+#define SF_AGG_UNICAST_IDLE_TIMER 320          /* 300 uSec */
+#define SF_AGG_UNICAST_AGING_TIMER 2016                /* 2 mSec */
+#define SF_MCAST_IDLE_TIMER 2016               /* 2 mSec */
+#define SF_MCAST_AGING_TIMER 10016             /* 10 mSec */
+#define SF_BA_IDLE_TIMER 320                   /* 300 uSec */
+#define SF_BA_AGING_TIMER 2016                 /* 2 mSec */
+#define SF_TX_RE_IDLE_TIMER 320                        /* 300 uSec */
+#define SF_TX_RE_AGING_TIMER 2016              /* 2 mSec */
+
+#define SF_LONG_DELAY_AGING_TIMER 1000000      /* 1 Sec */
+
+/**
+ * Smart Fifo configuration command.
+ * @state: smart fifo state, types listed in iwl_sf_sate.
+ * @watermark: Minimum allowed availabe free space in RXF for transient state.
+ * @long_delay_timeouts: aging and idle timer values for each scenario
+ * in long delay state.
+ * @full_on_timeouts: timer values for each scenario in full on state.
+ */
+struct iwl_sf_cfg_cmd {
+       enum iwl_sf_state state;
+       __le32 watermark[SF_TRANSIENT_STATES_NUMBER];
+       __le32 long_delay_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
+       __le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
+} __packed; /* SF_CFG_API_S_VER_2 */
+
 #endif /* __fw_api_h__ */
index 70e5297646b29b9d2410699b53b5daa7ed3fab3a..c03d39541f9ee50d7f179982d4a688d3f90c4246 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -241,7 +241,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 
        lockdep_assert_held(&mvm->mutex);
 
-       if (mvm->init_ucode_complete)
+       if (WARN_ON_ONCE(mvm->init_ucode_complete))
                return 0;
 
        iwl_init_notification_wait(&mvm->notif_wait,
@@ -287,7 +287,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
                IWL_DEBUG_RF_KILL(mvm,
                                  "jump over all phy activities due to RF kill\n");
                iwl_remove_notification(&mvm->notif_wait, &calib_wait);
-               return 1;
+               ret = 1;
+               goto out;
        }
 
        /* Send TX valid antennas before triggering calibrations */
@@ -319,9 +320,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 error:
        iwl_remove_notification(&mvm->notif_wait, &calib_wait);
 out:
-       if (!iwlmvm_mod_params.init_dbg) {
-               iwl_trans_stop_device(mvm->trans);
-       } else if (!mvm->nvm_data) {
+       if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
                /* we want to debug INIT and we have no NVM - fake */
                mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
                                        sizeof(struct ieee80211_channel) +
@@ -370,11 +369,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
                                ret = -ERFKILL;
                        goto error;
                }
-               /* should stop & start HW since that INIT image just loaded */
-               iwl_trans_stop_hw(mvm->trans, false);
-               ret = iwl_trans_start_hw(mvm->trans);
-               if (ret)
-                       return ret;
+               if (!iwlmvm_mod_params.init_dbg) {
+                       /*
+                        * should stop and start HW since that INIT
+                        * image just loaded
+                        */
+                       iwl_trans_stop_device(mvm->trans);
+                       ret = iwl_trans_start_hw(mvm->trans);
+                       if (ret)
+                               return ret;
+               }
        }
 
        if (iwlmvm_mod_params.init_dbg)
@@ -386,6 +390,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
                goto error;
        }
 
+       ret = iwl_mvm_sf_update(mvm, NULL, false);
+       if (ret)
+               IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
+
        ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
        if (ret)
                goto error;
index 2269a9e5cc6724832d384b031d5907dabcaf4597..6b4ea6bf8ffeaf13273b1f79ec46057290254e31 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -103,7 +103,7 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm)
                return 0;
        default:
                return -EINVAL;
-       };
+       }
 
        mvm->led.name = kasprintf(GFP_KERNEL, "%s-led",
                                   wiphy_name(mvm->hw->wiphy));
index fb93961da7500bf1ada5668fb86ef5d4b17c152a..ba723d50939a5582ea3aaf02c8d1fa4e9ae7388c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include "mvm.h"
 
 const u8 iwl_mvm_ac_to_tx_fifo[] = {
-       IWL_MVM_TX_FIFO_BK,
-       IWL_MVM_TX_FIFO_BE,
-       IWL_MVM_TX_FIFO_VI,
        IWL_MVM_TX_FIFO_VO,
+       IWL_MVM_TX_FIFO_VI,
+       IWL_MVM_TX_FIFO_BE,
+       IWL_MVM_TX_FIFO_BK,
 };
 
 struct iwl_mvm_mac_iface_iterator_data {
@@ -85,35 +85,15 @@ struct iwl_mvm_mac_iface_iterator_data {
        bool found_vif;
 };
 
-static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
-                                      struct ieee80211_vif *vif)
+static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
+                                   struct ieee80211_vif *vif)
 {
        struct iwl_mvm_mac_iface_iterator_data *data = _data;
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       u32 ac;
 
-       /* Iterator may already find the interface being added -- skip it */
-       if (vif == data->vif) {
-               data->found_vif = true;
+       /* Skip the interface for which we are trying to assign a tsf_id  */
+       if (vif == data->vif)
                return;
-       }
-
-       /* Mark the queues used by the vif */
-       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
-               if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
-                       __set_bit(vif->hw_queue[ac], data->used_hw_queues);
-
-       if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
-               __set_bit(vif->cab_queue, data->used_hw_queues);
-
-       /*
-        * Mark MAC IDs as used by clearing the available bit, and
-        * (below) mark TSFs as used if their existing use is not
-        * compatible with the new interface type.
-        * No locking or atomic bit operations are needed since the
-        * data is on the stack of the caller function.
-        */
-       __clear_bit(mvmvif->id, data->available_mac_ids);
 
        /*
         * The TSF is a hardware/firmware resource, there are 4 and
@@ -135,21 +115,26 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
        case NL80211_IFTYPE_STATION:
                /*
                 * The new interface is client, so if the existing one
-                * we're iterating is an AP, the TSF should be used to
+                * we're iterating is an AP, and both interfaces have the
+                * same beacon interval, the same TSF should be used to
                 * avoid drift between the new client and existing AP,
                 * the existing AP will get drift updates from the new
                 * client context in this case
                 */
                if (vif->type == NL80211_IFTYPE_AP) {
                        if (data->preferred_tsf == NUM_TSF_IDS &&
-                           test_bit(mvmvif->tsf_id, data->available_tsf_ids))
+                           test_bit(mvmvif->tsf_id, data->available_tsf_ids) &&
+                           (vif->bss_conf.beacon_int ==
+                            data->vif->bss_conf.beacon_int)) {
                                data->preferred_tsf = mvmvif->tsf_id;
-                       return;
+                               return;
+                       }
                }
                break;
        case NL80211_IFTYPE_AP:
                /*
-                * The new interface is AP/GO, so should get drift
+                * The new interface is AP/GO, so in case both interfaces
+                * have the same beacon interval, it should get drift
                 * updates from an existing client or use the same
                 * TSF as an existing GO. There's no drift between
                 * TSFs internally but if they used different TSFs
@@ -159,9 +144,12 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
                if (vif->type == NL80211_IFTYPE_STATION ||
                    vif->type == NL80211_IFTYPE_AP) {
                        if (data->preferred_tsf == NUM_TSF_IDS &&
-                           test_bit(mvmvif->tsf_id, data->available_tsf_ids))
+                           test_bit(mvmvif->tsf_id, data->available_tsf_ids) &&
+                           (vif->bss_conf.beacon_int ==
+                            data->vif->bss_conf.beacon_int)) {
                                data->preferred_tsf = mvmvif->tsf_id;
-                       return;
+                               return;
+                       }
                }
                break;
        default:
@@ -187,6 +175,39 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
                data->preferred_tsf = NUM_TSF_IDS;
 }
 
+static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
+                                      struct ieee80211_vif *vif)
+{
+       struct iwl_mvm_mac_iface_iterator_data *data = _data;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       u32 ac;
+
+       /* Iterator may already find the interface being added -- skip it */
+       if (vif == data->vif) {
+               data->found_vif = true;
+               return;
+       }
+
+       /* Mark the queues used by the vif */
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+               if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
+                       __set_bit(vif->hw_queue[ac], data->used_hw_queues);
+
+       if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
+               __set_bit(vif->cab_queue, data->used_hw_queues);
+
+       /* Mark MAC IDs as used by clearing the available bit, and
+        * (below) mark TSFs as used if their existing use is not
+        * compatible with the new interface type.
+        * No locking or atomic bit operations are needed since the
+        * data is on the stack of the caller function.
+        */
+       __clear_bit(mvmvif->id, data->available_mac_ids);
+
+       /* find a suitable tsf_id */
+       iwl_mvm_mac_tsf_id_iter(_data, mac, vif);
+}
+
 /*
  * Get the mask of the queus used by the vif
  */
@@ -205,6 +226,29 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
        return qmask;
 }
 
+void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
+                                   struct ieee80211_vif *vif)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm_mac_iface_iterator_data data = {
+               .mvm = mvm,
+               .vif = vif,
+               .available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
+               /* no preference yet */
+               .preferred_tsf = NUM_TSF_IDS,
+       };
+
+       ieee80211_iterate_active_interfaces_atomic(
+               mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               iwl_mvm_mac_tsf_id_iter, &data);
+
+       if (data.preferred_tsf != NUM_TSF_IDS)
+               mvmvif->tsf_id = data.preferred_tsf;
+       else if (!test_bit(mvmvif->tsf_id, data.available_tsf_ids))
+               mvmvif->tsf_id = find_first_bit(data.available_tsf_ids,
+                                               NUM_TSF_IDS);
+}
+
 static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
                                               struct ieee80211_vif *vif)
 {
@@ -586,18 +630,23 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
                cpu_to_le32(vif->bss_conf.use_short_slot ?
                            MAC_FLG_SHORT_SLOT : 0);
 
-       for (i = 0; i < AC_NUM; i++) {
-               cmd->ac[i].cw_min = cpu_to_le16(mvmvif->queue_params[i].cw_min);
-               cmd->ac[i].cw_max = cpu_to_le16(mvmvif->queue_params[i].cw_max);
-               cmd->ac[i].aifsn = mvmvif->queue_params[i].aifs;
-               cmd->ac[i].edca_txop =
+       for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+               u8 txf = iwl_mvm_ac_to_tx_fifo[i];
+
+               cmd->ac[txf].cw_min =
+                       cpu_to_le16(mvmvif->queue_params[i].cw_min);
+               cmd->ac[txf].cw_max =
+                       cpu_to_le16(mvmvif->queue_params[i].cw_max);
+               cmd->ac[txf].edca_txop =
                        cpu_to_le16(mvmvif->queue_params[i].txop * 32);
-               cmd->ac[i].fifos_mask = BIT(iwl_mvm_ac_to_tx_fifo[i]);
+               cmd->ac[txf].aifsn = mvmvif->queue_params[i].aifs;
+               cmd->ac[txf].fifos_mask = BIT(txf);
        }
 
        /* in AP mode, the MCAST FIFO takes the EDCA params from VO */
        if (vif->type == NL80211_IFTYPE_AP)
-               cmd->ac[AC_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST);
+               cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |=
+                       BIT(IWL_MVM_TX_FIFO_MCAST);
 
        if (vif->bss_conf.qos)
                cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
@@ -1007,7 +1056,7 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
                        iwl_mvm_mac_ap_iterator, &data);
 
                if (data.beacon_device_ts) {
-                       u32 rand = (prandom_u32() % (80 - 20)) + 20;
+                       u32 rand = (prandom_u32() % (64 - 36)) + 36;
                        mvmvif->ap_beacon_time = data.beacon_device_ts +
                                ieee80211_tu_to_usec(data.beacon_int * rand /
                                                     100);
@@ -1186,10 +1235,18 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
 static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
                                         struct ieee80211_vif *vif)
 {
-       u16 *id = _data;
+       struct iwl_missed_beacons_notif *missed_beacons = _data;
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 
-       if (mvmvif->id == *id)
+       if (mvmvif->id != (u16)le32_to_cpu(missed_beacons->mac_id))
+               return;
+
+       /*
+        * TODO: the threshold should be adjusted based on latency conditions,
+        * and/or in case of a CS flow on one of the other AP vifs.
+        */
+       if (le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx) >
+            IWL_MVM_MISSED_BEACONS_THRESHOLD)
                ieee80211_beacon_loss(vif);
 }
 
@@ -1198,12 +1255,19 @@ int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
                                    struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_missed_beacons_notif *missed_beacons = (void *)pkt->data;
-       u16 id = (u16)le32_to_cpu(missed_beacons->mac_id);
+       struct iwl_missed_beacons_notif *mb = (void *)pkt->data;
+
+       IWL_DEBUG_INFO(mvm,
+                      "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
+                      le32_to_cpu(mb->mac_id),
+                      le32_to_cpu(mb->consec_missed_beacons),
+                      le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
+                      le32_to_cpu(mb->num_recvd_beacons),
+                      le32_to_cpu(mb->num_expected_beacons));
 
        ieee80211_iterate_active_interfaces_atomic(mvm->hw,
                                                   IEEE80211_IFACE_ITER_NORMAL,
                                                   iwl_mvm_beacon_loss_iterator,
-                                                  &id);
+                                                  mb);
        return 0;
 }
index afc4419be46dd1eaff2f1b419dae01e4b231b1cb..b41177eb48887213d238f06c132f04390e44fcf1 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -261,6 +261,12 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 
        mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 
+       /* currently FW API supports only one optional cipher scheme */
+       if (mvm->fw->cs->cipher) {
+               mvm->hw->n_cipher_schemes = 1;
+               mvm->hw->cipher_schemes = mvm->fw->cs;
+       }
+
 #ifdef CONFIG_PM_SLEEP
        if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
            mvm->trans->ops->d3_suspend &&
@@ -399,7 +405,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
 static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 {
        iwl_trans_stop_device(mvm->trans);
-       iwl_trans_stop_hw(mvm->trans, false);
 
        mvm->scan_status = IWL_MVM_SCAN_NONE;
 
@@ -471,7 +476,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
        cancel_work_sync(&mvm->roc_done_wk);
 
        iwl_trans_stop_device(mvm->trans);
-       iwl_trans_stop_hw(mvm->trans, false);
 
        iwl_mvm_async_handlers_purge(mvm);
        /* async_handlers_list is empty and will stay empty: HW is stopped */
@@ -488,17 +492,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
        cancel_work_sync(&mvm->async_handlers_wk);
 }
 
-static void iwl_mvm_pm_disable_iterator(void *data, u8 *mac,
-                                       struct ieee80211_vif *vif)
-{
-       struct iwl_mvm *mvm = data;
-       int ret;
-
-       ret = iwl_mvm_power_disable(mvm, vif);
-       if (ret)
-               IWL_ERR(mvm, "failed to disable power management\n");
-}
-
 static void iwl_mvm_power_update_iterator(void *data, u8 *mac,
                                          struct ieee80211_vif *vif)
 {
@@ -521,6 +514,20 @@ static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
        return NULL;
 }
 
+static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                               s8 tx_power)
+{
+       /* FW is in charge of regulatory enforcement */
+       struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = {
+               .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id,
+               .pwr_restriction = cpu_to_le16(tx_power),
+       };
+
+       return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC,
+                                   sizeof(reduce_txpwr_cmd),
+                                   &reduce_txpwr_cmd);
+}
+
 static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
                                     struct ieee80211_vif *vif)
 {
@@ -541,26 +548,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
        if (ret)
                goto out_unlock;
 
-       /*
-        * TODO: remove this temporary code.
-        * Currently MVM FW supports power management only on single MAC.
-        * If new interface added, disable PM on existing interface.
-        * P2P device is a special case, since it is handled by FW similary to
-        * scan. If P2P deviced is added, PM remains enabled on existing
-        * interface.
-        * Note: the method below does not count the new interface being added
-        * at this moment.
-        */
+       /* Counting number of interfaces is needed for legacy PM */
        if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
                mvm->vif_count++;
-       if (mvm->vif_count > 1) {
-               IWL_DEBUG_MAC80211(mvm,
-                                  "Disable power on existing interfaces\n");
-               ieee80211_iterate_active_interfaces_atomic(
-                                           mvm->hw,
-                                           IEEE80211_IFACE_ITER_NORMAL,
-                                           iwl_mvm_pm_disable_iterator, mvm);
-       }
 
        /*
         * The AP binding flow can be done only after the beacon
@@ -591,11 +581,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
        if (ret)
                goto out_release;
 
-       /*
-        * Update power state on the new interface. Admittedly, based on
-        * mac80211 logics this power update will disable power management
-        */
-       iwl_mvm_power_update_mode(mvm, vif);
+       iwl_mvm_power_disable(mvm, vif);
 
        /* beacon filtering */
        ret = iwl_mvm_disable_beacon_filter(mvm, vif);
@@ -656,9 +642,12 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
  out_release:
        if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
                mvm->vif_count--;
+
+       /* TODO: remove this when legacy PM will be discarded */
        ieee80211_iterate_active_interfaces(
                mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
                iwl_mvm_power_update_iterator, mvm);
+
        iwl_mvm_mac_ctxt_release(mvm, vif);
  out_unlock:
        mutex_unlock(&mvm->mutex);
@@ -744,21 +733,13 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
                mvmvif->phy_ctxt = NULL;
        }
 
-       /*
-        * TODO: remove this temporary code.
-        * Currently MVM FW supports power management only on single MAC.
-        * Check if only one additional interface remains after removing
-        * current one. Update power mode on the remaining interface.
-        */
        if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)
                mvm->vif_count--;
-       IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
-                          mvm->vif_count);
-       if (mvm->vif_count == 1) {
-               ieee80211_iterate_active_interfaces(
-                                       mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
-                                       iwl_mvm_power_update_iterator, mvm);
-       }
+
+       /* TODO: remove this when legacy PM will be discarded */
+       ieee80211_iterate_active_interfaces(
+               mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+               iwl_mvm_power_update_iterator, mvm);
 
        iwl_mvm_mac_ctxt_remove(mvm, vif);
 
@@ -767,23 +748,91 @@ out_release:
        mutex_unlock(&mvm->mutex);
 }
 
-static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-                               s8 tx_power)
+static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
 {
-       /* FW is in charge of regulatory enforcement */
-       struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = {
-               .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id,
-               .pwr_restriction = cpu_to_le16(tx_power),
+       return 0;
+}
+
+struct iwl_mvm_mc_iter_data {
+       struct iwl_mvm *mvm;
+       int port_id;
+};
+
+static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
+                                     struct ieee80211_vif *vif)
+{
+       struct iwl_mvm_mc_iter_data *data = _data;
+       struct iwl_mvm *mvm = data->mvm;
+       struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd;
+       int ret, len;
+
+       /* if we don't have free ports, mcast frames will be dropped */
+       if (WARN_ON_ONCE(data->port_id >= MAX_PORT_ID_NUM))
+               return;
+
+       if (vif->type != NL80211_IFTYPE_STATION ||
+           !vif->bss_conf.assoc)
+               return;
+
+       cmd->port_id = data->port_id++;
+       memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
+       len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4);
+
+       ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC, len, cmd);
+       if (ret)
+               IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret);
+}
+
+static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
+{
+       struct iwl_mvm_mc_iter_data iter_data = {
+               .mvm = mvm,
        };
 
-       return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC,
-                                   sizeof(reduce_txpwr_cmd),
-                                   &reduce_txpwr_cmd);
+       lockdep_assert_held(&mvm->mutex);
+
+       if (WARN_ON_ONCE(!mvm->mcast_filter_cmd))
+               return;
+
+       ieee80211_iterate_active_interfaces(
+               mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+               iwl_mvm_mc_iface_iterator, &iter_data);
 }
 
-static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
+static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
+                                    struct netdev_hw_addr_list *mc_list)
 {
-       return 0;
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_mcast_filter_cmd *cmd;
+       struct netdev_hw_addr *addr;
+       int addr_count = netdev_hw_addr_list_count(mc_list);
+       bool pass_all = false;
+       int len;
+
+       if (addr_count > MAX_MCAST_FILTERING_ADDRESSES) {
+               pass_all = true;
+               addr_count = 0;
+       }
+
+       len = roundup(sizeof(*cmd) + addr_count * ETH_ALEN, 4);
+       cmd = kzalloc(len, GFP_ATOMIC);
+       if (!cmd)
+               return 0;
+
+       if (pass_all) {
+               cmd->pass_all = 1;
+               return (u64)(unsigned long)cmd;
+       }
+
+       netdev_hw_addr_list_for_each(addr, mc_list) {
+               IWL_DEBUG_MAC80211(mvm, "mcast addr (%d): %pM\n",
+                                  cmd->count, addr->addr);
+               memcpy(&cmd->addr_list[cmd->count * ETH_ALEN],
+                      addr->addr, ETH_ALEN);
+               cmd->count++;
+       }
+
+       return (u64)(unsigned long)cmd;
 }
 
 static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
@@ -791,21 +840,22 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
                                     unsigned int *total_flags,
                                     u64 multicast)
 {
-       *total_flags = 0;
-}
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_mcast_filter_cmd *cmd = (void *)(unsigned long)multicast;
 
-static int iwl_mvm_configure_mcast_filter(struct iwl_mvm *mvm,
-                                         struct ieee80211_vif *vif)
-{
-       struct iwl_mcast_filter_cmd mcast_filter_cmd = {
-               .pass_all = 1,
-       };
+       mutex_lock(&mvm->mutex);
 
-       memcpy(mcast_filter_cmd.bssid, vif->bss_conf.bssid, ETH_ALEN);
+       /* replace previous configuration */
+       kfree(mvm->mcast_filter_cmd);
+       mvm->mcast_filter_cmd = cmd;
+
+       if (!cmd)
+               goto out;
 
-       return iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC,
-                                   sizeof(mcast_filter_cmd),
-                                   &mcast_filter_cmd);
+       iwl_mvm_recalc_multicast(mvm);
+out:
+       mutex_unlock(&mvm->mutex);
+       *total_flags = 0;
 }
 
 static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
@@ -816,6 +866,14 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        int ret;
 
+       /*
+        * Re-calculate the tsf id, as the master-slave relations depend on the
+        * beacon interval, which was not known when the station interface was
+        * added.
+        */
+       if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc)
+               iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
+
        ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
        if (ret)
                IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
@@ -828,7 +886,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                IWL_ERR(mvm, "failed to update quotas\n");
                                return;
                        }
-                       iwl_mvm_configure_mcast_filter(mvm, vif);
 
                        if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
                                     &mvm->status)) {
@@ -850,7 +907,17 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                iwl_mvm_protect_session(mvm, vif, dur, dur,
                                                        5 * dur);
                        }
+
+                       iwl_mvm_sf_update(mvm, vif, false);
+                       iwl_mvm_power_vif_assoc(mvm, vif);
                } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
+                       /*
+                        * If update fails - SF might be running in associated
+                        * mode while disassociated - which is forbidden.
+                        */
+                       WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false),
+                                 "Failed to update SF upon disassociation\n");
+
                        /* remove AP station now that the MAC is unassoc */
                        ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
                        if (ret)
@@ -862,6 +929,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                IWL_ERR(mvm, "failed to update quotas\n");
                }
 
+               iwl_mvm_recalc_multicast(mvm);
+
                /* reset rssi values */
                mvmvif->bf_data.ave_beacon_signal = 0;
 
@@ -882,7 +951,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                 */
                iwl_mvm_remove_time_event(mvm, mvmvif,
                                          &mvmvif->time_event_data);
-       } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_QOS)) {
+       } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
+                             BSS_CHANGED_QOS)) {
                ret = iwl_mvm_power_update_mode(mvm, vif);
                if (ret)
                        IWL_ERR(mvm, "failed to update power mode\n");
@@ -917,6 +987,13 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
        if (ret)
                goto out_unlock;
 
+       /*
+        * Re-calculate the tsf id, as the master-slave relations depend on the
+        * beacon interval, which was not known when the AP interface was added.
+        */
+       if (vif->type == NL80211_IFTYPE_AP)
+               iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
+
        /* Add the mac context */
        ret = iwl_mvm_mac_ctxt_add(mvm, vif);
        if (ret)
@@ -991,11 +1068,16 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
                                 struct ieee80211_bss_conf *bss_conf,
                                 u32 changes)
 {
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        enum ieee80211_bss_change ht_change = BSS_CHANGED_ERP_CTS_PROT |
                                              BSS_CHANGED_HT |
                                              BSS_CHANGED_BANDWIDTH;
        int ret;
 
+       /* Changes will be applied when the AP/IBSS is started */
+       if (!mvmvif->ap_ibss_active)
+               return;
+
        if (changes & ht_change) {
                ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
                if (ret)
@@ -1114,6 +1196,28 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
        }
 }
 
+static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif,
+                                      struct ieee80211_sta *sta)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
+
+       /*
+        * This is called before mac80211 does RCU synchronisation,
+        * so here we already invalidate our internal RCU-protected
+        * station pointer. The rest of the code will thus no longer
+        * be able to find the station this way, and we don't rely
+        * on further RCU synchronisation after the sta_state()
+        * callback deleted the station.
+        */
+       mutex_lock(&mvm->mutex);
+       if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id]))
+               rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
+                                  ERR_PTR(-ENOENT));
+       mutex_unlock(&mvm->mutex);
+}
+
 static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                                 struct ieee80211_vif *vif,
                                 struct ieee80211_sta *sta,
@@ -1200,6 +1304,17 @@ static int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
        return 0;
 }
 
+static void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw,
+                                 struct ieee80211_vif *vif,
+                                 struct ieee80211_sta *sta, u32 changed)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+       if (vif->type == NL80211_IFTYPE_STATION &&
+           changed & IEEE80211_RC_NSS_CHANGED)
+               iwl_mvm_sf_update(mvm, vif, false);
+}
+
 static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
                               struct ieee80211_vif *vif, u16 ac,
                               const struct ieee80211_tx_queue_params *params)
@@ -1322,7 +1437,12 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
                 */
                return 0;
        default:
-               return -EOPNOTSUPP;
+               /* currently FW supports only one optional cipher scheme */
+               if (hw->n_cipher_schemes &&
+                   hw->cipher_schemes->cipher == key->cipher)
+                       key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
+               else
+                       return -EOPNOTSUPP;
        }
 
        mutex_lock(&mvm->mutex);
@@ -1528,7 +1648,7 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
                goto out;
        }
 
-       ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def,
+       ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
                                       ctx->rx_chains_static,
                                       ctx->rx_chains_dynamic);
        if (ret) {
@@ -1566,13 +1686,14 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
        if (WARN_ONCE((phy_ctxt->ref > 1) &&
                      (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
                                   IEEE80211_CHANCTX_CHANGE_RX_CHAINS |
-                                  IEEE80211_CHANCTX_CHANGE_RADAR)),
+                                  IEEE80211_CHANCTX_CHANGE_RADAR |
+                                  IEEE80211_CHANCTX_CHANGE_MIN_WIDTH)),
                      "Cannot change PHY. Ref=%d, changed=0x%X\n",
                      phy_ctxt->ref, changed))
                return;
 
        mutex_lock(&mvm->mutex);
-       iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def,
+       iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
                                 ctx->rx_chains_static,
                                 ctx->rx_chains_dynamic);
        iwl_mvm_bt_coex_vif_change(mvm);
@@ -1615,7 +1736,13 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
                goto out_unlock;
 
        /*
-        * Setting the quota at this stage is only required for monitor
+        * Power state must be updated before quotas,
+        * otherwise fw will complain.
+        */
+       mvm->bound_vif_cnt++;
+       iwl_mvm_power_update_binding(mvm, vif, true);
+
+       /* Setting the quota at this stage is only required for monitor
         * interfaces. For the other types, the bss_info changed flow
         * will handle quota settings.
         */
@@ -1630,6 +1757,8 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
 
  out_remove_binding:
        iwl_mvm_binding_remove_vif(mvm, vif);
+       mvm->bound_vif_cnt--;
+       iwl_mvm_power_update_binding(mvm, vif, false);
  out_unlock:
        mutex_unlock(&mvm->mutex);
        if (ret)
@@ -1663,6 +1792,9 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
        iwl_mvm_binding_remove_vif(mvm, vif);
 out_unlock:
        mvmvif->phy_ctxt = NULL;
+       mvm->bound_vif_cnt--;
+       iwl_mvm_power_update_binding(mvm, vif, false);
+
        mutex_unlock(&mvm->mutex);
 }
 
@@ -1757,14 +1889,17 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
        .add_interface = iwl_mvm_mac_add_interface,
        .remove_interface = iwl_mvm_mac_remove_interface,
        .config = iwl_mvm_mac_config,
+       .prepare_multicast = iwl_mvm_prepare_multicast,
        .configure_filter = iwl_mvm_configure_filter,
        .bss_info_changed = iwl_mvm_bss_info_changed,
        .hw_scan = iwl_mvm_mac_hw_scan,
        .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
+       .sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove,
        .sta_state = iwl_mvm_mac_sta_state,
        .sta_notify = iwl_mvm_mac_sta_notify,
        .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
        .set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
+       .sta_rc_update = iwl_mvm_sta_rc_update,
        .conf_tx = iwl_mvm_mac_conf_tx,
        .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
        .sched_scan_start = iwl_mvm_mac_sched_scan_start,
index 7dc57cfe58035cfc5128e1fa8f3969f46584d7c9..e4ead86f06d69a7ebb99d2ceede388035dd6c89e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -81,6 +81,7 @@
 #define IWL_MVM_MAX_ADDRESSES          5
 /* RSSI offset for WkP */
 #define IWL_RSSI_OFFSET 50
+#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
 
 enum iwl_mvm_tx_fifo {
        IWL_MVM_TX_FIFO_BK = 0,
@@ -163,6 +164,8 @@ struct iwl_mvm_power_ops {
                                 struct ieee80211_vif *vif);
        int (*power_update_device_mode)(struct iwl_mvm *mvm);
        int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+       void (*power_update_binding)(struct iwl_mvm *mvm,
+                                    struct ieee80211_vif *vif, bool assign);
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                                char *buf, int bufsz);
@@ -181,6 +184,7 @@ enum iwl_dbgfs_pm_mask {
        MVM_DEBUGFS_PM_LPRX_ENA = BIT(6),
        MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7),
        MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8),
+       MVM_DEBUGFS_PM_UAPSD_MISBEHAVING = BIT(9),
 };
 
 struct iwl_dbgfs_pm {
@@ -193,6 +197,7 @@ struct iwl_dbgfs_pm {
        bool lprx_ena;
        u32 lprx_rssi_threshold;
        bool snooze_ena;
+       bool uapsd_misbehaving;
        int mask;
 };
 
@@ -269,8 +274,8 @@ struct iwl_mvm_vif_bf_data {
  * @bcast_sta: station used for broadcast packets. Used by the following
  *  vifs: P2P_DEVICE, GO and AP.
  * @beacon_skb: the skb used to hold the AP/GO beacon template
- * @smps_requests: the requests of of differents parts of the driver, regard
      the desired smps mode.
+ * @smps_requests: the SMPS requests of differents parts of the driver,
*     combined on update to yield the overall request to mac80211.
  */
 struct iwl_mvm_vif {
        u16 id;
@@ -331,6 +336,11 @@ struct iwl_mvm_vif {
 #endif
 
        enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ];
+
+       /* FW identified misbehaving AP */
+       u8 uapsd_misbehaving_bssid[ETH_ALEN];
+
+       bool pm_prevented;
 };
 
 static inline struct iwl_mvm_vif *
@@ -479,6 +489,7 @@ struct iwl_mvm {
        /* Scan status, cmd (pre-allocated) and auxiliary station */
        enum iwl_scan_status scan_status;
        struct iwl_scan_cmd *scan_cmd;
+       struct iwl_mcast_filter_cmd *mcast_filter_cmd;
 
        /* rx chain antennas set through debugfs for the scan command */
        u8 scan_rx_ant;
@@ -489,6 +500,9 @@ struct iwl_mvm {
        u8 scan_last_antenna_idx; /* to toggle TX between antennas */
        u8 mgmt_last_antenna_idx;
 
+       /* last smart fifo state that was successfully sent to firmware */
+       enum iwl_sf_state sf_state;
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        struct dentry *debugfs_dir;
        u32 dbgfs_sram_offset, dbgfs_sram_len;
@@ -512,12 +526,6 @@ struct iwl_mvm {
         */
        unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
 
-       /*
-        * This counter of created interfaces is referenced only in conjunction
-        * with FW limitation related to power management. Currently PM is
-        * supported only on a single interface.
-        * IMPORTANT: this variable counts all interfaces except P2P device.
-        */
        u8 vif_count;
 
        /* -1 for always, 0 for never, >0 for that many times */
@@ -560,6 +568,11 @@ struct iwl_mvm {
        u8 aux_queue;
        u8 first_agg_queue;
        u8 last_agg_queue;
+
+       u8 bound_vif_cnt;
+
+       /* Indicate if device power save is allowed */
+       bool ps_prevented;
 };
 
 /* Extract MVM priv from op_mode and _hw */
@@ -699,6 +712,8 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
 int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
                                    struct iwl_rx_cmd_buffer *rxb,
                                    struct iwl_device_cmd *cmd);
+void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
+                                   struct ieee80211_vif *vif);
 
 /* Bindings */
 int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -778,6 +793,19 @@ static inline int iwl_mvm_power_update_device_mode(struct iwl_mvm *mvm)
        return 0;
 }
 
+static inline void iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
+                                               struct ieee80211_vif *vif,
+                                               bool assign)
+{
+       if (mvm->pm_ops->power_update_binding)
+               mvm->pm_ops->power_update_binding(mvm, vif, assign);
+}
+
+void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
+                                            struct iwl_rx_cmd_buffer *rxb,
+                                            struct iwl_device_cmd *cmd);
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm,
                                            struct ieee80211_vif *vif,
@@ -869,4 +897,8 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm);
 void iwl_mvm_tt_exit(struct iwl_mvm *mvm);
 void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);
 
+/* smart fifo */
+int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                     bool added_vif);
+
 #endif /* __IWL_MVM_H__ */
index 48089b1625fff7c1dfc804c6f84a9e68ae56d282..c6beb0f842d5358c25e612911baed6436331e479 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -367,16 +367,17 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
                        break;
                }
 
+               if (WARN(section_id >= NVM_NUM_OF_SECTIONS,
+                        "Invalid NVM section ID %d\n", section_id)) {
+                       ret = -EINVAL;
+                       break;
+               }
+
                temp = kmemdup(file_sec->data, section_size, GFP_KERNEL);
                if (!temp) {
                        ret = -ENOMEM;
                        break;
                }
-               if (WARN_ON(section_id >= NVM_NUM_OF_SECTIONS)) {
-                       IWL_ERR(mvm, "Invalid NVM section ID\n");
-                       ret = -EINVAL;
-                       break;
-               }
                mvm->nvm_sections[section_id].data = temp;
                mvm->nvm_sections[section_id].length = section_size;
 
index d86083c6f445ac40cbcf824df4892b597ee11f35..552c76a926ed7aee2a0d30b1c8a4f4df1385b353 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -236,6 +236,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
                   false),
 
        RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false),
+       RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION,
+                  iwl_mvm_power_uapsd_misbehaving_ap_notif, false),
 };
 #undef RX_HANDLER
 #define CMD(x) [x] = #x
@@ -311,6 +313,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
        CMD(REPLY_THERMAL_MNG_BACKOFF),
        CMD(MAC_PM_POWER_TABLE),
        CMD(BT_COEX_CI),
+       CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
 };
 #undef CMD
 
@@ -341,7 +344,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 
        op_mode = hw->priv;
        op_mode->ops = &iwl_mvm_ops;
-       op_mode->trans = trans;
 
        mvm = IWL_OP_MODE_GET_MVM(op_mode);
        mvm->dev = trans->dev;
@@ -359,6 +361,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
                mvm->aux_queue = 11;
                mvm->first_agg_queue = 12;
        }
+       mvm->sf_state = SF_UNINIT;
 
        mutex_init(&mvm->mutex);
        spin_lock_init(&mvm->async_handlers_lock);
@@ -424,7 +427,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
         * there is no need to unnecessarily power up the NIC at driver load
         */
        if (iwlwifi_mod_params.nvm_file) {
-                       iwl_nvm_init(mvm);
+               err = iwl_nvm_init(mvm);
+               if (err)
+                       goto out_free;
        } else {
                err = iwl_trans_start_hw(mvm->trans);
                if (err)
@@ -432,16 +437,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 
                mutex_lock(&mvm->mutex);
                err = iwl_run_init_mvm_ucode(mvm, true);
+               iwl_trans_stop_device(trans);
                mutex_unlock(&mvm->mutex);
                /* returns 0 if successful, 1 if success but in rfkill */
                if (err < 0 && !iwlmvm_mod_params.init_dbg) {
                        IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err);
                        goto out_free;
                }
-
-               /* Stop the hw after the ALIVE and NVM has been read */
-               if (!iwlmvm_mod_params.init_dbg)
-                       iwl_trans_stop_hw(mvm->trans, false);
        }
 
        scan_size = sizeof(struct iwl_scan_cmd) +
@@ -474,7 +476,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        iwl_phy_db_free(mvm->phy_db);
        kfree(mvm->scan_cmd);
        if (!iwlwifi_mod_params.nvm_file)
-               iwl_trans_stop_hw(trans, true);
+               iwl_trans_op_mode_leave(trans);
        ieee80211_free_hw(mvm->hw);
        return NULL;
 }
@@ -491,12 +493,14 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
        ieee80211_unregister_hw(mvm->hw);
 
        kfree(mvm->scan_cmd);
+       kfree(mvm->mcast_filter_cmd);
+       mvm->mcast_filter_cmd = NULL;
 
 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
        kfree(mvm->d3_resume_sram);
 #endif
 
-       iwl_trans_stop_hw(mvm->trans, true);
+       iwl_trans_op_mode_leave(mvm->trans);
 
        iwl_phy_db_free(mvm->phy_db);
        mvm->phy_db = NULL;
@@ -661,6 +665,8 @@ static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
        else
                clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
 
+       if (state && mvm->cur_ucode != IWL_UCODE_INIT)
+               iwl_trans_stop_device(mvm->trans);
        wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
 }
 
index a8652ddd6bedb54ed7bd045d44fc414c618b5ce9..b7268c0b33339c975a93eca4450d145bfa27137b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 550824aa84ea4bde8794b267bda27401c6b6f058..d9eab3b7bb9f871a37b818e5a63e1320a12d7189 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -64,7 +64,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 
 #include <net/mac80211.h>
 
@@ -186,6 +185,92 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm,
        }
 }
 
+static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
+                                         struct ieee80211_vif *vif,
+                                         struct iwl_mac_power_cmd *cmd)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       enum ieee80211_ac_numbers ac;
+       bool tid_found = false;
+
+       for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
+               if (!mvmvif->queue_params[ac].uapsd)
+                       continue;
+
+               if (mvm->cur_ucode != IWL_UCODE_WOWLAN)
+                       cmd->flags |=
+                               cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
+
+               cmd->uapsd_ac_flags |= BIT(ac);
+
+               /* QNDP TID - the highest TID with no admission control */
+               if (!tid_found && !mvmvif->queue_params[ac].acm) {
+                       tid_found = true;
+                       switch (ac) {
+                       case IEEE80211_AC_VO:
+                               cmd->qndp_tid = 6;
+                               break;
+                       case IEEE80211_AC_VI:
+                               cmd->qndp_tid = 5;
+                               break;
+                       case IEEE80211_AC_BE:
+                               cmd->qndp_tid = 0;
+                               break;
+                       case IEEE80211_AC_BK:
+                               cmd->qndp_tid = 1;
+                               break;
+                       }
+               }
+       }
+
+       if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
+               return;
+
+       cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
+
+       if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
+                                   BIT(IEEE80211_AC_VI) |
+                                   BIT(IEEE80211_AC_BE) |
+                                   BIT(IEEE80211_AC_BK))) {
+               cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
+               cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
+               cmd->snooze_window = (mvm->cur_ucode == IWL_UCODE_WOWLAN) ?
+                       cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
+                       cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
+       }
+
+       cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP;
+
+       if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags &
+           cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
+               cmd->rx_data_timeout_uapsd =
+                       cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
+               cmd->tx_data_timeout_uapsd =
+                       cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
+       } else {
+               cmd->rx_data_timeout_uapsd =
+                       cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
+               cmd->tx_data_timeout_uapsd =
+                       cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
+       }
+
+       if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
+               cmd->heavy_tx_thld_packets =
+                       IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
+               cmd->heavy_rx_thld_packets =
+                       IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
+       } else {
+               cmd->heavy_tx_thld_packets =
+                       IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
+               cmd->heavy_rx_thld_packets =
+                       IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
+       }
+       cmd->heavy_tx_thld_percentage =
+               IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
+       cmd->heavy_rx_thld_percentage =
+               IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
+}
+
 static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
                                    struct ieee80211_vif *vif,
                                    struct iwl_mac_power_cmd *cmd)
@@ -198,8 +283,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
        bool radar_detect = false;
        struct iwl_mvm_vif *mvmvif __maybe_unused =
                iwl_mvm_vif_from_mac80211(vif);
-       enum ieee80211_ac_numbers ac;
-       bool tid_found = false;
+       bool allow_uapsd = true;
 
        cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
                                                            mvmvif->color));
@@ -217,7 +301,8 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
        keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
        cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
 
-       if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
+       if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM ||
+           mvm->ps_prevented)
                return;
 
        cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
@@ -227,7 +312,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
            mvmvif->dbgfs_pm.disable_power_off)
                cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
 #endif
-       if (!vif->bss_conf.ps)
+       if (!vif->bss_conf.ps || mvmvif->pm_prevented)
                return;
 
        cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
@@ -269,81 +354,24 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
                        cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
        }
 
-       for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
-               if (!mvmvif->queue_params[ac].uapsd)
-                       continue;
-
-               if (mvm->cur_ucode != IWL_UCODE_WOWLAN)
-                       cmd->flags |=
-                               cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
-
-               cmd->uapsd_ac_flags |= BIT(ac);
+       if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
+                   ETH_ALEN))
+               allow_uapsd = false;
 
-               /* QNDP TID - the highest TID with no admission control */
-               if (!tid_found && !mvmvif->queue_params[ac].acm) {
-                       tid_found = true;
-                       switch (ac) {
-                       case IEEE80211_AC_VO:
-                               cmd->qndp_tid = 6;
-                               break;
-                       case IEEE80211_AC_VI:
-                               cmd->qndp_tid = 5;
-                               break;
-                       case IEEE80211_AC_BE:
-                               cmd->qndp_tid = 0;
-                               break;
-                       case IEEE80211_AC_BK:
-                               cmd->qndp_tid = 1;
-                               break;
-                       }
-               }
-       }
-
-       if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
-               if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
-                                           BIT(IEEE80211_AC_VI) |
-                                           BIT(IEEE80211_AC_BE) |
-                                           BIT(IEEE80211_AC_BK))) {
-                       cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
-                       cmd->snooze_interval =
-                               cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
-                       cmd->snooze_window =
-                               (mvm->cur_ucode == IWL_UCODE_WOWLAN) ?
-                               cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
-                               cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
-               }
-
-               cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP;
-
-               if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags &
-                   cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
-                       cmd->rx_data_timeout_uapsd =
-                               cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
-                       cmd->tx_data_timeout_uapsd =
-                               cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
-               } else {
-                       cmd->rx_data_timeout_uapsd =
-                               cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
-                       cmd->tx_data_timeout_uapsd =
-                               cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
-               }
+       if (vif->p2p &&
+           !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD))
+               allow_uapsd = false;
+       /*
+        * Avoid using uAPSD if P2P client is associated to GO that uses
+        * opportunistic power save. This is due to current FW limitation.
+        */
+       if (vif->p2p &&
+           vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
+           IEEE80211_P2P_OPPPS_ENABLE_BIT)
+               allow_uapsd = false;
 
-               if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
-                       cmd->heavy_tx_thld_packets =
-                               IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
-                       cmd->heavy_rx_thld_packets =
-                               IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
-               } else {
-                       cmd->heavy_tx_thld_packets =
-                               IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
-                       cmd->heavy_rx_thld_packets =
-                               IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
-               }
-               cmd->heavy_tx_thld_percentage =
-                       IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
-               cmd->heavy_rx_thld_percentage =
-                       IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
-       }
+       if (allow_uapsd)
+               iwl_mvm_power_configure_uapsd(mvm, vif, cmd);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
@@ -381,6 +409,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
                        cmd->flags &=
                                cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
        }
+       if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_UAPSD_MISBEHAVING) {
+               u16 flag = POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK;
+               if (mvmvif->dbgfs_pm.uapsd_misbehaving)
+                       cmd->flags |= cpu_to_le16(flag);
+               else
+                       cmd->flags &= cpu_to_le16(flag);
+       }
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 }
 
@@ -391,18 +426,11 @@ static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
        bool ba_enable;
        struct iwl_mac_power_cmd cmd = {};
 
-       if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
+       if (vif->type != NL80211_IFTYPE_STATION)
                return 0;
 
-       /*
-        * TODO: The following vif_count verification is temporary condition.
-        * Avoid power mode update if more than one interface is currently
-        * active. Remove this condition when FW will support power management
-        * on multiple MACs.
-        */
-       IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n",
-                       mvm->vif_count);
-       if (mvm->vif_count > 1)
+       if (vif->p2p &&
+           !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS))
                return 0;
 
        iwl_mvm_power_build_cmd(mvm, vif, &cmd);
@@ -446,7 +474,7 @@ static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm,
                                    sizeof(cmd), &cmd);
 }
 
-static int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
+static int _iwl_mvm_power_update_device(struct iwl_mvm *mvm, bool force_disable)
 {
        struct iwl_device_power_cmd cmd = {
                .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
@@ -455,7 +483,8 @@ static int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
        if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
                return 0;
 
-       if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
+       if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM ||
+           force_disable)
                cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -472,6 +501,78 @@ static int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
                                    &cmd);
 }
 
+static int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
+{
+       return _iwl_mvm_power_update_device(mvm, false);
+}
+
+void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid,
+                  ETH_ALEN))
+               memset(mvmvif->uapsd_misbehaving_bssid, 0, ETH_ALEN);
+}
+
+static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
+                                                    struct ieee80211_vif *vif)
+{
+       u8 *ap_sta_id = _data;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       /* The ap_sta_id is not expected to change during current association
+        * so no explicit protection is needed
+        */
+       if (mvmvif->ap_sta_id == *ap_sta_id)
+               memcpy(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
+                      ETH_ALEN);
+}
+
+int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
+                                            struct iwl_rx_cmd_buffer *rxb,
+                                            struct iwl_device_cmd *cmd)
+{
+       struct iwl_rx_packet *pkt = rxb_addr(rxb);
+       struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
+       u8 ap_sta_id = le32_to_cpu(notif->sta_id);
+
+       ieee80211_iterate_active_interfaces_atomic(
+               mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+               iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
+
+       return 0;
+}
+
+static void iwl_mvm_power_binding_iterator(void *_data, u8 *mac,
+                                          struct ieee80211_vif *vif)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm *mvm = _data;
+       int ret;
+
+       mvmvif->pm_prevented = (mvm->bound_vif_cnt <= 1) ? false : true;
+
+       ret = iwl_mvm_power_mac_update_mode(mvm, vif);
+       WARN_ONCE(ret, "Failed to update power parameters on a specific vif\n");
+}
+
+static void _iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
+                                         struct ieee80211_vif *vif,
+                                         bool assign)
+{
+       if (vif->type == NL80211_IFTYPE_MONITOR) {
+               int ret = _iwl_mvm_power_update_device(mvm, assign);
+               mvm->ps_prevented = assign;
+               WARN_ONCE(ret, "Failed to update power device state\n");
+       }
+
+       ieee80211_iterate_active_interfaces(mvm->hw,
+                                           IEEE80211_IFACE_ITER_NORMAL,
+                                           iwl_mvm_power_binding_iterator,
+                                           mvm);
+}
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
                                        struct ieee80211_vif *vif, char *buf,
@@ -494,70 +595,58 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
        pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
                         le16_to_cpu(cmd.keep_alive_seconds));
 
-       if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
-               pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
-                                (cmd.flags &
-                                cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
-                                1 : 0);
-               pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
-                                cmd.skip_dtim_periods);
-               if (!(cmd.flags &
-                     cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "rx_data_timeout = %d\n",
-                                        le32_to_cpu(cmd.rx_data_timeout));
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "tx_data_timeout = %d\n",
-                                        le32_to_cpu(cmd.tx_data_timeout));
-               }
-               if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "lprx_rssi_threshold = %d\n",
-                                        cmd.lprx_rssi_threshold);
-               if (cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
-                       pos +=
-                       scnprintf(buf+pos, bufsz-pos,
-                                 "rx_data_timeout_uapsd = %d\n",
-                                 le32_to_cpu(cmd.rx_data_timeout_uapsd));
-                       pos +=
-                       scnprintf(buf+pos, bufsz-pos,
-                                 "tx_data_timeout_uapsd = %d\n",
-                                 le32_to_cpu(cmd.tx_data_timeout_uapsd));
-                       pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n",
-                                        cmd.qndp_tid);
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "uapsd_ac_flags = 0x%x\n",
-                                        cmd.uapsd_ac_flags);
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "uapsd_max_sp = %d\n",
-                                        cmd.uapsd_max_sp);
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "heavy_tx_thld_packets = %d\n",
-                                        cmd.heavy_tx_thld_packets);
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "heavy_rx_thld_packets = %d\n",
-                                        cmd.heavy_rx_thld_packets);
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "heavy_tx_thld_percentage = %d\n",
-                                        cmd.heavy_tx_thld_percentage);
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "heavy_rx_thld_percentage = %d\n",
-                                        cmd.heavy_rx_thld_percentage);
-                       pos +=
-                       scnprintf(buf+pos, bufsz-pos, "snooze_enable = %d\n",
-                                 (cmd.flags &
-                                  cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) ?
-                                 1 : 0);
-               }
-               if (cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "snooze_interval = %d\n",
-                                        cmd.snooze_interval);
-                       pos += scnprintf(buf+pos, bufsz-pos,
-                                        "snooze_window = %d\n",
-                                        cmd.snooze_window);
-               }
+       if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)))
+               return pos;
+
+       pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
+                        (cmd.flags &
+                        cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0);
+       pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
+                        cmd.skip_dtim_periods);
+       if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
+               pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
+                                le32_to_cpu(cmd.rx_data_timeout));
+               pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
+                                le32_to_cpu(cmd.tx_data_timeout));
        }
+       if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
+               pos += scnprintf(buf+pos, bufsz-pos,
+                                "lprx_rssi_threshold = %d\n",
+                                cmd.lprx_rssi_threshold);
+
+       if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
+               return pos;
+
+       pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n",
+                        le32_to_cpu(cmd.rx_data_timeout_uapsd));
+       pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n",
+                        le32_to_cpu(cmd.tx_data_timeout_uapsd));
+       pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid);
+       pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n",
+                        cmd.uapsd_ac_flags);
+       pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n",
+                        cmd.uapsd_max_sp);
+       pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n",
+                        cmd.heavy_tx_thld_packets);
+       pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n",
+                        cmd.heavy_rx_thld_packets);
+       pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n",
+                        cmd.heavy_tx_thld_percentage);
+       pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n",
+                        cmd.heavy_rx_thld_percentage);
+       pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n",
+                        (cmd.flags &
+                         cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ?
+                        1 : 0);
+
+       if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)))
+               return pos;
+
+       pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n",
+                        cmd.snooze_interval);
+       pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n",
+                        cmd.snooze_window);
+
        return pos;
 }
 
@@ -654,6 +743,7 @@ const struct iwl_mvm_power_ops pm_mac_ops = {
        .power_update_mode = iwl_mvm_power_mac_update_mode,
        .power_update_device_mode = iwl_mvm_power_update_device,
        .power_disable = iwl_mvm_power_mac_disable,
+       .power_update_binding = _iwl_mvm_power_update_binding,
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read,
 #endif
index 2ce79bad5845d6325bb0fc512cbe034158acf701..ef712ae5bc621e46b0fb70e0c38ebe375cbea625 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 38165eba2a177da38eb564258a36d81f641e445a..ce5db6c4ef7e60e3ad557cd0e2d773738419d587 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index bf6e29f5b4d0af23d6422f73f07fa13163936d35..ba078a3322b8014a7d9f31fcd443a0fb572b37ce 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -24,7 +24,6 @@
  *
  *****************************************************************************/
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <net/mac80211.h>
 
 #define RS_NAME "iwl-mvm-rs"
 
-#define NUM_TRY_BEFORE_ANT_TOGGLE 1
-#define IWL_NUMBER_TRY      1
-#define IWL_HT_NUMBER_TRY   3
+#define NUM_TRY_BEFORE_ANT_TOGGLE       1
+#define RS_LEGACY_RETRIES_PER_RATE      1
+#define RS_HT_VHT_RETRIES_PER_RATE      2
+#define RS_HT_VHT_RETRIES_PER_RATE_TW   1
+#define RS_INITIAL_MIMO_NUM_RATES       3
+#define RS_INITIAL_SISO_NUM_RATES       3
+#define RS_INITIAL_LEGACY_NUM_RATES     LINK_QUAL_MAX_RETRY_NUM
+#define RS_SECONDARY_LEGACY_NUM_RATES   LINK_QUAL_MAX_RETRY_NUM
+#define RS_SECONDARY_SISO_NUM_RATES     3
+#define RS_SECONDARY_SISO_RETRIES       1
 
 #define IWL_RATE_MAX_WINDOW            62      /* # tx in history window */
 #define IWL_RATE_MIN_FAILURE_TH                3       /* min failures to calc tpt */
@@ -123,6 +129,12 @@ static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = {
        IWL_DECLARE_MCS_RATE(9),                 /* MCS 9 */
 };
 
+enum rs_action {
+       RS_ACTION_STAY = 0,
+       RS_ACTION_DOWNSCALE = -1,
+       RS_ACTION_UPSCALE = 1,
+};
+
 enum rs_column_mode {
        RS_INVALID = 0,
        RS_LEGACY,
@@ -351,20 +363,12 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                                   struct sk_buff *skb,
                                   struct ieee80211_sta *sta,
                                   struct iwl_lq_sta *lq_sta);
-static void rs_fill_link_cmd(struct iwl_mvm *mvm,
-                            struct ieee80211_sta *sta,
-                            struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
+static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
+                          struct ieee80211_sta *sta,
+                          struct iwl_lq_sta *lq_sta,
+                          const struct rs_rate *initial_rate);
 static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search);
 
-#ifdef CONFIG_MAC80211_DEBUGFS
-static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
-                            u32 *rate_n_flags);
-#else
-static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
-                            u32 *rate_n_flags)
-{}
-#endif
-
 /**
  * The following tables contain the expected throughput metrics for all rates
  *
@@ -504,30 +508,6 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
        return (ant_type & valid_antenna) == ant_type;
 }
 
-#ifdef CONFIG_MAC80211_DEBUGFS
-/**
- * Program the device to use fixed rate for frame transmit
- * This is for debugging/testing only
- * once the device start use fixed rate, we need to reload the module
- * to being back the normal operation.
- */
-static void rs_program_fix_rate(struct iwl_mvm *mvm,
-                               struct iwl_lq_sta *lq_sta)
-{
-       lq_sta->active_legacy_rate = 0x0FFF;    /* 1 - 54 MBits, includes CCK */
-       lq_sta->active_siso_rate   = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
-       lq_sta->active_mimo2_rate  = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
-
-       IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n",
-                      lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
-
-       if (lq_sta->dbg_fixed_rate) {
-               rs_fill_link_cmd(NULL, NULL, lq_sta, lq_sta->dbg_fixed_rate);
-               iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false);
-       }
-}
-#endif
-
 static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,
                                      struct iwl_lq_sta *lq_data, u8 tid,
                                      struct ieee80211_sta *sta)
@@ -658,7 +638,7 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
 
 /* Convert rs_rate object into ucode rate bitmask */
 static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
-                                  struct rs_rate *rate)
+                                 struct rs_rate *rate)
 {
        u32 ucode_rate = 0;
        int index = rate->index;
@@ -719,7 +699,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
        u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate);
        u8 nss;
 
-       memset(rate, 0, sizeof(struct rs_rate));
+       memset(rate, 0, sizeof(*rate));
        rate->index = iwl_hwrate_to_plcp_idx(ucode_rate);
 
        if (rate->index == IWL_RATE_INVALID) {
@@ -785,8 +765,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
 
 /* switch to another antenna/antennas and return 1 */
 /* if no other valid antenna found, return 0 */
-static int rs_toggle_antenna(u32 valid_ant, u32 *ucode_rate,
-                            struct rs_rate *rate)
+static int rs_toggle_antenna(u32 valid_ant, struct rs_rate *rate)
 {
        u8 new_ant_type;
 
@@ -807,9 +786,6 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *ucode_rate,
 
        rate->ant = new_ant_type;
 
-       /* TODO: get rid of ucode_rate here. This should handle only rs_rate */
-       *ucode_rate &= ~RATE_MCS_ANT_ABC_MSK;
-       *ucode_rate |= new_ant_type << RATE_MCS_ANT_POS;
        return 1;
 }
 
@@ -883,65 +859,73 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask,
        return (high << 8) | low;
 }
 
-static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
-                            struct rs_rate *rate,
-                            u8 scale_index, u8 ht_possible)
+static inline bool rs_rate_supported(struct iwl_lq_sta *lq_sta,
+                                    struct rs_rate *rate)
 {
-       s32 low;
-       u16 rate_mask;
+       return BIT(rate->index) & rs_get_supported_rates(lq_sta, rate);
+}
+
+/* Get the next supported lower rate in the current column.
+ * Return true if bottom rate in the current column was reached
+ */
+static bool rs_get_lower_rate_in_column(struct iwl_lq_sta *lq_sta,
+                                       struct rs_rate *rate)
+{
+       u8 low;
        u16 high_low;
-       u8 switch_to_legacy = 0;
+       u16 rate_mask;
        struct iwl_mvm *mvm = lq_sta->drv;
 
-       /* check if we need to switch from HT to legacy rates.
-        * assumption is that mandatory rates (1Mbps or 6Mbps)
-        * are always supported (spec demand) */
-       if (!is_legacy(rate) && (!ht_possible || !scale_index)) {
-               switch_to_legacy = 1;
-               WARN_ON_ONCE(scale_index < IWL_RATE_MCS_0_INDEX &&
-                            scale_index > IWL_RATE_MCS_9_INDEX);
-               scale_index = rs_ht_to_legacy[scale_index];
+       rate_mask = rs_get_supported_rates(lq_sta, rate);
+       high_low = rs_get_adjacent_rate(mvm, rate->index, rate_mask,
+                                       rate->type);
+       low = high_low & 0xff;
+
+       /* Bottom rate of column reached */
+       if (low == IWL_RATE_INVALID)
+               return true;
+
+       rate->index = low;
+       return false;
+}
+
+/* Get the next rate to use following a column downgrade */
+static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
+                                         struct rs_rate *rate)
+{
+       struct iwl_mvm *mvm = lq_sta->drv;
+
+       if (is_legacy(rate)) {
+               /* No column to downgrade from Legacy */
+               return;
+       } else if (is_siso(rate)) {
+               /* Downgrade to Legacy if we were in SISO */
                if (lq_sta->band == IEEE80211_BAND_5GHZ)
                        rate->type = LQ_LEGACY_A;
                else
                        rate->type = LQ_LEGACY_G;
 
-               if (num_of_ant(rate->ant) > 1)
-                       rate->ant =
-                           first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
-
                rate->bw = RATE_MCS_CHAN_WIDTH_20;
-               rate->sgi = false;
-       }
 
-       rate_mask = rs_get_supported_rates(lq_sta, rate);
+               WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX &&
+                            rate->index > IWL_RATE_MCS_9_INDEX);
 
-       /* Mask with station rate restriction */
-       if (is_legacy(rate)) {
-               /* supp_rates has no CCK bits in A mode */
-               if (lq_sta->band == IEEE80211_BAND_5GHZ)
-                       rate_mask = (u16)(rate_mask &
-                          (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
-               else
-                       rate_mask = (u16)(rate_mask & lq_sta->supp_rates);
+               rate->index = rs_ht_to_legacy[rate->index];
+       } else {
+               /* Downgrade to SISO with same MCS if in MIMO  */
+               rate->type = is_vht_mimo2(rate) ?
+                       LQ_VHT_SISO : LQ_HT_SISO;
        }
 
-       /* If we switched from HT to legacy, check current rate */
-       if (switch_to_legacy && (rate_mask & (1 << scale_index))) {
-               low = scale_index;
-               goto out;
-       }
 
-       high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask,
-                                       rate->type);
-       low = high_low & 0xff;
+       if (num_of_ant(rate->ant) > 1)
+               rate->ant = first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
 
-       if (low == IWL_RATE_INVALID)
-               low = scale_index;
+       /* Relevant in both switching to SISO or Legacy */
+       rate->sgi = false;
 
-out:
-       rate->index = low;
-       return ucode_rate_from_rs_rate(lq_sta->drv, rate);
+       if (!rs_rate_supported(lq_sta, rate))
+               rs_get_lower_rate_in_column(lq_sta, rate);
 }
 
 /* Simple function to compare two rate scale table types */
@@ -1137,14 +1121,9 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
                                tmp_tbl = curr_tbl;
                        else if (rs_rate_match(&rate, &other_tbl->rate))
                                tmp_tbl = other_tbl;
-                       else {
-                               IWL_DEBUG_RATE(mvm,
-                                              "Tx packet rate doesn't match ACTIVE or SEARCH tables\n");
-                               rs_dump_rate(mvm, &rate, "Tx PACKET:");
-                               rs_dump_rate(mvm, &curr_tbl->rate, "CURRENT:");
-                               rs_dump_rate(mvm, &other_tbl->rate, "OTHER:");
+                       else
                                continue;
-                       }
+
                        rs_collect_tx_data(tmp_tbl, rate.index, 1,
                                           i < retries ? 0 : legacy_success);
                }
@@ -1471,10 +1450,7 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm,
                               struct iwl_lq_sta *lq_sta,
                               struct rs_rate *rate)
 {
-       u32 ucode_rate;
-
-       ucode_rate = ucode_rate_from_rs_rate(mvm, rate);
-       rs_fill_link_cmd(mvm, sta, lq_sta, ucode_rate);
+       rs_fill_lq_cmd(mvm, sta, lq_sta, rate);
        iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
 }
 
@@ -1634,10 +1610,6 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
                rate->index = rate_idx;
        }
 
-       /* TODO: remove current_rate and keep using rs_rate all the way until
-        * we need to fill in the rs_table in the LQ command
-        */
-       search_tbl->current_rate = ucode_rate_from_rs_rate(mvm, rate);
        IWL_DEBUG_RATE(mvm, "Switched to column %d: Index %d\n",
                       col_id, rate->index);
 
@@ -1649,6 +1621,97 @@ err:
        return -1;
 }
 
+static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm,
+                                        struct iwl_scale_tbl_info *tbl,
+                                        s32 sr, int low, int high,
+                                        int current_tpt,
+                                        int low_tpt, int high_tpt)
+{
+       enum rs_action action = RS_ACTION_STAY;
+
+       /* Too many failures, decrease rate */
+       if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) {
+               IWL_DEBUG_RATE(mvm,
+                              "decrease rate because of low SR\n");
+               action = RS_ACTION_DOWNSCALE;
+       /* No throughput measured yet for adjacent rates; try increase. */
+       } else if ((low_tpt == IWL_INVALID_VALUE) &&
+                  (high_tpt == IWL_INVALID_VALUE)) {
+               if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) {
+                       IWL_DEBUG_RATE(mvm,
+                                      "Good SR and no high rate measurement. "
+                                      "Increase rate\n");
+                       action = RS_ACTION_UPSCALE;
+               } else if (low != IWL_RATE_INVALID) {
+                       IWL_DEBUG_RATE(mvm,
+                                      "Remain in current rate\n");
+                       action = RS_ACTION_STAY;
+               }
+       }
+
+       /* Both adjacent throughputs are measured, but neither one has better
+        * throughput; we're using the best rate, don't change it!
+        */
+       else if ((low_tpt != IWL_INVALID_VALUE) &&
+                (high_tpt != IWL_INVALID_VALUE) &&
+                (low_tpt < current_tpt) &&
+                (high_tpt < current_tpt)) {
+               IWL_DEBUG_RATE(mvm,
+                              "Both high and low are worse. "
+                              "Maintain rate\n");
+               action = RS_ACTION_STAY;
+       }
+
+       /* At least one adjacent rate's throughput is measured,
+        * and may have better performance.
+        */
+       else {
+               /* Higher adjacent rate's throughput is measured */
+               if (high_tpt != IWL_INVALID_VALUE) {
+                       /* Higher rate has better throughput */
+                       if (high_tpt > current_tpt &&
+                           sr >= IWL_RATE_INCREASE_TH) {
+                               IWL_DEBUG_RATE(mvm,
+                                              "Higher rate is better and good "
+                                              "SR. Increate rate\n");
+                               action = RS_ACTION_UPSCALE;
+                       } else {
+                               IWL_DEBUG_RATE(mvm,
+                                              "Higher rate isn't better OR "
+                                              "no good SR. Maintain rate\n");
+                               action = RS_ACTION_STAY;
+                       }
+
+               /* Lower adjacent rate's throughput is measured */
+               } else if (low_tpt != IWL_INVALID_VALUE) {
+                       /* Lower rate has better throughput */
+                       if (low_tpt > current_tpt) {
+                               IWL_DEBUG_RATE(mvm,
+                                              "Lower rate is better. "
+                                              "Decrease rate\n");
+                               action = RS_ACTION_DOWNSCALE;
+                       } else if (sr >= IWL_RATE_INCREASE_TH) {
+                               IWL_DEBUG_RATE(mvm,
+                                              "Lower rate isn't better and "
+                                              "good SR. Increase rate\n");
+                               action = RS_ACTION_UPSCALE;
+                       }
+               }
+       }
+
+       /* Sanity check; asked for decrease, but success rate or throughput
+        * has been good at old rate.  Don't change it.
+        */
+       if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) &&
+           ((sr > IWL_RATE_HIGH_TH) ||
+            (current_tpt > (100 * tbl->expected_tpt[low])))) {
+               IWL_DEBUG_RATE(mvm,
+                              "Sanity check failed. Maintain rate\n");
+               action = RS_ACTION_STAY;
+       }
+
+       return action;
+}
 
 /*
  * Do rate scaling and search for new modulation mode.
@@ -1669,11 +1732,10 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        int low_tpt = IWL_INVALID_VALUE;
        int high_tpt = IWL_INVALID_VALUE;
        u32 fail_count;
-       s8 scale_action = 0;
+       enum rs_action scale_action = RS_ACTION_STAY;
        u16 rate_mask;
        u8 update_lq = 0;
        struct iwl_scale_tbl_info *tbl, *tbl1;
-       u16 rate_scale_index_msk = 0;
        u8 active_tbl = 0;
        u8 done_search = 0;
        u16 high_low;
@@ -1690,8 +1752,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
            info->flags & IEEE80211_TX_CTL_NO_ACK)
                return;
 
-       lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
-
        tid = rs_get_tid(lq_sta, hdr);
        if ((tid != IWL_MAX_TID_COUNT) &&
            (lq_sta->tx_agg_tid_en & (1 << tid))) {
@@ -1730,33 +1790,13 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        /* rates available for this association, and for modulation mode */
        rate_mask = rs_get_supported_rates(lq_sta, rate);
 
-       /* mask with station rate restriction */
-       if (is_legacy(rate)) {
-               if (lq_sta->band == IEEE80211_BAND_5GHZ)
-                       /* supp_rates has no CCK bits in A mode */
-                       rate_scale_index_msk = (u16) (rate_mask &
-                               (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
-               else
-                       rate_scale_index_msk = (u16) (rate_mask &
-                                                     lq_sta->supp_rates);
-
-       } else {
-               rate_scale_index_msk = rate_mask;
-       }
-
-       if (!rate_scale_index_msk)
-               rate_scale_index_msk = rate_mask;
-
-       if (!((BIT(index) & rate_scale_index_msk))) {
+       if (!(BIT(index) & rate_mask)) {
                IWL_ERR(mvm, "Current Rate is not valid\n");
                if (lq_sta->search_better_tbl) {
                        /* revert to active table if search table is not valid*/
                        rate->type = LQ_NONE;
                        lq_sta->search_better_tbl = 0;
                        tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-                       /* get "active" rate info */
-                       index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
-                       tbl->rate.index = index;
                        rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate);
                }
                return;
@@ -1847,7 +1887,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                        tbl = &(lq_sta->lq_info[active_tbl]);
 
                        /* Revert to "active" rate and throughput info */
-                       index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
+                       index = tbl->rate.index;
                        current_tpt = lq_sta->last_tpt;
 
                        /* Need to set up a new rate table in uCode */
@@ -1863,8 +1903,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
 
        /* (Else) not in search of better modulation mode, try for better
         * starting rate, while staying in this mode. */
-       high_low = rs_get_adjacent_rate(mvm, index, rate_scale_index_msk,
-                                       rate->type);
+       high_low = rs_get_adjacent_rate(mvm, index, rate_mask, rate->type);
        low = high_low & 0xff;
        high = (high_low >> 8) & 0xff;
 
@@ -1887,85 +1926,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                       rs_pretty_lq_type(rate->type), index, current_tpt, sr,
                       low, high, low_tpt, high_tpt);
 
-       scale_action = 0;
-
-       /* Too many failures, decrease rate */
-       if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) {
-               IWL_DEBUG_RATE(mvm,
-                              "decrease rate because of low SR\n");
-               scale_action = -1;
-       /* No throughput measured yet for adjacent rates; try increase. */
-       } else if ((low_tpt == IWL_INVALID_VALUE) &&
-                  (high_tpt == IWL_INVALID_VALUE)) {
-               if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) {
-                       IWL_DEBUG_RATE(mvm,
-                                      "Good SR and no high rate measurement. "
-                                      "Increase rate\n");
-                       scale_action = 1;
-               } else if (low != IWL_RATE_INVALID) {
-                       IWL_DEBUG_RATE(mvm,
-                                      "Remain in current rate\n");
-                       scale_action = 0;
-               }
-       }
-
-       /* Both adjacent throughputs are measured, but neither one has better
-        * throughput; we're using the best rate, don't change it! */
-       else if ((low_tpt != IWL_INVALID_VALUE) &&
-                (high_tpt != IWL_INVALID_VALUE) &&
-                (low_tpt < current_tpt) &&
-                (high_tpt < current_tpt)) {
-               IWL_DEBUG_RATE(mvm,
-                              "Both high and low are worse. "
-                              "Maintain rate\n");
-               scale_action = 0;
-       }
-
-       /* At least one adjacent rate's throughput is measured,
-        * and may have better performance. */
-       else {
-               /* Higher adjacent rate's throughput is measured */
-               if (high_tpt != IWL_INVALID_VALUE) {
-                       /* Higher rate has better throughput */
-                       if (high_tpt > current_tpt &&
-                           sr >= IWL_RATE_INCREASE_TH) {
-                               IWL_DEBUG_RATE(mvm,
-                                              "Higher rate is better and good "
-                                              "SR. Increate rate\n");
-                               scale_action = 1;
-                       } else {
-                               IWL_DEBUG_RATE(mvm,
-                                              "Higher rate isn't better OR "
-                                              "no good SR. Maintain rate\n");
-                               scale_action = 0;
-                       }
-
-               /* Lower adjacent rate's throughput is measured */
-               } else if (low_tpt != IWL_INVALID_VALUE) {
-                       /* Lower rate has better throughput */
-                       if (low_tpt > current_tpt) {
-                               IWL_DEBUG_RATE(mvm,
-                                              "Lower rate is better. "
-                                              "Decrease rate\n");
-                               scale_action = -1;
-                       } else if (sr >= IWL_RATE_INCREASE_TH) {
-                               IWL_DEBUG_RATE(mvm,
-                                              "Lower rate isn't better and "
-                                              "good SR. Increase rate\n");
-                               scale_action = 1;
-                       }
-               }
-       }
-
-       /* Sanity check; asked for decrease, but success rate or throughput
-        * has been good at old rate.  Don't change it. */
-       if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
-           ((sr > IWL_RATE_HIGH_TH) ||
-            (current_tpt > (100 * tbl->expected_tpt[low])))) {
-               IWL_DEBUG_RATE(mvm,
-                              "Sanity check failed. Maintain rate\n");
-               scale_action = 0;
-       }
+       scale_action = rs_get_rate_action(mvm, tbl, sr, low, high,
+                                         current_tpt, low_tpt, high_tpt);
 
        /* Force a search in case BT doesn't like us being in MIMO */
        if (is_mimo(rate) &&
@@ -1977,7 +1939,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        }
 
        switch (scale_action) {
-       case -1:
+       case RS_ACTION_DOWNSCALE:
                /* Decrease starting rate, update uCode's rate table */
                if (low != IWL_RATE_INVALID) {
                        update_lq = 1;
@@ -1988,7 +1950,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                }
 
                break;
-       case 1:
+       case RS_ACTION_UPSCALE:
                /* Increase starting rate, update uCode's rate table */
                if (high != IWL_RATE_INVALID) {
                        update_lq = 1;
@@ -1999,7 +1961,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                }
 
                break;
-       case 0:
+       case RS_ACTION_STAY:
                /* No change */
        default:
                break;
@@ -2053,11 +2015,11 @@ lq_update:
                                rs_rate_scale_clear_window(&(tbl->win[i]));
 
                        /* Use new "search" start rate */
-                       index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
+                       index = tbl->rate.index;
 
                        rs_dump_rate(mvm, &tbl->rate,
                                     "Switch to SEARCH TABLE:");
-                       rs_fill_link_cmd(mvm, sta, lq_sta, tbl->current_rate);
+                       rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate);
                        iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
                } else {
                        done_search = 1;
@@ -2095,8 +2057,6 @@ lq_update:
        }
 
 out:
-       tbl->rate.index = index;
-       tbl->current_rate = ucode_rate_from_rs_rate(mvm, &tbl->rate);
        lq_sta->last_txrate_idx = index;
 }
 
@@ -2123,7 +2083,6 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
        struct iwl_scale_tbl_info *tbl;
        struct rs_rate *rate;
        int i;
-       u32 ucode_rate;
        u8 active_tbl = 0;
        u8 valid_tx_ant;
 
@@ -2154,9 +2113,6 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
        else
                rate->type = LQ_LEGACY_G;
 
-       ucode_rate = ucode_rate_from_rs_rate(mvm, rate);
-       tbl->current_rate = ucode_rate;
-
        WARN_ON_ONCE(rate->ant != ANT_A && rate->ant != ANT_B);
        if (rate->ant == ANT_A)
                tbl->column = RS_COLUMN_LEGACY_ANT_A;
@@ -2164,7 +2120,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
                tbl->column = RS_COLUMN_LEGACY_ANT_B;
 
        rs_set_expected_tpt_table(lq_sta, tbl);
-       rs_fill_link_cmd(NULL, NULL, lq_sta, ucode_rate);
+       rs_fill_lq_cmd(mvm, sta, lq_sta, rate);
        /* TODO restore station should remember the lq cmd */
        iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init);
 }
@@ -2250,6 +2206,10 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
                        if (i == IWL_RATE_9M_INDEX)
                                continue;
 
+                       /* Disable MCS9 as a workaround */
+                       if (i == IWL_RATE_MCS_9_INDEX)
+                               continue;
+
                        /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
                        if (i == IWL_RATE_MCS_9_INDEX &&
                            sta->bandwidth == IEEE80211_STA_RX_BW_20)
@@ -2268,6 +2228,10 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
                        if (i == IWL_RATE_9M_INDEX)
                                continue;
 
+                       /* Disable MCS9 as a workaround */
+                       if (i == IWL_RATE_MCS_9_INDEX)
+                               continue;
+
                        /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
                        if (i == IWL_RATE_MCS_9_INDEX &&
                            sta->bandwidth == IEEE80211_STA_RX_BW_20)
@@ -2306,7 +2270,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                        rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
 
        lq_sta->flush_timer = 0;
-       lq_sta->supp_rates = sta->supp_rates[sband->band];
 
        IWL_DEBUG_RATE(mvm,
                       "LQ: *** rate scale station global init for station %d ***\n",
@@ -2395,112 +2358,163 @@ static void rs_rate_update(void *mvm_r,
        iwl_mvm_rs_rate_init(mvm, sta, sband->band, false);
 }
 
-static void rs_fill_link_cmd(struct iwl_mvm *mvm,
-                            struct ieee80211_sta *sta,
-                            struct iwl_lq_sta *lq_sta, u32 new_rate)
+#ifdef CONFIG_MAC80211_DEBUGFS
+static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
+                                           struct iwl_lq_cmd *lq_cmd,
+                                           enum ieee80211_band band,
+                                           u32 ucode_rate)
 {
        struct rs_rate rate;
-       int index = 0;
-       int repeat_rate = 0;
-       u8 ant_toggle_cnt = 0;
-       u8 use_ht_possible = 1;
+       int i;
+       int num_rates = ARRAY_SIZE(lq_cmd->rs_table);
+       __le32 ucode_rate_le32 = cpu_to_le32(ucode_rate);
+
+       for (i = 0; i < num_rates; i++)
+               lq_cmd->rs_table[i] = ucode_rate_le32;
+
+       rs_rate_from_ucode_rate(ucode_rate, band, &rate);
+
+       if (is_mimo(&rate))
+               lq_cmd->mimo_delim = num_rates - 1;
+       else
+               lq_cmd->mimo_delim = 0;
+}
+#endif /* CONFIG_MAC80211_DEBUGFS */
+
+static void rs_fill_rates_for_column(struct iwl_mvm *mvm,
+                                    struct iwl_lq_sta *lq_sta,
+                                    struct rs_rate *rate,
+                                    __le32 *rs_table, int *rs_table_index,
+                                    int num_rates, int num_retries,
+                                    u8 valid_tx_ant, bool toggle_ant)
+{
+       int i, j;
+       __le32 ucode_rate;
+       bool bottom_reached = false;
+       int prev_rate_idx = rate->index;
+       int end = LINK_QUAL_MAX_RETRY_NUM;
+       int index = *rs_table_index;
+
+       for (i = 0; i < num_rates && index < end; i++) {
+               ucode_rate = cpu_to_le32(ucode_rate_from_rs_rate(mvm, rate));
+               for (j = 0; j < num_retries && index < end; j++, index++)
+                       rs_table[index] = ucode_rate;
+
+               if (toggle_ant)
+                       rs_toggle_antenna(valid_tx_ant, rate);
+
+               prev_rate_idx = rate->index;
+               bottom_reached = rs_get_lower_rate_in_column(lq_sta, rate);
+               if (bottom_reached && !is_legacy(rate))
+                       break;
+       }
+
+       if (!bottom_reached)
+               rate->index = prev_rate_idx;
+
+       *rs_table_index = index;
+}
+
+/* Building the rate table is non trivial. When we're in MIMO2/VHT/80Mhz/SGI
+ * column the rate table should look like this:
+ *
+ * rate[0] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
+ * rate[1] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
+ * rate[2] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
+ * rate[3] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
+ * rate[4] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
+ * rate[5] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
+ * rate[6] 0x4005007 VHT | ANT: A BW: 80Mhz MCS: 7 NSS: 1 NGI
+ * rate[7] 0x4009006 VHT | ANT: B BW: 80Mhz MCS: 6 NSS: 1 NGI
+ * rate[8] 0x4005005 VHT | ANT: A BW: 80Mhz MCS: 5 NSS: 1 NGI
+ * rate[9] 0x800B Legacy | ANT: B Rate: 36 Mbps
+ * rate[10] 0x4009 Legacy | ANT: A Rate: 24 Mbps
+ * rate[11] 0x8007 Legacy | ANT: B Rate: 18 Mbps
+ * rate[12] 0x4005 Legacy | ANT: A Rate: 12 Mbps
+ * rate[13] 0x800F Legacy | ANT: B Rate: 9 Mbps
+ * rate[14] 0x400D Legacy | ANT: A Rate: 6 Mbps
+ * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps
+ */
+static void rs_build_rates_table(struct iwl_mvm *mvm,
+                                struct iwl_lq_sta *lq_sta,
+                                const struct rs_rate *initial_rate)
+{
+       struct rs_rate rate;
+       int num_rates, num_retries, index = 0;
        u8 valid_tx_ant = 0;
        struct iwl_lq_cmd *lq_cmd = &lq_sta->lq;
+       bool toggle_ant = false;
 
-       /* Override starting rate (index 0) if needed for debug purposes */
-       rs_dbgfs_set_mcs(lq_sta, &new_rate);
+       memcpy(&rate, initial_rate, sizeof(rate));
 
-       rs_rate_from_ucode_rate(new_rate, lq_sta->band, &rate);
+       valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
 
-       /* How many times should we repeat the initial rate? */
-       if (is_legacy(&rate)) {
-               ant_toggle_cnt = 1;
-               repeat_rate = IWL_NUMBER_TRY;
+       if (is_siso(&rate)) {
+               num_rates = RS_INITIAL_SISO_NUM_RATES;
+               num_retries = RS_HT_VHT_RETRIES_PER_RATE;
+       } else if (is_mimo(&rate)) {
+               num_rates = RS_INITIAL_MIMO_NUM_RATES;
+               num_retries = RS_HT_VHT_RETRIES_PER_RATE;
        } else {
-               repeat_rate = min(IWL_HT_NUMBER_TRY,
-                                 LINK_QUAL_AGG_DISABLE_START_DEF - 1);
+               num_rates = RS_INITIAL_LEGACY_NUM_RATES;
+               num_retries = RS_LEGACY_RETRIES_PER_RATE;
+               toggle_ant = true;
        }
 
-       lq_cmd->mimo_delim = is_mimo(&rate) ? 1 : 0;
-
-       /* Fill 1st table entry (index 0) */
-       lq_cmd->rs_table[index] = cpu_to_le32(new_rate);
-
-       if (num_of_ant(rate.ant) == 1)
-               lq_cmd->single_stream_ant_msk = rate.ant;
-       /* otherwise we don't modify the existing value */
-
-       index++;
-       repeat_rate--;
-       if (mvm)
-               valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
-
-       /* Fill rest of rate table */
-       while (index < LINK_QUAL_MAX_RETRY_NUM) {
-               /* Repeat initial/next rate.
-                * For legacy IWL_NUMBER_TRY == 1, this loop will not execute.
-                * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
-               while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
-                       if (is_legacy(&rate)) {
-                               if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
-                                       ant_toggle_cnt++;
-                               else if (mvm &&
-                                        rs_toggle_antenna(valid_tx_ant,
-                                                       &new_rate, &rate))
-                                       ant_toggle_cnt = 1;
-                       }
+       rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index,
+                                num_rates, num_retries, valid_tx_ant,
+                                toggle_ant);
 
-                       /* Override next rate if needed for debug purposes */
-                       rs_dbgfs_set_mcs(lq_sta, &new_rate);
+       rs_get_lower_rate_down_column(lq_sta, &rate);
 
-                       /* Fill next table entry */
-                       lq_cmd->rs_table[index] =
-                                       cpu_to_le32(new_rate);
-                       repeat_rate--;
-                       index++;
-               }
+       if (is_siso(&rate)) {
+               num_rates = RS_SECONDARY_SISO_NUM_RATES;
+               num_retries = RS_SECONDARY_SISO_RETRIES;
+       } else if (is_legacy(&rate)) {
+               num_rates = RS_SECONDARY_LEGACY_NUM_RATES;
+               num_retries = RS_LEGACY_RETRIES_PER_RATE;
+       } else {
+               WARN_ON_ONCE(1);
+       }
 
-               rs_rate_from_ucode_rate(new_rate, lq_sta->band, &rate);
+       toggle_ant = true;
 
-               /* Indicate to uCode which entries might be MIMO.
-                * If initial rate was MIMO, this will finally end up
-                * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */
-               if (is_mimo(&rate))
-                       lq_cmd->mimo_delim = index;
+       rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index,
+                                num_rates, num_retries, valid_tx_ant,
+                                toggle_ant);
 
-               /* Get next rate */
-               new_rate = rs_get_lower_rate(lq_sta, &rate, rate.index,
-                                            use_ht_possible);
+       rs_get_lower_rate_down_column(lq_sta, &rate);
 
-               /* How many times should we repeat the next rate? */
-               if (is_legacy(&rate)) {
-                       if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
-                               ant_toggle_cnt++;
-                       else if (mvm &&
-                                rs_toggle_antenna(valid_tx_ant,
-                                                  &new_rate, &rate))
-                               ant_toggle_cnt = 1;
+       num_rates = RS_SECONDARY_LEGACY_NUM_RATES;
+       num_retries = RS_LEGACY_RETRIES_PER_RATE;
 
-                       repeat_rate = IWL_NUMBER_TRY;
-               } else {
-                       repeat_rate = IWL_HT_NUMBER_TRY;
-               }
+       rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index,
+                                num_rates, num_retries, valid_tx_ant,
+                                toggle_ant);
 
-               /* Don't allow HT rates after next pass.
-                * rs_get_lower_rate() will change type to LQ_LEGACY_A
-                * or LQ_LEGACY_G.
-                */
-               use_ht_possible = 0;
+}
 
-               /* Override next rate if needed for debug purposes */
-               rs_dbgfs_set_mcs(lq_sta, &new_rate);
+static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
+                          struct ieee80211_sta *sta,
+                          struct iwl_lq_sta *lq_sta,
+                          const struct rs_rate *initial_rate)
+{
+       struct iwl_lq_cmd *lq_cmd = &lq_sta->lq;
+       u8 ant = initial_rate->ant;
 
-               /* Fill next table entry */
-               lq_cmd->rs_table[index] = cpu_to_le32(new_rate);
+#ifdef CONFIG_MAC80211_DEBUGFS
+       if (lq_sta->dbg_fixed_rate) {
+               rs_build_rates_table_from_fixed(mvm, lq_cmd,
+                                               lq_sta->band,
+                                               lq_sta->dbg_fixed_rate);
+               ant = (lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >>
+                       RATE_MCS_ANT_POS;
+       } else
+#endif
+               rs_build_rates_table(mvm, lq_sta, initial_rate);
 
-               index++;
-               repeat_rate--;
-       }
+       if (num_of_ant(ant) == 1)
+               lq_cmd->single_stream_ant_msk = ant;
 
        lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
        lq_cmd->agg_disable_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
@@ -2534,31 +2548,6 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta,
 }
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
-                            u32 *rate_n_flags)
-{
-       struct iwl_mvm *mvm;
-       u8 valid_tx_ant;
-       u8 ant_sel_tx;
-
-       mvm = lq_sta->drv;
-       valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
-       if (lq_sta->dbg_fixed_rate) {
-               ant_sel_tx =
-                 ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
-                 >> RATE_MCS_ANT_POS);
-               if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) {
-                       *rate_n_flags = lq_sta->dbg_fixed_rate;
-               } else {
-                       lq_sta->dbg_fixed_rate = 0;
-                       IWL_ERR(mvm,
-                               "Invalid antenna selection 0x%X, Valid is 0x%X\n",
-                               ant_sel_tx, valid_tx_ant);
-                       IWL_DEBUG_RATE(mvm, "Fixed rate OFF\n");
-               }
-       }
-}
-
 static int rs_pretty_print_rate(char *buf, const u32 rate)
 {
 
@@ -2612,6 +2601,31 @@ static int rs_pretty_print_rate(char *buf, const u32 rate)
                       (rate & RATE_MCS_ZLF_MSK) ? "ZLF " : "");
 }
 
+/**
+ * Program the device to use fixed rate for frame transmit
+ * This is for debugging/testing only
+ * once the device start use fixed rate, we need to reload the module
+ * to being back the normal operation.
+ */
+static void rs_program_fix_rate(struct iwl_mvm *mvm,
+                               struct iwl_lq_sta *lq_sta)
+{
+       lq_sta->active_legacy_rate = 0x0FFF;    /* 1 - 54 MBits, includes CCK */
+       lq_sta->active_siso_rate   = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
+       lq_sta->active_mimo2_rate  = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
+
+       IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n",
+                      lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
+
+       if (lq_sta->dbg_fixed_rate) {
+               struct rs_rate rate;
+               rs_rate_from_ucode_rate(lq_sta->dbg_fixed_rate,
+                                       lq_sta->band, &rate);
+               rs_fill_lq_cmd(mvm, NULL, lq_sta, &rate);
+               iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false);
+       }
+}
+
 static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
                        const char __user *user_buf, size_t count, loff_t *ppos)
 {
@@ -2702,12 +2716,10 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
                        lq_sta->lq.initial_rate_index[3]);
 
        for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
-               u32 rate = le32_to_cpu(lq_sta->lq.rs_table[i]);
-               desc += sprintf(buff+desc,
-                               " rate[%d] 0x%X ",
-                               i, rate);
+               u32 r = le32_to_cpu(lq_sta->lq.rs_table[i]);
 
-               desc += rs_pretty_print_rate(buff+desc, rate);
+               desc += sprintf(buff+desc, " rate[%d] 0x%X ", i, r);
+               desc += rs_pretty_print_rate(buff+desc, r);
        }
 
        ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
@@ -2741,14 +2753,14 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
                rate = &tbl->rate;
                desc += sprintf(buff+desc,
                                "%s type=%d SGI=%d BW=%s DUP=0\n"
-                               "rate=0x%X\n",
+                               "index=%d\n",
                                lq_sta->active_tbl == i ? "*" : "x",
                                rate->type,
                                rate->sgi,
                                is_ht20(rate) ? "20Mhz" :
                                is_ht40(rate) ? "40Mhz" :
                                is_ht80(rate) ? "80Mhz" : "ERR",
-                               tbl->current_rate);
+                               rate->index);
                for (j = 0; j < IWL_RATE_COUNT; j++) {
                        desc += sprintf(buff+desc,
                                "counter=%d success=%d %%=%d\n",
index b32960796384e15331fcd4b8149fbd1fb8cc91a0..7bc6404f6986f4b0babca6c5d8c17bc94343e0f9 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -278,7 +278,6 @@ struct iwl_scale_tbl_info {
        struct rs_rate rate;
        enum rs_column column;
        s32 *expected_tpt;      /* throughput metrics; expected_tpt_G, etc. */
-       u32 current_rate;  /* rate_n_flags, uCode API format */
        struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
 };
 
@@ -315,7 +314,6 @@ struct iwl_lq_sta {
        enum ieee80211_band band;
 
        /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
-       u32 supp_rates;
        u16 active_legacy_rate;
        u16 active_siso_rate;
        u16 active_mimo2_rate;
index 3a1f3982109d1dbc02bccba42588545e000b8271..a85b60f7e67e47e24c842f65f726794dd32dfddd 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -251,6 +251,12 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
                stats->flag |= RX_FLAG_DECRYPTED;
                return 0;
 
+       case RX_MPDU_RES_STATUS_SEC_EXT_ENC:
+               if (!(rx_pkt_status & RX_MPDU_RES_STATUS_MIC_OK))
+                       return -1;
+               stats->flag |= RX_FLAG_DECRYPTED;
+               return 0;
+
        default:
                IWL_ERR(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status);
        }
index 4ce9bb581144e4a64c8842980e41e0097a4da6e9..0e0007960612e7866b332e27a1f19af9c5847afc 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -473,13 +473,18 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
        if (mvm->scan_status == IWL_MVM_SCAN_NONE)
                return;
 
+       if (iwl_mvm_is_radio_killed(mvm)) {
+               ieee80211_scan_completed(mvm->hw, true);
+               mvm->scan_status = IWL_MVM_SCAN_NONE;
+               return;
+       }
+
        iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort,
                                   scan_abort_notif,
                                   ARRAY_SIZE(scan_abort_notif),
                                   iwl_mvm_scan_abort_notif, NULL);
 
-       ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD,
-                                  CMD_SYNC | CMD_SEND_IN_RFKILL, 0, NULL);
+       ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, CMD_SYNC, 0, NULL);
        if (ret) {
                IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret);
                /* mac80211's state will be cleaned in the fw_restart flow */
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c
new file mode 100644 (file)
index 0000000..8401627
--- /dev/null
@@ -0,0 +1,291 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 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.
+ *
+ *****************************************************************************/
+#include "mvm.h"
+
+/* For counting bound interfaces */
+struct iwl_mvm_active_iface_iterator_data {
+       struct ieee80211_vif *ignore_vif;
+       u8 sta_vif_ap_sta_id;
+       enum iwl_sf_state sta_vif_state;
+       int num_active_macs;
+};
+
+/*
+ * Count bound interfaces which are not p2p, besides data->ignore_vif.
+ * data->station_vif will point to one bound vif of type station, if exists.
+ */
+static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac,
+                                        struct ieee80211_vif *vif)
+{
+       struct iwl_mvm_active_iface_iterator_data *data = _data;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       if (vif == data->ignore_vif || !mvmvif->phy_ctxt ||
+           vif->type == NL80211_IFTYPE_P2P_DEVICE)
+               return;
+
+       data->num_active_macs++;
+
+       if (vif->type == NL80211_IFTYPE_STATION) {
+               data->sta_vif_ap_sta_id = mvmvif->ap_sta_id;
+               if (vif->bss_conf.assoc)
+                       data->sta_vif_state = SF_FULL_ON;
+               else
+                       data->sta_vif_state = SF_INIT_OFF;
+       }
+}
+
+/*
+ * Aging and idle timeouts for the different possible scenarios
+ * in SF_FULL_ON state.
+ */
+static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = {
+       {
+               cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER),
+               cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER)
+       },
+       {
+               cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER),
+               cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER)
+       },
+       {
+               cpu_to_le32(SF_MCAST_AGING_TIMER),
+               cpu_to_le32(SF_MCAST_IDLE_TIMER)
+       },
+       {
+               cpu_to_le32(SF_BA_AGING_TIMER),
+               cpu_to_le32(SF_BA_IDLE_TIMER)
+       },
+       {
+               cpu_to_le32(SF_TX_RE_AGING_TIMER),
+               cpu_to_le32(SF_TX_RE_IDLE_TIMER)
+       },
+};
+
+static void iwl_mvm_fill_sf_command(struct iwl_sf_cfg_cmd *sf_cmd,
+                                   struct ieee80211_sta *sta)
+{
+       int i, j, watermark;
+
+       sf_cmd->watermark[SF_LONG_DELAY_ON] = cpu_to_le32(SF_W_MARK_SCAN);
+
+       /*
+        * If we are in association flow - check antenna configuration
+        * capabilities of the AP station, and choose the watermark accordingly.
+        */
+       if (sta) {
+               if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) {
+                       switch (sta->rx_nss) {
+                       case 1:
+                               watermark = SF_W_MARK_SISO;
+                               break;
+                       case 2:
+                               watermark = SF_W_MARK_MIMO2;
+                               break;
+                       default:
+                               watermark = SF_W_MARK_MIMO3;
+                               break;
+                       }
+               } else {
+                       watermark = SF_W_MARK_LEGACY;
+               }
+       /* default watermark value for unassociated mode. */
+       } else {
+               watermark = SF_W_MARK_MIMO2;
+       }
+       sf_cmd->watermark[SF_FULL_ON] = cpu_to_le32(watermark);
+
+       for (i = 0; i < SF_NUM_SCENARIO; i++) {
+               for (j = 0; j < SF_NUM_TIMEOUT_TYPES; j++) {
+                       sf_cmd->long_delay_timeouts[i][j] =
+                                       cpu_to_le32(SF_LONG_DELAY_AGING_TIMER);
+               }
+       }
+       BUILD_BUG_ON(sizeof(sf_full_timeout) !=
+                    sizeof(__le32) * SF_NUM_SCENARIO * SF_NUM_TIMEOUT_TYPES);
+
+       memcpy(sf_cmd->full_on_timeouts, sf_full_timeout,
+              sizeof(sf_full_timeout));
+}
+
+static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id,
+                            enum iwl_sf_state new_state)
+{
+       struct iwl_sf_cfg_cmd sf_cmd = {
+               .state = new_state,
+       };
+       struct ieee80211_sta *sta;
+       int ret = 0;
+
+       /*
+        * If an associated AP sta changed its antenna configuration, the state
+        * will remain FULL_ON but SF parameters need to be reconsidered.
+        */
+       if (new_state != SF_FULL_ON && mvm->sf_state == new_state)
+               return 0;
+
+       switch (new_state) {
+       case SF_UNINIT:
+               break;
+       case SF_FULL_ON:
+               if (sta_id == IWL_MVM_STATION_COUNT) {
+                       IWL_ERR(mvm,
+                               "No station: Cannot switch SF to FULL_ON\n");
+                       return -EINVAL;
+               }
+               rcu_read_lock();
+               sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
+               if (IS_ERR_OR_NULL(sta)) {
+                       IWL_ERR(mvm, "Invalid station id\n");
+                       rcu_read_unlock();
+                       return -EINVAL;
+               }
+               iwl_mvm_fill_sf_command(&sf_cmd, sta);
+               rcu_read_unlock();
+               break;
+       case SF_INIT_OFF:
+               iwl_mvm_fill_sf_command(&sf_cmd, NULL);
+               break;
+       default:
+               WARN_ONCE(1, "Invalid state: %d. not sending Smart Fifo cmd\n",
+                         new_state);
+               return -EINVAL;
+       }
+
+       ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_SF_CFG_CMD, CMD_ASYNC,
+                                  sizeof(sf_cmd), &sf_cmd);
+       if (!ret)
+               mvm->sf_state = new_state;
+
+       return ret;
+}
+
+/*
+ * Update Smart fifo:
+ * Count bound interfaces that are not to be removed, ignoring p2p devices,
+ * and set new state accordingly.
+ */
+int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
+                     bool remove_vif)
+{
+       enum iwl_sf_state new_state;
+       u8 sta_id = IWL_MVM_STATION_COUNT;
+       struct iwl_mvm_vif *mvmvif = NULL;
+       struct iwl_mvm_active_iface_iterator_data data = {
+               .ignore_vif = changed_vif,
+               .sta_vif_state = SF_UNINIT,
+               .sta_vif_ap_sta_id = IWL_MVM_STATION_COUNT,
+       };
+
+       if (IWL_UCODE_API(mvm->fw->ucode_ver) < 8)
+               return 0;
+
+       /*
+        * Ignore the call if we are in HW Restart flow, or if the handled
+        * vif is a p2p device.
+        */
+       if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
+           (changed_vif && changed_vif->type == NL80211_IFTYPE_P2P_DEVICE))
+               return 0;
+
+       ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+                                                  IEEE80211_IFACE_ITER_NORMAL,
+                                                  iwl_mvm_bound_iface_iterator,
+                                                  &data);
+
+       /* If changed_vif exists and is not to be removed, add to the count */
+       if (changed_vif && !remove_vif)
+               data.num_active_macs++;
+
+       switch (data.num_active_macs) {
+       case 0:
+               /* If there are no active macs - change state to SF_INIT_OFF */
+               new_state = SF_INIT_OFF;
+               break;
+       case 1:
+               if (remove_vif) {
+                       /* The one active mac left is of type station
+                        * and we filled the relevant data during iteration
+                        */
+                       new_state = data.sta_vif_state;
+                       sta_id = data.sta_vif_ap_sta_id;
+               } else {
+                       if (WARN_ON(!changed_vif))
+                               return -EINVAL;
+                       if (changed_vif->type != NL80211_IFTYPE_STATION) {
+                               new_state = SF_UNINIT;
+                       } else if (changed_vif->bss_conf.assoc) {
+                               mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
+                               sta_id = mvmvif->ap_sta_id;
+                               new_state = SF_FULL_ON;
+                       } else {
+                               new_state = SF_INIT_OFF;
+                       }
+               }
+               break;
+       default:
+               /* If there are multiple active macs - change to SF_UNINIT */
+               new_state = SF_UNINIT;
+       }
+       return iwl_mvm_sf_config(mvm, sta_id, new_state);
+}
index 7a5b7473eafa615e946d3d4fe0802129149858bc..ec1812133235d8834ab5a235b66794e20d6a9bbd 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -452,8 +452,15 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk)
                        rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
                                                  lockdep_is_held(&mvm->mutex));
 
-               /* This station is in use */
-               if (!IS_ERR(sta))
+               /*
+                * This station is in use or RCU-removed; the latter happens in
+                * managed mode, where mac80211 removes the station before we
+                * can remove it from firmware (we can only do that after the
+                * MAC is marked unassociated), and possibly while the deauth
+                * frame to disconnect from the AP is still queued. Then, the
+                * station pointer is -ENOENT when the last skb is reclaimed.
+                */
+               if (!IS_ERR(sta) || PTR_ERR(sta) == -ENOENT)
                        continue;
 
                if (PTR_ERR(sta) == -EINVAL) {
@@ -932,19 +939,6 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",
                     sta->addr, tid);
 
-       if (mvm->cfg->ht_params->use_rts_for_aggregation) {
-               /*
-                * switch to RTS/CTS if it is the prefer protection
-                * method for HT traffic
-                * this function also sends the LQ command
-                */
-               return iwl_mvm_tx_protection(mvm, mvmsta, true);
-               /*
-                * TODO: remove the TLC_RTS flag when we tear down the last
-                * AGG session (agg_tids_count in DVM)
-                */
-       }
-
        return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, false);
 }
 
@@ -1123,8 +1117,8 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
                memcpy(cmd.key, keyconf->key, keyconf->keylen);
                break;
        default:
-               WARN_ON(1);
-               return -EINVAL;
+               key_flags |= cpu_to_le16(STA_KEY_FLG_EXT);
+               memcpy(cmd.key, keyconf->key, keyconf->keylen);
        }
 
        if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
@@ -1288,8 +1282,8 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
                                           0, NULL, CMD_SYNC);
                break;
        default:
-               IWL_ERR(mvm, "Unknown cipher %x\n", keyconf->cipher);
-               ret = -EINVAL;
+               ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,
+                                          sta_id, 0, NULL, CMD_SYNC);
        }
 
        if (ret)
index b34941148a9834161eea211bfb17e9c568e9aa6d..4968d0237dc5455d6aa29f3fa5f03e470effd596 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index eb74391d91cac9a7469277c3beab830427bbfa0f..0241665925f704037faeb73999989a2cadff21b2 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 95ce4b601fef3050085518e59a4e32036c57fbfc..50f3d7f560bc1a82094e5db23bdc3c0926b731e9 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index d9c8d6cfa2db0c4a44a58b0ec2bc0eaf6fca94cc..4a61c8c02372824cd08b3901f2e26c2a0353f35d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 18be04da8e3fe5449307d4c63c5e6714e0e032e1..3afa6b6bf83571734eae30e9042c798a0bdb65ed 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -340,7 +340,7 @@ static void check_exit_ctkill(struct work_struct *work)
 
        iwl_trans_start_hw(mvm->trans);
        temp = check_nic_temperature(mvm);
-       iwl_trans_stop_hw(mvm->trans, false);
+       iwl_trans_stop_device(mvm->trans);
 
        if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) {
                IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n");
index d87649ac88e1419fde870f4f7fdb4abc1d520fab..3c575a39987bc0ffed36c67c06c22cc336f86ff1 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -253,8 +253,7 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
                memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
                break;
        default:
-               IWL_ERR(mvm, "Unknown encode cipher %x\n", keyconf->cipher);
-               break;
+               tx_cmd->sec_ctl |= TX_CMD_SEC_EXT;
        }
 }
 
index 56cf819bc0c7003d970a16b08b493804d6e2544b..487d61b25359bb54cb99aa00cd107b060d76ce16 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -518,6 +518,11 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        int i;
 
        lockdep_assert_held(&mvm->mutex);
+
+       /* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */
+       if (num_of_ant(iwl_fw_valid_rx_ant(mvm->fw)) == 1)
+               return;
+
        mvmvif = iwl_mvm_vif_from_mac80211(vif);
        mvmvif->smps_requests[req_type] = smps_request;
        for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
index 2e97a39953339abdf436b90c2553c790b342ab07..e58b8af56c045f0095d6d41405b3bc3f2ce83dab 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 051268c037b1d4f7d03715cdbf13b68311f883ff..e851f26fd44c1644c81b24f9a91b690ab2fb418e 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
@@ -256,13 +256,13 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
  * @hw_base: pci hardware address support
  * @ucode_write_complete: indicates that the ucode has been copied.
  * @ucode_write_waitq: wait queue for uCode load
- * @status - transport specific status flags
  * @cmd_queue - command queue number
  * @rx_buf_size_8k: 8 kB RX buffer size
  * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes)
  * @rx_page_order: page order for receive buffer size
  * @wd_timeout: queue watchdog timeout (jiffies)
  * @reg_lock: protect hw register access
+ * @cmd_in_flight: true when we have a host command in flight
  */
 struct iwl_trans_pcie {
        struct iwl_rxq rxq;
@@ -274,7 +274,6 @@ struct iwl_trans_pcie {
        __le32 *ict_tbl;
        dma_addr_t ict_tbl_dma;
        int ict_index;
-       u32 inta;
        bool use_ict;
        struct isr_statistics isr_stats;
 
@@ -296,7 +295,6 @@ struct iwl_trans_pcie {
        wait_queue_head_t ucode_write_waitq;
        wait_queue_head_t wait_command_queue;
 
-       unsigned long status;
        u8 cmd_queue;
        u8 cmd_fifo;
        u8 n_no_reclaim_cmds;
@@ -313,24 +311,7 @@ struct iwl_trans_pcie {
 
        /*protect hw register */
        spinlock_t reg_lock;
-};
-
-/**
- * enum iwl_pcie_status: status of the PCIe transport
- * @STATUS_HCMD_ACTIVE: a SYNC command is being processed
- * @STATUS_DEVICE_ENABLED: APM is enabled
- * @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up)
- * @STATUS_INT_ENABLED: interrupts are enabled
- * @STATUS_RFKILL: the HW RFkill switch is in KILL position
- * @STATUS_FW_ERROR: the fw is in error state
- */
-enum iwl_pcie_status {
-       STATUS_HCMD_ACTIVE,
-       STATUS_DEVICE_ENABLED,
-       STATUS_TPOWER_PMI,
-       STATUS_INT_ENABLED,
-       STATUS_RFKILL,
-       STATUS_FW_ERROR,
+       bool cmd_in_flight;
 };
 
 #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
@@ -363,7 +344,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans);
 /*****************************************************
 * ICT - interrupt handling
 ******************************************************/
-irqreturn_t iwl_pcie_isr_ict(int irq, void *data);
+irqreturn_t iwl_pcie_isr(int irq, void *data);
 int iwl_pcie_alloc_ict(struct iwl_trans *trans);
 void iwl_pcie_free_ict(struct iwl_trans *trans);
 void iwl_pcie_reset_ict(struct iwl_trans *trans);
@@ -399,8 +380,7 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans);
 ******************************************************/
 static inline void iwl_disable_interrupts(struct iwl_trans *trans)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       clear_bit(STATUS_INT_ENABLED, &trans_pcie->status);
+       clear_bit(STATUS_INT_ENABLED, &trans->status);
 
        /* disable interrupts from uCode/NIC to host */
        iwl_write32(trans, CSR_INT_MASK, 0x00000000);
@@ -417,14 +397,18 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
        IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
-       set_bit(STATUS_INT_ENABLED, &trans_pcie->status);
+       set_bit(STATUS_INT_ENABLED, &trans->status);
+       trans_pcie->inta_mask = CSR_INI_SET_MASK;
        iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
 }
 
 static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
 {
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
        IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
-       iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+       trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL;
+       iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
 }
 
 static inline void iwl_wake_queue(struct iwl_trans *trans,
@@ -477,12 +461,31 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
                CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
 }
 
-static inline void iwl_nic_error(struct iwl_trans *trans)
+static inline void __iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans,
+                                                 u32 reg, u32 mask, u32 value)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       u32 v;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+       WARN_ON_ONCE(value & ~mask);
+#endif
+
+       v = iwl_read32(trans, reg);
+       v &= ~mask;
+       v |= value;
+       iwl_write32(trans, reg, v);
+}
 
-       set_bit(STATUS_FW_ERROR, &trans_pcie->status);
-       iwl_op_mode_nic_error(trans->op_mode);
+static inline void __iwl_trans_pcie_clear_bit(struct iwl_trans *trans,
+                                             u32 reg, u32 mask)
+{
+       __iwl_trans_pcie_set_bits_mask(trans, reg, mask, 0);
+}
+
+static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
+                                           u32 reg, u32 mask)
+{
+       __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask);
 }
 
 #endif /* __iwl_trans_int_pcie_h__ */
index 1d6bf7b98e2d0075c1e09f05b5f4ee96dce71474..1890ea29c264c2eeeedced38d8f033b5bae67c53 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
@@ -148,10 +148,9 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans)
 static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
                                    struct iwl_rxq *rxq)
 {
-       unsigned long flags;
        u32 reg;
 
-       spin_lock_irqsave(&rxq->lock, flags);
+       spin_lock(&rxq->lock);
 
        if (rxq->need_update == 0)
                goto exit_unlock;
@@ -162,11 +161,8 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
                rxq->write_actual = (rxq->write & ~0x7);
                iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
        } else {
-               struct iwl_trans_pcie *trans_pcie =
-                       IWL_TRANS_GET_PCIE_TRANS(trans);
-
                /* If power-saving is in use, make sure device is awake */
-               if (test_bit(STATUS_TPOWER_PMI, &trans_pcie->status)) {
+               if (test_bit(STATUS_TPOWER_PMI, &trans->status)) {
                        reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
 
                        if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
@@ -193,7 +189,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
        rxq->need_update = 0;
 
  exit_unlock:
-       spin_unlock_irqrestore(&rxq->lock, flags);
+       spin_unlock(&rxq->lock);
 }
 
 /*
@@ -212,7 +208,6 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_rxq *rxq = &trans_pcie->rxq;
        struct iwl_rx_mem_buffer *rxb;
-       unsigned long flags;
 
        /*
         * If the device isn't enabled - not need to try to add buffers...
@@ -222,10 +217,10 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
         * stopped, we cannot access the HW (in particular not prph).
         * So don't try to restock if the APM has been already stopped.
         */
-       if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status))
+       if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status))
                return;
 
-       spin_lock_irqsave(&rxq->lock, flags);
+       spin_lock(&rxq->lock);
        while ((iwl_rxq_space(rxq) > 0) && (rxq->free_count)) {
                /* The overwritten rxb must be a used one */
                rxb = rxq->queue[rxq->write];
@@ -242,7 +237,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
                rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
                rxq->free_count--;
        }
-       spin_unlock_irqrestore(&rxq->lock, flags);
+       spin_unlock(&rxq->lock);
        /* If the pre-allocated buffer pool is dropping low, schedule to
         * refill it */
        if (rxq->free_count <= RX_LOW_WATERMARK)
@@ -251,9 +246,9 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
        /* If we've added more space for the firmware to place data, tell it.
         * Increment device's write pointer in multiples of 8. */
        if (rxq->write_actual != (rxq->write & ~0x7)) {
-               spin_lock_irqsave(&rxq->lock, flags);
+               spin_lock(&rxq->lock);
                rxq->need_update = 1;
-               spin_unlock_irqrestore(&rxq->lock, flags);
+               spin_unlock(&rxq->lock);
                iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
        }
 }
@@ -273,16 +268,15 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
        struct iwl_rxq *rxq = &trans_pcie->rxq;
        struct iwl_rx_mem_buffer *rxb;
        struct page *page;
-       unsigned long flags;
        gfp_t gfp_mask = priority;
 
        while (1) {
-               spin_lock_irqsave(&rxq->lock, flags);
+               spin_lock(&rxq->lock);
                if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       spin_unlock(&rxq->lock);
                        return;
                }
-               spin_unlock_irqrestore(&rxq->lock, flags);
+               spin_unlock(&rxq->lock);
 
                if (rxq->free_count > RX_LOW_WATERMARK)
                        gfp_mask |= __GFP_NOWARN;
@@ -311,17 +305,17 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
                        return;
                }
 
-               spin_lock_irqsave(&rxq->lock, flags);
+               spin_lock(&rxq->lock);
 
                if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       spin_unlock(&rxq->lock);
                        __free_pages(page, trans_pcie->rx_page_order);
                        return;
                }
                rxb = list_first_entry(&rxq->rx_used, struct iwl_rx_mem_buffer,
                                       list);
                list_del(&rxb->list);
-               spin_unlock_irqrestore(&rxq->lock, flags);
+               spin_unlock(&rxq->lock);
 
                BUG_ON(rxb->page);
                rxb->page = page;
@@ -332,9 +326,9 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
                                     DMA_FROM_DEVICE);
                if (dma_mapping_error(trans->dev, rxb->page_dma)) {
                        rxb->page = NULL;
-                       spin_lock_irqsave(&rxq->lock, flags);
+                       spin_lock(&rxq->lock);
                        list_add(&rxb->list, &rxq->rx_used);
-                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       spin_unlock(&rxq->lock);
                        __free_pages(page, trans_pcie->rx_page_order);
                        return;
                }
@@ -343,12 +337,12 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
                /* and also 256 byte aligned! */
                BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
 
-               spin_lock_irqsave(&rxq->lock, flags);
+               spin_lock(&rxq->lock);
 
                list_add_tail(&rxb->list, &rxq->rx_free);
                rxq->free_count++;
 
-               spin_unlock_irqrestore(&rxq->lock, flags);
+               spin_unlock(&rxq->lock);
        }
 }
 
@@ -382,13 +376,12 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans)
 static void iwl_pcie_rx_replenish(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       unsigned long flags;
 
        iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL);
 
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
        iwl_pcie_rxq_restock(trans);
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 }
 
 static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans)
@@ -514,7 +507,6 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_rxq *rxq = &trans_pcie->rxq;
        int i, err;
-       unsigned long flags;
 
        if (!rxq->bd) {
                err = iwl_pcie_rx_alloc(trans);
@@ -522,7 +514,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
                        return err;
        }
 
-       spin_lock_irqsave(&rxq->lock, flags);
+       spin_lock(&rxq->lock);
 
        INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work);
 
@@ -538,16 +530,16 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
        rxq->read = rxq->write = 0;
        rxq->write_actual = 0;
        memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
-       spin_unlock_irqrestore(&rxq->lock, flags);
+       spin_unlock(&rxq->lock);
 
        iwl_pcie_rx_replenish(trans);
 
        iwl_pcie_rx_hw_init(trans, rxq);
 
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
        rxq->need_update = 1;
        iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 
        return 0;
 }
@@ -556,7 +548,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_rxq *rxq = &trans_pcie->rxq;
-       unsigned long flags;
 
        /*if rxq->bd is NULL, it means that nothing has been allocated,
         * exit now */
@@ -567,9 +558,9 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
 
        cancel_work_sync(&trans_pcie->rx_replenish);
 
-       spin_lock_irqsave(&rxq->lock, flags);
+       spin_lock(&rxq->lock);
        iwl_pcie_rxq_free_rbs(trans);
-       spin_unlock_irqrestore(&rxq->lock, flags);
+       spin_unlock(&rxq->lock);
 
        dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE,
                          rxq->bd, rxq->bd_dma);
@@ -592,7 +583,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_rxq *rxq = &trans_pcie->rxq;
        struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
-       unsigned long flags;
        bool page_stolen = false;
        int max_len = PAGE_SIZE << trans_pcie->rx_page_order;
        u32 offset = 0;
@@ -694,7 +684,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
        /* Reuse the page if possible. For notification packets and
         * SKBs that fail to Rx correctly, add them back into the
         * rx_free list for reuse later. */
-       spin_lock_irqsave(&rxq->lock, flags);
+       spin_lock(&rxq->lock);
        if (rxb->page != NULL) {
                rxb->page_dma =
                        dma_map_page(trans->dev, rxb->page, 0,
@@ -715,7 +705,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
                }
        } else
                list_add_tail(&rxb->list, &rxq->rx_used);
-       spin_unlock_irqrestore(&rxq->lock, flags);
+       spin_unlock(&rxq->lock);
 }
 
 /*
@@ -791,7 +781,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
                             APMS_CLK_VAL_MRB_FUNC_MODE) ||
             (iwl_read_prph(trans, APMG_PS_CTRL_REG) &
                            APMG_PS_CTRL_VAL_RESET_REQ))) {
-               clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
+               clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
                iwl_op_mode_wimax_active(trans->op_mode);
                wake_up(&trans_pcie->wait_command_queue);
                return;
@@ -800,14 +790,95 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
        iwl_pcie_dump_csr(trans);
        iwl_dump_fh(trans, NULL);
 
-       /* set the ERROR bit before we wake up the caller */
-       set_bit(STATUS_FW_ERROR, &trans_pcie->status);
-       clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
-       wake_up(&trans_pcie->wait_command_queue);
-
        local_bh_disable();
-       iwl_nic_error(trans);
+       /* The STATUS_FW_ERROR bit is set in this function. This must happen
+        * before we wake up the command caller, to ensure a proper cleanup. */
+       iwl_trans_fw_error(trans);
        local_bh_enable();
+
+       clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
+       wake_up(&trans_pcie->wait_command_queue);
+}
+
+static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       u32 inta;
+
+       lockdep_assert_held(&trans_pcie->irq_lock);
+
+       trace_iwlwifi_dev_irq(trans->dev);
+
+       /* Discover which interrupts are active/pending */
+       inta = iwl_read32(trans, CSR_INT);
+
+       /* the thread will service interrupts and re-enable them */
+       return inta;
+}
+
+/* a device (PCI-E) page is 4096 bytes long */
+#define ICT_SHIFT      12
+#define ICT_SIZE       (1 << ICT_SHIFT)
+#define ICT_COUNT      (ICT_SIZE / sizeof(u32))
+
+/* interrupt handler using ict table, with this interrupt driver will
+ * stop using INTA register to get device's interrupt, reading this register
+ * is expensive, device will write interrupts in ICT dram table, increment
+ * index then will fire interrupt to driver, driver will OR all ICT table
+ * entries from current index up to table entry with 0 value. the result is
+ * the interrupt we need to service, driver will set the entries back to 0 and
+ * set index.
+ */
+static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       u32 inta;
+       u32 val = 0;
+       u32 read;
+
+       trace_iwlwifi_dev_irq(trans->dev);
+
+       /* Ignore interrupt if there's nothing in NIC to service.
+        * This may be due to IRQ shared with another device,
+        * or due to sporadic interrupts thrown from our NIC. */
+       read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+       trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
+       if (!read)
+               return 0;
+
+       /*
+        * Collect all entries up to the first 0, starting from ict_index;
+        * note we already read at ict_index.
+        */
+       do {
+               val |= read;
+               IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
+                               trans_pcie->ict_index, read);
+               trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
+               trans_pcie->ict_index =
+                       iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
+
+               read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+               trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
+                                          read);
+       } while (read);
+
+       /* We should not get this value, just ignore it. */
+       if (val == 0xffffffff)
+               val = 0;
+
+       /*
+        * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
+        * (bit 15 before shifting it to 31) to clear when using interrupt
+        * coalescing. fortunately, bits 18 and 19 stay set when this happens
+        * so we use them to decide on the real state of the Rx bit.
+        * In order words, bit 15 is set if bit 18 or bit 19 are set.
+        */
+       if (val & 0xC0000)
+               val |= 0x8000;
+
+       inta = (0xff & val) | ((0xff00 & val) << 16);
+       return inta;
 }
 
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
@@ -817,12 +888,61 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
        struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
        u32 inta = 0;
        u32 handled = 0;
-       unsigned long flags;
        u32 i;
 
        lock_map_acquire(&trans->sync_cmd_lockdep_map);
 
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
+
+       /* dram interrupt table not set yet,
+        * use legacy interrupt.
+        */
+       if (likely(trans_pcie->use_ict))
+               inta = iwl_pcie_int_cause_ict(trans);
+       else
+               inta = iwl_pcie_int_cause_non_ict(trans);
+
+       if (iwl_have_debug_level(IWL_DL_ISR)) {
+               IWL_DEBUG_ISR(trans,
+                             "ISR inta 0x%08x, enabled 0x%08x(sw), enabled(hw) 0x%08x, fh 0x%08x\n",
+                             inta, trans_pcie->inta_mask,
+                             iwl_read32(trans, CSR_INT_MASK),
+                             iwl_read32(trans, CSR_FH_INT_STATUS));
+               if (inta & (~trans_pcie->inta_mask))
+                       IWL_DEBUG_ISR(trans,
+                                     "We got a masked interrupt (0x%08x)\n",
+                                     inta & (~trans_pcie->inta_mask));
+       }
+
+       inta &= trans_pcie->inta_mask;
+
+       /*
+        * Ignore interrupt if there's nothing in NIC to service.
+        * This may be due to IRQ shared with another device,
+        * or due to sporadic interrupts thrown from our NIC.
+        */
+       if (unlikely(!inta)) {
+               IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+               /*
+                * Re-enable interrupts here since we don't
+                * have anything to service
+                */
+               if (test_bit(STATUS_INT_ENABLED, &trans->status))
+                       iwl_enable_interrupts(trans);
+               spin_unlock(&trans_pcie->irq_lock);
+               lock_map_release(&trans->sync_cmd_lockdep_map);
+               return IRQ_NONE;
+       }
+
+       if (unlikely(inta == 0xFFFFFFFF || (inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+               /*
+                * Hardware disappeared. It might have
+                * already raised an interrupt.
+                */
+               IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+               spin_unlock(&trans_pcie->irq_lock);
+               goto out;
+       }
 
        /* Ack/clear/reset pending uCode interrupts.
         * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
@@ -835,19 +955,13 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
         * hardware bugs here by ACKing all the possible interrupts so that
         * interrupt coalescing can still be achieved.
         */
-       iwl_write32(trans, CSR_INT,
-                   trans_pcie->inta | ~trans_pcie->inta_mask);
-
-       inta = trans_pcie->inta;
+       iwl_write32(trans, CSR_INT, inta | ~trans_pcie->inta_mask);
 
        if (iwl_have_debug_level(IWL_DL_ISR))
                IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n",
                              inta, iwl_read32(trans, CSR_INT_MASK));
 
-       /* saved interrupt in inta variable now we can reset trans_pcie->inta */
-       trans_pcie->inta = 0;
-
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 
        /* Now service all interrupt bits discovered above. */
        if (inta & CSR_INT_BIT_HW_ERR) {
@@ -894,14 +1008,14 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 
                iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
                if (hw_rfkill) {
-                       set_bit(STATUS_RFKILL, &trans_pcie->status);
-                       if (test_and_clear_bit(STATUS_HCMD_ACTIVE,
-                                              &trans_pcie->status))
+                       set_bit(STATUS_RFKILL, &trans->status);
+                       if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE,
+                                              &trans->status))
                                IWL_DEBUG_RF_KILL(trans,
                                                  "Rfkill while SYNC HCMD in flight\n");
                        wake_up(&trans_pcie->wait_command_queue);
                } else {
-                       clear_bit(STATUS_RFKILL, &trans_pcie->status);
+                       clear_bit(STATUS_RFKILL, &trans->status);
                }
 
                handled |= CSR_INT_BIT_RF_KILL;
@@ -1005,7 +1119,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 
        /* Re-enable all interrupts */
        /* only Re-enable if disabled by irq */
-       if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status))
+       if (test_bit(STATUS_INT_ENABLED, &trans->status))
                iwl_enable_interrupts(trans);
        /* Re-enable RF_KILL if it occurred */
        else if (handled & CSR_INT_BIT_RF_KILL)
@@ -1022,11 +1136,6 @@ out:
  *
  ******************************************************************************/
 
-/* a device (PCI-E) page is 4096 bytes long */
-#define ICT_SHIFT      12
-#define ICT_SIZE       (1 << ICT_SHIFT)
-#define ICT_COUNT      (ICT_SIZE / sizeof(u32))
-
 /* Free dram table */
 void iwl_pcie_free_ict(struct iwl_trans *trans)
 {
@@ -1051,7 +1160,7 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
        trans_pcie->ict_tbl =
-               dma_alloc_coherent(trans->dev, ICT_SIZE,
+               dma_zalloc_coherent(trans->dev, ICT_SIZE,
                                   &trans_pcie->ict_tbl_dma,
                                   GFP_KERNEL);
        if (!trans_pcie->ict_tbl)
@@ -1063,17 +1172,10 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
                return -EINVAL;
        }
 
-       IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n",
-                     (unsigned long long)trans_pcie->ict_tbl_dma);
-
-       IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl);
-
-       /* reset table and index to all 0 */
-       memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
-       trans_pcie->ict_index = 0;
+       IWL_DEBUG_ISR(trans, "ict dma addr %Lx ict vir addr %p\n",
+                     (unsigned long long)trans_pcie->ict_tbl_dma,
+                     trans_pcie->ict_tbl);
 
-       /* add periodic RX interrupt */
-       trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
        return 0;
 }
 
@@ -1084,12 +1186,11 @@ void iwl_pcie_reset_ict(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        u32 val;
-       unsigned long flags;
 
        if (!trans_pcie->ict_tbl)
                return;
 
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
        iwl_disable_interrupts(trans);
 
        memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
@@ -1106,120 +1207,26 @@ void iwl_pcie_reset_ict(struct iwl_trans *trans)
        trans_pcie->ict_index = 0;
        iwl_write32(trans, CSR_INT, trans_pcie->inta_mask);
        iwl_enable_interrupts(trans);
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 }
 
 /* Device is going down disable ict interrupt usage */
 void iwl_pcie_disable_ict(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       unsigned long flags;
 
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
        trans_pcie->use_ict = false;
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 }
 
-/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
-static irqreturn_t iwl_pcie_isr(int irq, void *data)
+irqreturn_t iwl_pcie_isr(int irq, void *data)
 {
        struct iwl_trans *trans = data;
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       u32 inta, inta_mask;
-
-       lockdep_assert_held(&trans_pcie->irq_lock);
-
-       trace_iwlwifi_dev_irq(trans->dev);
-
-       /* Disable (but don't clear!) interrupts here to avoid
-        *    back-to-back ISRs and sporadic interrupts from our NIC.
-        * If we have something to service, the irq thread will re-enable ints.
-        * If we *don't* have something, we'll re-enable before leaving here. */
-       inta_mask = iwl_read32(trans, CSR_INT_MASK);
-       iwl_write32(trans, CSR_INT_MASK, 0x00000000);
-
-       /* Discover which interrupts are active/pending */
-       inta = iwl_read32(trans, CSR_INT);
-
-       if (inta & (~inta_mask)) {
-               IWL_DEBUG_ISR(trans,
-                             "We got a masked interrupt (0x%08x)...Ack and ignore\n",
-                             inta & (~inta_mask));
-               iwl_write32(trans, CSR_INT, inta & (~inta_mask));
-               inta &= inta_mask;
-       }
-
-       /* Ignore interrupt if there's nothing in NIC to service.
-        * This may be due to IRQ shared with another device,
-        * or due to sporadic interrupts thrown from our NIC. */
-       if (!inta) {
-               IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-               /*
-                * Re-enable interrupts here since we don't have anything to
-                * service, but only in case the handler won't run. Note that
-                * the handler can be scheduled because of a previous
-                * interrupt.
-                */
-               if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
-                   !trans_pcie->inta)
-                       iwl_enable_interrupts(trans);
-               return IRQ_NONE;
-       }
-
-       if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-               /* Hardware disappeared. It might have already raised
-                * an interrupt */
-               IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-               return IRQ_HANDLED;
-       }
-
-       if (iwl_have_debug_level(IWL_DL_ISR))
-               IWL_DEBUG_ISR(trans,
-                             "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-                             inta, inta_mask,
-                             iwl_read32(trans, CSR_FH_INT_STATUS));
-
-       trans_pcie->inta |= inta;
-       /* the thread will service interrupts and re-enable them */
-       return IRQ_WAKE_THREAD;
-}
-
-/* interrupt handler using ict table, with this interrupt driver will
- * stop using INTA register to get device's interrupt, reading this register
- * is expensive, device will write interrupts in ICT dram table, increment
- * index then will fire interrupt to driver, driver will OR all ICT table
- * entries from current index up to table entry with 0 value. the result is
- * the interrupt we need to service, driver will set the entries back to 0 and
- * set index.
- */
-irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
-{
-       struct iwl_trans *trans = data;
-       struct iwl_trans_pcie *trans_pcie;
-       u32 inta;
-       u32 val = 0;
-       u32 read;
-       unsigned long flags;
-       irqreturn_t ret = IRQ_NONE;
 
        if (!trans)
                return IRQ_NONE;
 
-       trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-
-       /* dram interrupt table not set yet,
-        * use legacy interrupt.
-        */
-       if (unlikely(!trans_pcie->use_ict)) {
-               ret = iwl_pcie_isr(irq, data);
-               spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-               return ret;
-       }
-
-       trace_iwlwifi_dev_irq(trans->dev);
-
        /* Disable (but don't clear!) interrupts here to avoid
         * back-to-back ISRs and sporadic interrupts from our NIC.
         * If we have something to service, the tasklet will re-enable ints.
@@ -1227,73 +1234,5 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
         */
        iwl_write32(trans, CSR_INT_MASK, 0x00000000);
 
-       /* Ignore interrupt if there's nothing in NIC to service.
-        * This may be due to IRQ shared with another device,
-        * or due to sporadic interrupts thrown from our NIC. */
-       read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
-       trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
-       if (!read) {
-               IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-               goto none;
-       }
-
-       /*
-        * Collect all entries up to the first 0, starting from ict_index;
-        * note we already read at ict_index.
-        */
-       do {
-               val |= read;
-               IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
-                               trans_pcie->ict_index, read);
-               trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
-               trans_pcie->ict_index =
-                       iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
-
-               read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
-               trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
-                                          read);
-       } while (read);
-
-       /* We should not get this value, just ignore it. */
-       if (val == 0xffffffff)
-               val = 0;
-
-       /*
-        * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
-        * (bit 15 before shifting it to 31) to clear when using interrupt
-        * coalescing. fortunately, bits 18 and 19 stay set when this happens
-        * so we use them to decide on the real state of the Rx bit.
-        * In order words, bit 15 is set if bit 18 or bit 19 are set.
-        */
-       if (val & 0xC0000)
-               val |= 0x8000;
-
-       inta = (0xff & val) | ((0xff00 & val) << 16);
-       IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled(sw) 0x%08x ict 0x%08x\n",
-                     inta, trans_pcie->inta_mask, val);
-       if (iwl_have_debug_level(IWL_DL_ISR))
-               IWL_DEBUG_ISR(trans, "enabled(hw) 0x%08x\n",
-                             iwl_read32(trans, CSR_INT_MASK));
-
-       inta &= trans_pcie->inta_mask;
-       trans_pcie->inta |= inta;
-
-       /* iwl_pcie_tasklet() will service interrupts and re-enable them */
-       if (likely(inta)) {
-               spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-               return IRQ_WAKE_THREAD;
-       }
-
-       ret = IRQ_HANDLED;
-
- none:
-       /* re-enable interrupts here since we don't have anything to service.
-        * only Re-enable if disabled by irq.
-        */
-       if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
-           !trans_pcie->inta)
-               iwl_enable_interrupts(trans);
-
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-       return ret;
+       return IRQ_WAKE_THREAD;
 }
index cde9c16f6e4febb26c66c2206068bdba973c708a..16f66c1a23def29b447b5c1dd4827ee7165483c9 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include "iwl-agn-hw.h"
 #include "internal.h"
 
-static void __iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans,
-                                                 u32 reg, u32 mask, u32 value)
-{
-       u32 v;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       WARN_ON_ONCE(value & ~mask);
-#endif
-
-       v = iwl_read32(trans, reg);
-       v &= ~mask;
-       v |= value;
-       iwl_write32(trans, reg, v);
-}
-
-static inline void __iwl_trans_pcie_clear_bit(struct iwl_trans *trans,
-                                             u32 reg, u32 mask)
-{
-       __iwl_trans_pcie_set_bits_mask(trans, reg, mask, 0);
-}
-
-static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
-                                           u32 reg, u32 mask)
-{
-       __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask);
-}
-
 static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
 {
        if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold))
@@ -150,7 +123,6 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
  */
 static int iwl_pcie_apm_init(struct iwl_trans *trans)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        int ret = 0;
        IWL_DEBUG_INFO(trans, "Init card's basic functions\n");
 
@@ -223,7 +195,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
        /* Clear the interrupt in APMG if the NIC is in RFKILL */
        iwl_write_prph(trans, APMG_RTC_INT_STT_REG, APMG_RTC_INT_STT_RFKILL);
 
-       set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
+       set_bit(STATUS_DEVICE_ENABLED, &trans->status);
 
 out:
        return ret;
@@ -249,10 +221,9 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
 
 static void iwl_pcie_apm_stop(struct iwl_trans *trans)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n");
 
-       clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
+       clear_bit(STATUS_DEVICE_ENABLED, &trans->status);
 
        /* Stop device's DMA activity */
        iwl_pcie_apm_stop_master(trans);
@@ -273,13 +244,12 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans)
 static int iwl_pcie_nic_init(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       unsigned long flags;
 
        /* nic_init */
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
        iwl_pcie_apm_init(trans);
 
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 
        iwl_pcie_set_pwr(trans, false);
 
@@ -582,7 +552,6 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
 static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
                                   const struct fw_img *fw, bool run_in_rfkill)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        int ret;
        bool hw_rfkill;
 
@@ -592,16 +561,14 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
                return -EIO;
        }
 
-       clear_bit(STATUS_FW_ERROR, &trans_pcie->status);
-
        iwl_enable_rfkill_int(trans);
 
        /* If platform's RF_KILL switch is NOT set to KILL */
        hw_rfkill = iwl_is_rfkill_set(trans);
        if (hw_rfkill)
-               set_bit(STATUS_RFKILL, &trans_pcie->status);
+               set_bit(STATUS_RFKILL, &trans->status);
        else
-               clear_bit(STATUS_RFKILL, &trans_pcie->status);
+               clear_bit(STATUS_RFKILL, &trans->status);
        iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
        if (hw_rfkill && !run_in_rfkill)
                return -ERFKILL;
@@ -640,12 +607,14 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
 static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       unsigned long flags;
+       bool hw_rfkill, was_hw_rfkill;
+
+       was_hw_rfkill = iwl_is_rfkill_set(trans);
 
        /* tell the device to stop sending interrupts */
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
        iwl_disable_interrupts(trans);
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 
        /* device going down, Stop using ICT table */
        iwl_pcie_disable_ict(trans);
@@ -657,7 +626,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
         * restart. So don't process again if the device is
         * already dead.
         */
-       if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) {
+       if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
                iwl_pcie_tx_stop(trans);
                iwl_pcie_rx_stop(trans);
 
@@ -677,21 +646,45 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
        /* Upon stop, the APM issues an interrupt if HW RF kill is set.
         * Clean again the interrupt here
         */
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
        iwl_disable_interrupts(trans);
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-
-       iwl_enable_rfkill_int(trans);
+       spin_unlock(&trans_pcie->irq_lock);
 
        /* stop and reset the on-board processor */
        iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 
        /* clear all status bits */
-       clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
-       clear_bit(STATUS_INT_ENABLED, &trans_pcie->status);
-       clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
-       clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status);
-       clear_bit(STATUS_RFKILL, &trans_pcie->status);
+       clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
+       clear_bit(STATUS_INT_ENABLED, &trans->status);
+       clear_bit(STATUS_DEVICE_ENABLED, &trans->status);
+       clear_bit(STATUS_TPOWER_PMI, &trans->status);
+       clear_bit(STATUS_RFKILL, &trans->status);
+
+       /*
+        * Even if we stop the HW, we still want the RF kill
+        * interrupt
+        */
+       iwl_enable_rfkill_int(trans);
+
+       /*
+        * Check again since the RF kill state may have changed while
+        * all the interrupts were disabled, in this case we couldn't
+        * receive the RF kill interrupt and update the state in the
+        * op_mode.
+        * Don't call the op_mode if the rkfill state hasn't changed.
+        * This allows the op_mode to call stop_device from the rfkill
+        * notification without endless recursion. Under very rare
+        * circumstances, we might have a small recursion if the rfkill
+        * state changed exactly now while we were called from stop_device.
+        * This is very unlikely but can happen and is supported.
+        */
+       hw_rfkill = iwl_is_rfkill_set(trans);
+       if (hw_rfkill)
+               set_bit(STATUS_RFKILL, &trans->status);
+       else
+               clear_bit(STATUS_RFKILL, &trans->status);
+       if (hw_rfkill != was_hw_rfkill)
+               iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 }
 
 static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test)
@@ -776,7 +769,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
 
 static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        bool hw_rfkill;
        int err;
 
@@ -787,7 +779,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
        }
 
        /* Reset the entire device */
-       iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+       iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
 
        usleep_range(10, 15);
 
@@ -798,53 +790,30 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 
        hw_rfkill = iwl_is_rfkill_set(trans);
        if (hw_rfkill)
-               set_bit(STATUS_RFKILL, &trans_pcie->status);
+               set_bit(STATUS_RFKILL, &trans->status);
        else
-               clear_bit(STATUS_RFKILL, &trans_pcie->status);
+               clear_bit(STATUS_RFKILL, &trans->status);
        iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 
        return 0;
 }
 
-static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
-                                  bool op_mode_leaving)
+static void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       bool hw_rfkill;
-       unsigned long flags;
 
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       /* disable interrupts - don't enable HW RF kill interrupt */
+       spin_lock(&trans_pcie->irq_lock);
        iwl_disable_interrupts(trans);
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 
        iwl_pcie_apm_stop(trans);
 
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
        iwl_disable_interrupts(trans);
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 
        iwl_pcie_disable_ict(trans);
-
-       if (!op_mode_leaving) {
-               /*
-                * Even if we stop the HW, we still want the RF kill
-                * interrupt
-                */
-               iwl_enable_rfkill_int(trans);
-
-               /*
-                * Check again since the RF kill state may have changed while
-                * all the interrupts were disabled, in this case we couldn't
-                * receive the RF kill interrupt and update the state in the
-                * op_mode.
-                */
-               hw_rfkill = iwl_is_rfkill_set(trans);
-               if (hw_rfkill)
-                       set_bit(STATUS_RFKILL, &trans_pcie->status);
-               else
-                       clear_bit(STATUS_RFKILL, &trans_pcie->status);
-               iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
-       }
 }
 
 static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val)
@@ -928,12 +897,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
 
 static void iwl_trans_pcie_set_pmi(struct iwl_trans *trans, bool state)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
        if (state)
-               set_bit(STATUS_TPOWER_PMI, &trans_pcie->status);
+               set_bit(STATUS_TPOWER_PMI, &trans->status);
        else
-               clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status);
+               clear_bit(STATUS_TPOWER_PMI, &trans->status);
 }
 
 static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,
@@ -944,6 +911,9 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,
 
        spin_lock_irqsave(&trans_pcie->reg_lock, *flags);
 
+       if (trans_pcie->cmd_in_flight)
+               goto out;
+
        /* this bit wakes up the NIC */
        __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
                                 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -983,6 +953,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,
                }
        }
 
+out:
        /*
         * Fool sparse by faking we release the lock - sparse will
         * track nic_access anyway.
@@ -1004,6 +975,9 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans,
         */
        __acquire(&trans_pcie->reg_lock);
 
+       if (trans_pcie->cmd_in_flight)
+               goto out;
+
        __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
                                   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
        /*
@@ -1013,6 +987,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans,
         * scheduled on different CPUs (after we drop reg_lock).
         */
        mmiowb();
+out:
        spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags);
 }
 
@@ -1457,7 +1432,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
 
 static const struct iwl_trans_ops trans_ops_pcie = {
        .start_hw = iwl_trans_pcie_start_hw,
-       .stop_hw = iwl_trans_pcie_stop_hw,
+       .op_mode_leave = iwl_trans_pcie_op_mode_leave,
        .fw_alive = iwl_trans_pcie_fw_alive,
        .start_fw = iwl_trans_pcie_start_fw,
        .stop_device = iwl_trans_pcie_stop_device,
@@ -1609,7 +1584,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        if (iwl_pcie_alloc_ict(trans))
                goto out_free_cmd_pool;
 
-       err = request_threaded_irq(pdev->irq, iwl_pcie_isr_ict,
+       err = request_threaded_irq(pdev->irq, iwl_pcie_isr,
                                   iwl_pcie_irq_handler,
                                   IRQF_SHARED, DRV_NAME, trans);
        if (err) {
index a4ef5cc1110010d76439a670242c8d9a22888094..3b14fa8abfc70461d6cd643b71a7997b3234ebe6 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
                IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
                        le32_to_cpu(txq->scratchbufs[i].scratch));
 
-       iwl_nic_error(trans);
+       iwl_trans_fw_error(trans);
 }
 
 /*
@@ -300,10 +300,8 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq)
                iwl_write32(trans, HBUS_TARG_WRPTR,
                            txq->q.write_ptr | (txq_id << 8));
        } else {
-               struct iwl_trans_pcie *trans_pcie =
-                       IWL_TRANS_GET_PCIE_TRANS(trans);
                /* if we're trying to save power */
-               if (test_bit(STATUS_TPOWER_PMI, &trans_pcie->status)) {
+               if (test_bit(STATUS_TPOWER_PMI, &trans->status)) {
                        /* wake up nic if it's powered down ...
                         * uCode will wake up, and interrupt us again, so next
                         * time we'll skip this part. */
@@ -739,10 +737,9 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        int ch, txq_id, ret;
-       unsigned long flags;
 
        /* Turn off all Tx DMA fifos */
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
 
        iwl_pcie_txq_set_sched(trans, 0);
 
@@ -759,13 +756,19 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans)
                                iwl_read_direct32(trans,
                                                  FH_TSSR_TX_STATUS_REG));
        }
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 
-       if (!trans_pcie->txq) {
-               IWL_WARN(trans,
-                        "Stopping tx queues that aren't allocated...\n");
+       /*
+        * This function can be called before the op_mode disabled the
+        * queues. This happens when we have an rfkill interrupt.
+        * Since we stop Tx altogether - mark the queues as stopped.
+        */
+       memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
+       memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
+
+       /* This can happen: start_hw, stop_device */
+       if (!trans_pcie->txq)
                return 0;
-       }
 
        /* Unmap DMA from host system and free skb's */
        for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
@@ -867,7 +870,6 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        int ret;
        int txq_id, slots_num;
-       unsigned long flags;
        bool alloc = false;
 
        if (!trans_pcie->txq) {
@@ -877,7 +879,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
                alloc = true;
        }
 
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       spin_lock(&trans_pcie->irq_lock);
 
        /* Turn off all Tx DMA fifos */
        iwl_write_prph(trans, SCD_TXFACT, 0);
@@ -886,7 +888,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
        iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
                           trans_pcie->kw.dma >> 4);
 
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+       spin_unlock(&trans_pcie->irq_lock);
 
        /* Alloc and init all Tx queues, including the command queue (#4/#9) */
        for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
@@ -1005,6 +1007,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_txq *txq = &trans_pcie->txq[txq_id];
        struct iwl_queue *q = &txq->q;
+       unsigned long flags;
        int nfreed = 0;
 
        lockdep_assert_held(&txq->lock);
@@ -1023,10 +1026,20 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
                if (nfreed++ > 0) {
                        IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
                                idx, q->write_ptr, q->read_ptr);
-                       iwl_nic_error(trans);
+                       iwl_trans_fw_error(trans);
                }
        }
 
+       if (q->read_ptr == q->write_ptr) {
+               spin_lock_irqsave(&trans_pcie->reg_lock, flags);
+               WARN_ON(!trans_pcie->cmd_in_flight);
+               trans_pcie->cmd_in_flight = false;
+               __iwl_trans_pcie_clear_bit(trans,
+                                          CSR_GP_CNTRL,
+                                          CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+               spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
+       }
+
        iwl_pcie_txq_progress(trans_pcie, txq);
 }
 
@@ -1143,8 +1156,15 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
                        SCD_TX_STTS_QUEUE_OFFSET(txq_id);
        static const u32 zero_val[4] = {};
 
+       /*
+        * Upon HW Rfkill - we stop the device, and then stop the queues
+        * in the op_mode. Just for the sake of the simplicity of the op_mode,
+        * allow the op_mode to call txq_disable after it already called
+        * stop_device.
+        */
        if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
-               WARN_ONCE(1, "queue %d not used", txq_id);
+               WARN_ONCE(test_bit(STATUS_DEVICE_ENABLED, &trans->status),
+                         "queue %d not used", txq_id);
                return;
        }
 
@@ -1178,12 +1198,13 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
        struct iwl_queue *q = &txq->q;
        struct iwl_device_cmd *out_cmd;
        struct iwl_cmd_meta *out_meta;
+       unsigned long flags;
        void *dup_buf = NULL;
        dma_addr_t phys_addr;
        int idx;
        u16 copy_size, cmd_size, scratch_size;
        bool had_nocopy = false;
-       int i;
+       int i, ret;
        u32 cmd_pos;
        const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
        u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
@@ -1381,10 +1402,38 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
        if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout)
                mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
 
+       spin_lock_irqsave(&trans_pcie->reg_lock, flags);
+
+       /*
+        * wake up the NIC to make sure that the firmware will see the host
+        * command - we will let the NIC sleep once all the host commands
+        * returned.
+        */
+       if (!trans_pcie->cmd_in_flight) {
+               trans_pcie->cmd_in_flight = true;
+               __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
+                                        CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+               ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
+                                  CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+                                  (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+                                   CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
+                                  15000);
+               if (ret < 0) {
+                       __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
+                                  CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+                       spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
+                       trans_pcie->cmd_in_flight = false;
+                       idx = -EIO;
+                       goto out;
+               }
+       }
+
        /* Increment and update queue's write index */
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
        iwl_pcie_txq_inc_wr_ptr(trans, txq);
 
+       spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
+
  out:
        spin_unlock_bh(&txq->lock);
  free_dup_buf:
@@ -1449,12 +1498,12 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
        iwl_pcie_cmdq_reclaim(trans, txq_id, index);
 
        if (!(meta->flags & CMD_ASYNC)) {
-               if (!test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) {
+               if (!test_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status)) {
                        IWL_WARN(trans,
                                 "HCMD_ACTIVE already clear for command %s\n",
                                 get_cmd_string(trans_pcie, cmd->hdr.cmd));
                }
-               clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
+               clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
                IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
                               get_cmd_string(trans_pcie, cmd->hdr.cmd));
                wake_up(&trans_pcie->wait_command_queue);
@@ -1466,7 +1515,6 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
 }
 
 #define HOST_COMPLETE_TIMEOUT  (2 * HZ)
-#define COMMAND_POKE_TIMEOUT   (HZ / 10)
 
 static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans,
                                    struct iwl_host_cmd *cmd)
@@ -1494,13 +1542,12 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        int cmd_idx;
        int ret;
-       int timeout = HOST_COMPLETE_TIMEOUT;
 
        IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
                       get_cmd_string(trans_pcie, cmd->id));
 
-       if (WARN(test_and_set_bit(STATUS_HCMD_ACTIVE,
-                                 &trans_pcie->status),
+       if (WARN(test_and_set_bit(STATUS_SYNC_HCMD_ACTIVE,
+                                 &trans->status),
                 "Command %s: a command is already active!\n",
                 get_cmd_string(trans_pcie, cmd->id)))
                return -EIO;
@@ -1511,36 +1558,17 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
        cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd);
        if (cmd_idx < 0) {
                ret = cmd_idx;
-               clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
+               clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
                IWL_ERR(trans,
                        "Error sending %s: enqueue_hcmd failed: %d\n",
                        get_cmd_string(trans_pcie, cmd->id), ret);
                return ret;
        }
 
-       while (timeout > 0) {
-               unsigned long flags;
-
-               timeout -= COMMAND_POKE_TIMEOUT;
-               ret = wait_event_timeout(trans_pcie->wait_command_queue,
-                                        !test_bit(STATUS_HCMD_ACTIVE,
-                                                  &trans_pcie->status),
-                                        COMMAND_POKE_TIMEOUT);
-               if (ret)
-                       break;
-               /* poke the device - it may have lost the command */
-               if (iwl_trans_grab_nic_access(trans, true, &flags)) {
-                       iwl_trans_release_nic_access(trans, &flags);
-                       IWL_DEBUG_INFO(trans,
-                                      "Tried to wake NIC for command %s\n",
-                                      get_cmd_string(trans_pcie, cmd->id));
-               } else {
-                       IWL_ERR(trans, "Failed to poke NIC for command %s\n",
-                               get_cmd_string(trans_pcie, cmd->id));
-                       break;
-               }
-       }
-
+       ret = wait_event_timeout(trans_pcie->wait_command_queue,
+                                !test_bit(STATUS_SYNC_HCMD_ACTIVE,
+                                          &trans->status),
+                                HOST_COMPLETE_TIMEOUT);
        if (!ret) {
                struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
                struct iwl_queue *q = &txq->q;
@@ -1552,17 +1580,17 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
                IWL_ERR(trans, "Current CMD queue read_ptr %d write_ptr %d\n",
                        q->read_ptr, q->write_ptr);
 
-               clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
+               clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
                IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
                               get_cmd_string(trans_pcie, cmd->id));
                ret = -ETIMEDOUT;
 
-               iwl_nic_error(trans);
+               iwl_trans_fw_error(trans);
 
                goto cancel;
        }
 
-       if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) {
+       if (test_bit(STATUS_FW_ERROR, &trans->status)) {
                IWL_ERR(trans, "FW error in SYNC CMD %s\n",
                        get_cmd_string(trans_pcie, cmd->id));
                dump_stack();
@@ -1571,7 +1599,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
        }
 
        if (!(cmd->flags & CMD_SEND_IN_RFKILL) &&
-           test_bit(STATUS_RFKILL, &trans_pcie->status)) {
+           test_bit(STATUS_RFKILL, &trans->status)) {
                IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n");
                ret = -ERFKILL;
                goto cancel;
@@ -1608,13 +1636,8 @@ cancel:
 
 int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       if (test_bit(STATUS_FW_ERROR, &trans_pcie->status))
-               return -EIO;
-
        if (!(cmd->flags & CMD_SEND_IN_RFKILL) &&
-           test_bit(STATUS_RFKILL, &trans_pcie->status)) {
+           test_bit(STATUS_RFKILL, &trans->status)) {
                IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n",
                                  cmd->id);
                return -ERFKILL;
index 0b803c05cab3dae49be31b61b6cddb7e60674955..6261f8c53d44bd7a6ba4f30651bfc8c67da6f4e5 100644 (file)
@@ -483,7 +483,7 @@ mwifiex_get_ba_tbl(struct mwifiex_private *priv, int tid, u8 *ra)
 
        spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
        list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
-               if (!memcmp(tx_ba_tsr_tbl->ra, ra, ETH_ALEN) &&
+               if (ether_addr_equal_unaligned(tx_ba_tsr_tbl->ra, ra) &&
                    tx_ba_tsr_tbl->tid == tid) {
                        spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
                                               flags);
index 4d23647faef0451ef227804dbe1464bbd2442161..e7c81abf108eda9f438b810687bbdefcc60adcd0 100644 (file)
@@ -538,23 +538,33 @@ static void mwifiex_reg_notifier(struct wiphy *wiphy,
                                 struct regulatory_request *request)
 {
        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+       struct mwifiex_private *priv = mwifiex_get_priv(adapter,
+                                                       MWIFIEX_BSS_ROLE_ANY);
 
        wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n",
                  request->alpha2[0], request->alpha2[1]);
 
-       memcpy(adapter->country_code, request->alpha2, sizeof(request->alpha2));
-
        switch (request->initiator) {
        case NL80211_REGDOM_SET_BY_DRIVER:
        case NL80211_REGDOM_SET_BY_CORE:
        case NL80211_REGDOM_SET_BY_USER:
-               break;
-               /* Todo: apply driver specific changes in channel flags based
-                  on the request initiator if necessary. */
        case NL80211_REGDOM_SET_BY_COUNTRY_IE:
                break;
+       default:
+               wiphy_err(wiphy, "unknown regdom initiator: %d\n",
+                         request->initiator);
+               return;
+       }
+
+       /* Don't send world or same regdom info to firmware */
+       if (strncmp(request->alpha2, "00", 2) &&
+           strncmp(request->alpha2, adapter->country_code,
+                   sizeof(request->alpha2))) {
+               memcpy(adapter->country_code, request->alpha2,
+                      sizeof(request->alpha2));
+               mwifiex_send_domain_info_cmd_fw(wiphy);
+               mwifiex_dnld_txpwr_table(priv);
        }
-       mwifiex_send_domain_info_cmd_fw(wiphy);
 }
 
 /*
@@ -1171,10 +1181,10 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
        else
                bitmap_rates[1] = mask->control[band].legacy;
 
-       /* Fill MCS rates */
-       bitmap_rates[2] = mask->control[band].mcs[0];
+       /* Fill HT MCS rates */
+       bitmap_rates[2] = mask->control[band].ht_mcs[0];
        if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2)
-               bitmap_rates[2] |= mask->control[band].mcs[1] << 8;
+               bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;
 
        return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG,
                                     HostCmd_ACT_GEN_SET, 0, bitmap_rates);
index 8fcb500fa09b37c7e253906350141972998c5c9e..4cee6ceb7e9e9c10c0ca15773033df1f1156e18d 100644 (file)
@@ -468,8 +468,6 @@ enum P2P_MODES {
 #define MWIFIEX_CRITERIA_UNICAST       BIT(1)
 #define MWIFIEX_CRITERIA_MULTICAST     BIT(3)
 
-#define CFG_DATA_TYPE_CAL              2
-
 struct mwifiex_ie_types_header {
        __le16 type;
        __le16 len;
@@ -1592,12 +1590,6 @@ struct mwifiex_ie_list {
        struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX];
 } __packed;
 
-struct host_cmd_ds_802_11_cfg_data {
-       __le16 action;
-       __le16 type;
-       __le16 data_len;
-} __packed;
-
 struct coalesce_filt_field_param {
        u8 operation;
        u8 operand_len;
@@ -1678,7 +1670,6 @@ struct host_cmd_ds_command {
                struct host_cmd_ds_sys_config uap_sys_config;
                struct host_cmd_ds_sta_deauth sta_deauth;
                struct host_cmd_11ac_vht_cfg vht_cfg;
-               struct host_cmd_ds_802_11_cfg_data cfg_data;
                struct host_cmd_ds_coalesce_cfg coalesce_cfg;
        } params;
 } __packed;
index 6bf58aba51d20ca59253efb55ada327888615e5d..2d6f5e1721cfc5428823896a20f9963e9d843ce0 100644 (file)
@@ -749,7 +749,7 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
 static u16
 mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb)
 {
-       skb->priority = cfg80211_classify8021d(skb);
+       skb->priority = cfg80211_classify8021d(skb, NULL);
        return mwifiex_1d_to_wmm_queue[skb->priority];
 }
 
index dc34457557f38452de46f47276d6194d4ff766e1..d8ad554ce39f566cbf95221317fca751482d7e5c 100644 (file)
@@ -32,6 +32,7 @@
 #include <net/lib80211.h>
 #include <linux/firmware.h>
 #include <linux/ctype.h>
+#include <linux/of.h>
 
 #include "decl.h"
 #include "ioctl.h"
@@ -739,6 +740,7 @@ struct mwifiex_adapter {
        u8 scan_delay_cnt;
        u8 empty_tx_q_cnt;
        const struct firmware *cal_data;
+       struct device_node *dt_node;
 
        /* 11AC */
        u32 is_hw_11ac_capable;
@@ -1151,6 +1153,9 @@ void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
 void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer,
                              struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv);
+int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv,
+                           struct device_node *node, const char *prefix);
+void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv);
 
 extern const struct ethtool_ops mwifiex_ethtool_ops;
 
index 1efa43ec1c6ec3921d143752b3fb7ab3d6511902..9208a8816b800f619426eb41403d4177ad2d0ad3 100644 (file)
@@ -1156,30 +1156,62 @@ static u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst)
        return d - dst;
 }
 
+int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv,
+                           struct device_node *node, const char *prefix)
+{
+#ifdef CONFIG_OF
+       struct property *prop;
+       size_t len = strlen(prefix);
+       int ret;
+
+       /* look for all matching property names */
+       for_each_property_of_node(node, prop) {
+               if (len > strlen(prop->name) ||
+                   strncmp(prop->name, prefix, len))
+                       continue;
+
+               /* property header is 6 bytes, data must fit in cmd buffer */
+               if (prop && prop->value && prop->length > 6 &&
+                   prop->length <= MWIFIEX_SIZE_OF_CMD_BUFFER - S_DS_GEN) {
+                       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA,
+                                                   HostCmd_ACT_GEN_SET, 0,
+                                                   prop);
+                       if (ret)
+                               return ret;
+               }
+       }
+#endif
+       return 0;
+}
+
 /* This function prepares command of set_cfg_data. */
 static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd,
-                               u16 cmd_action)
+                               struct host_cmd_ds_command *cmd, void *data_buf)
 {
-       struct host_cmd_ds_802_11_cfg_data *cfg_data = &cmd->params.cfg_data;
        struct mwifiex_adapter *adapter = priv->adapter;
-       u32 len, cal_data_offset;
-       u8 *tmp_cmd = (u8 *)cmd;
+       struct property *prop = data_buf;
+       u32 len;
+       u8 *data = (u8 *)cmd + S_DS_GEN;
+       int ret;
 
-       cal_data_offset = S_DS_GEN + sizeof(*cfg_data);
-       if ((adapter->cal_data->data) && (adapter->cal_data->size > 0))
+       if (prop) {
+               len = prop->length;
+               ret = of_property_read_u8_array(adapter->dt_node, prop->name,
+                                               data, len);
+               if (ret)
+                       return ret;
+               dev_dbg(adapter->dev,
+                       "download cfg_data from device tree: %s\n", prop->name);
+       } else if (adapter->cal_data->data && adapter->cal_data->size > 0) {
                len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data,
-                                           adapter->cal_data->size,
-                                           (u8 *)(tmp_cmd + cal_data_offset));
-       else
+                                           adapter->cal_data->size, data);
+               dev_dbg(adapter->dev, "download cfg_data from config file\n");
+       } else {
                return -1;
-
-       cfg_data->action = cpu_to_le16(cmd_action);
-       cfg_data->type = cpu_to_le16(CFG_DATA_TYPE_CAL);
-       cfg_data->data_len = cpu_to_le16(len);
+       }
 
        cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA);
-       cmd->size = cpu_to_le16(S_DS_GEN + sizeof(*cfg_data) + len);
+       cmd->size = cpu_to_le16(S_DS_GEN + len);
 
        return 0;
 }
@@ -1267,7 +1299,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr);
                break;
        case HostCmd_CMD_CFG_DATA:
-               ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, cmd_action);
+               ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, data_buf);
                break;
        case HostCmd_CMD_MAC_CONTROL:
                ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action,
@@ -1527,7 +1559,19 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
                if (ret)
                        return -1;
 
-               /* Download calibration data to firmware */
+               /* Download calibration data to firmware.
+                * The cal-data can be read from device tree and/or
+                * a configuration file and downloaded to firmware.
+                */
+               adapter->dt_node =
+                               of_find_node_by_name(NULL, "marvell_cfgdata");
+               if (adapter->dt_node) {
+                       ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
+                                                     "marvell,caldata");
+                       if (ret)
+                               return -1;
+               }
+
                if (adapter->cal_data) {
                        ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA,
                                                HostCmd_ACT_GEN_SET, 0, NULL);
index 551194605aa7ae1862c2df113b33a8701c8d5243..24523e4015cba11a9fe02ee449ad462f557e1642 100644 (file)
@@ -782,8 +782,7 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
        }
 
        /* If BSSID is diff, modify current BSS parameters */
-       if (memcmp(priv->curr_bss_params.bss_descriptor.mac_address,
-                  ibss_coal_resp->bssid, ETH_ALEN)) {
+       if (!ether_addr_equal(priv->curr_bss_params.bss_descriptor.mac_address, ibss_coal_resp->bssid)) {
                /* BSSID */
                memcpy(priv->curr_bss_params.bss_descriptor.mac_address,
                       ibss_coal_resp->bssid, ETH_ALEN);
index a09398fe9e2a67218f50530af8a0b4616443cbbb..c5cb2ed19ec2e240d6a65a7bb9ee4165ad181b68 100644 (file)
@@ -184,6 +184,16 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
        return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc);
 }
 
+void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv)
+{
+       if (priv->adapter->dt_node) {
+               char txpwr[] = {"marvell,00_txpwrlimit"};
+
+               memcpy(&txpwr[8], priv->adapter->country_code, 2);
+               mwifiex_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr);
+       }
+}
+
 static int mwifiex_process_country_ie(struct mwifiex_private *priv,
                                      struct cfg80211_bss *bss)
 {
@@ -205,6 +215,14 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
                return 0;
        }
 
+       if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) {
+               rcu_read_unlock();
+               wiphy_dbg(priv->wdev->wiphy,
+                         "11D: skip setting domain info in FW\n");
+               return 0;
+       }
+       memcpy(priv->adapter->country_code, &country_ie[2], 2);
+
        domain_info->country_code[0] = country_ie[2];
        domain_info->country_code[1] = country_ie[3];
        domain_info->country_code[2] = ' ';
@@ -226,6 +244,8 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
                return -1;
        }
 
+       mwifiex_dnld_txpwr_table(priv);
+
        return 0;
 }
 
index 0bb510de80710a1348c1743ca95fbe107ef223e7..4651d676df380c16f9ec8577a1f97e4ab72a4b8c 100644 (file)
@@ -224,7 +224,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
         * directly to os. Don't pass thru rx reordering
         */
        if (!IS_11N_ENABLED(priv) ||
-           memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) {
+           !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) {
                mwifiex_process_rx_packet(priv, skb);
                return ret;
        }
index b953ad621e0b90ef23e9fbe009bc0c4cd5f66876..63dbde5c3713304e538890ba1aa90fef5caec400 100644 (file)
@@ -9,7 +9,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -1258,7 +1257,7 @@ mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh)
 {
        return priv->capture_beacon &&
                ieee80211_is_beacon(wh->frame_control) &&
-               ether_addr_equal(wh->addr3, priv->capture_bssid);
+               ether_addr_equal_64bits(wh->addr3, priv->capture_bssid);
 }
 
 static inline void mwl8k_save_beacon(struct ieee80211_hw *hw,
index 75c15bc7b34cabf7b59ed87f2c41af5f54242fbc..43790fbea0e00ab6c7d292ee71d9209e9cf36ba5 100644 (file)
@@ -40,7 +40,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 
 #include "hermes.h"
index d21d95939316ece9557d579226bdc2ef66896b50..c0a27377d9e26306ea7dc32b44efc6749723bcda 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
index bdfe637953f4d3a41270abafa9e174d04901879c..f9805c9353d2295f076d1f5cbe1eaaa5a1f0be72 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/poll.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/spinlock.h>
index e2264bc12ebf30cf5119d997c70356dc2af1446c..b60048c95e0a852863f3e2f541bc283fd263f9ab 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
index d43e3740e45d95e4b55bc3af085747dcf346c04b..0fe67d2da20895373c6bcf1cad50356184494224 100644 (file)
@@ -16,7 +16,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/firmware.h>
 #include <linux/etherdevice.h>
 #include <linux/sort.h>
index b3879fbf53688bcea74ba9b639d5b6c8ddab860d..bc065e8e348b264fad86bffa8450c31a96d0274e 100644 (file)
@@ -16,7 +16,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/firmware.h>
 #include <linux/etherdevice.h>
index 3837e1eec5f4a56fdbf80a2b8f13984f3d15742b..1f6fd5ff55313731b034b565c358ac56b21bfaf7 100644 (file)
@@ -16,7 +16,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/firmware.h>
 #include <linux/etherdevice.h>
 
index 067e6f2fd050fcad0ddc4eb00565ba3324397894..80d93cba51502edc28806202af6c48f8c42485ff 100644 (file)
@@ -16,7 +16,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/firmware.h>
 #include <linux/etherdevice.h>
index f9a07b0d83acd2f40df4755880fa1551e6276091..d411de4090509df56f9e51a7b268296d979dc59e 100644 (file)
@@ -13,7 +13,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/firmware.h>
index e328d3058c419a0c7c4c367fd7e62ada31ddded4..6e635cfa24c8dea70eb439f3724ee52adc01d27d 100644 (file)
@@ -12,7 +12,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/usb.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
index f95de0d162166e1de1e9035d1d3be9db238869fe..9c96831c0b5c8ded956451ebd7d41a4f22fd92a5 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <linux/export.h>
-#include <linux/init.h>
 #include <linux/firmware.h>
 #include <linux/etherdevice.h>
 #include <asm/div64.h>
@@ -308,7 +307,7 @@ static void p54_pspoll_workaround(struct p54_common *priv, struct sk_buff *skb)
                return;
 
        /* only consider beacons from the associated BSSID */
-       if (!ether_addr_equal(hdr->addr3, priv->bssid))
+       if (!ether_addr_equal_64bits(hdr->addr3, priv->bssid))
                return;
 
        tim = p54_find_ie(skb, WLAN_EID_TIM);
index df784fefb8e3e322ca0fc5dd73c127051a08524a..78fa64d3f2232a85a15a8b88f698765f80c9dfc8 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/if_arp.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
+#include <linux/etherdevice.h>
 
 #include <asm/uaccess.h>
 
@@ -1860,7 +1861,7 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
        if (mutex_lock_interruptible(&acl->lock))
                return -ERESTARTSYS;
        list_for_each_entry(entry, &acl->mac_list, _list) {
-               if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
+               if (ether_addr_equal(entry->addr, addr->sa_data)) {
                        list_del(&entry->_list);
                        acl->size--;
                        kfree(entry);
index c3cdda1252defba9d9c27d25e0fdeca72bedf76e..5028557aa18adb1a22c74c7a59123f1bb52b0d5a 100644 (file)
@@ -26,7 +26,6 @@
 // #define     VERBOSE                 // more; success messages
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
index 4ad0de9d1d08b4a54bb8b87643be4e7c84ad6511..4ccfef5094e0b2ecec3c2633df2a22ac7d5747a5 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
index 4f61ffbcd2f196a2b9fbe0354ab87b8e86f336e2..abc5f56f29fe1c96c3dc585af30f662c138c1cd7 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
index 1bb76935da717c6fb15a46e9399407a2955b2531..9f16824cd1bccf80407633fa0864d1d7f0d6d257 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 49ff178a0b46eac88cd78156bb7263f4843991d2..5c5c4906c6b669517d043209685f476dd40cee02 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/usb.h>
index 00c3fae6fa3c1cfe2a7574a372e868432b073a85..2bde6729f5e61e4923c472bade9da057e850b0e0 100644 (file)
@@ -565,10 +565,10 @@ static void rt2x00lib_rxdone_check_ba(struct rt2x00_dev *rt2x00dev,
 
 #undef TID_CHECK
 
-               if (!ether_addr_equal(ba->ra, entry->ta))
+               if (!ether_addr_equal_64bits(ba->ra, entry->ta))
                        continue;
 
-               if (!ether_addr_equal(ba->ta, entry->ra))
+               if (!ether_addr_equal_64bits(ba->ta, entry->ra))
                        continue;
 
                /* Mark BAR since we received the according BA */
index b76f6049ad9a9f099e8293f23a403a8e79a0c69a..24402984ee5749f272609d82907cda4a68f750f6 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/crc-itu-t.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index ade88d7e089cc485fc0f0a9fafb9ac0000cbf217..a140170b1eb3e63625ecde7b4cc43ec6bf1b87b1 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/crc-itu-t.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index a91506b12a627f26a084aef5e6dcb9a4213ac5e4..8ec17aad0e520019fa0f93fbd50f1999885ea9ad 100644 (file)
@@ -15,7 +15,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
index dc845693f321ee39dbe1728aada582cccb609165..b1bfee73893703f89cc00720566e4a4fa631fdf0 100644 (file)
@@ -19,7 +19,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <net/mac80211.h>
index a63c443c3c6fbc9cbf16dca89e20f34ac56d22ba..eebf23976524a3a8da9f51575f4d233e18235698 100644 (file)
@@ -18,7 +18,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <net/mac80211.h>
index ee638d0749d601ac593a17fd1304753ad2203a2f..d60a5f399022447c81130e7edc9e60d45d59a3c0 100644 (file)
@@ -15,7 +15,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <net/mac80211.h>
index 7614d9ccc72931edf0e41557c7882fd555ded246..959b049827de1e44df543940d68026f670cb787a 100644 (file)
@@ -19,7 +19,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <net/mac80211.h>
index ec9aa5b6738171f547dc50a45b977795de133486..fd78df813a8533911ffaeb7c08d53c0a440810f1 100644 (file)
@@ -20,7 +20,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/usb.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
index a26193a0444790286c625c3fae39d773698fb1b0..5ecf18ed67b88abc8627f2fd2dabfa06d8a7db13 100644 (file)
@@ -16,7 +16,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/usb.h>
 #include <net/mac80211.h>
 
index fcf9b621918c07ba2ab42e38622af9b56ac66682..d63a12cc5de8e6af64b3b9fef9650b42bbfcd6e5 100644 (file)
@@ -1293,7 +1293,7 @@ void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb)
                return;
 
        /* and only beacons from the associated BSSID, please */
-       if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
+       if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid))
                return;
 
        rtlpriv->link_info.bcn_rx_inperiod++;
@@ -1781,7 +1781,7 @@ void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len)
                return;
 
        /* and only beacons from the associated BSSID, please */
-       if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
+       if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid))
                return;
 
        if (rtl_find_221_ie(hw, data, len))
index 0e510f73041ab88659b131c2a392598046e127fe..0276153c72cc2b8f65a8eed5cfeb638b793012f9 100644 (file)
@@ -295,7 +295,7 @@ u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr)
        /* Does STA already exist? */
        for (i = 4; i < TOTAL_CAM_ENTRY; i++) {
                addr = rtlpriv->sec.hwsec_cam_sta_addr[i];
-               if (memcmp(addr, sta_addr, ETH_ALEN) == 0)
+               if (ether_addr_equal_unaligned(addr, sta_addr))
                        return i;
        }
        /* Get a free CAM entry. */
@@ -335,7 +335,7 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
                addr = rtlpriv->sec.hwsec_cam_sta_addr[i];
                bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i;
                if (((bitmap & BIT(0)) == BIT(0)) &&
-                   (memcmp(addr, sta_addr, ETH_ALEN) == 0)) {
+                   (ether_addr_equal_unaligned(addr, sta_addr))) {
                        /* Remove from HW Security CAM */
                        eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]);
                        rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
index 8707d1a94995c740d11a5b6cd3dd5d4849616f53..d7aa165fe6776cb64e178f3ec6db0eeb7e9c255c 100644 (file)
@@ -738,6 +738,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
        };
        int index = rtlpci->rx_ring[rx_queue_idx].idx;
 
+       if (rtlpci->driver_is_goingto_unload)
+               return;
        /*RX NORMAL PKT */
        while (count--) {
                /*rx descriptor */
@@ -1634,6 +1636,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
         */
        set_hal_stop(rtlhal);
 
+       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->disable_interrupt(hw);
        cancel_work_sync(&rtlpriv->works.lps_change_work);
 
@@ -1651,7 +1654,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
        ppsc->rfchange_inprogress = true;
        spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);
 
-       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->hw_disable(hw);
        /* some things are not needed if firmware not available */
        if (!rtlpriv->max_fw_size)
index 0d81f766fd0f9e27b6b60478ceae71d9629bfa9a..deedae3c54498370462ef4bc1bde40d7749ee0c8 100644 (file)
@@ -478,7 +478,7 @@ void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
                return;
 
        /* and only beacons from the associated BSSID, please */
-       if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
+       if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid))
                return;
 
        rtlpriv->psc.last_beacon = jiffies;
@@ -923,7 +923,7 @@ void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len)
                return;
 
        /* and only beacons from the associated BSSID, please */
-       if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
+       if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid))
                return;
 
        /* check if this really is a beacon */
index 374268d5ac6a70e97355269489538ad31d802cbb..5a4ec56c83d0aa15e7e00226a6cfe69c9146696b 100644 (file)
@@ -194,7 +194,7 @@ out:
        return ret;
 }
 
-int wl1251_acx_feature_cfg(struct wl1251 *wl)
+int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options)
 {
        struct acx_feature_config *feature;
        int ret;
@@ -205,8 +205,8 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl)
        if (!feature)
                return -ENOMEM;
 
-       /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
-       feature->data_flow_options = 0;
+       /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE can be set */
+       feature->data_flow_options = data_flow_options;
        feature->options = 0;
 
        ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
@@ -381,7 +381,8 @@ out:
        return ret;
 }
 
-int wl1251_acx_group_address_tbl(struct wl1251 *wl)
+int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
+                                void *mc_list, u32 mc_list_len)
 {
        struct acx_dot11_grp_addr_tbl *acx;
        int ret;
@@ -393,9 +394,9 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl)
                return -ENOMEM;
 
        /* MAC filtering */
-       acx->enabled = 0;
-       acx->num_groups = 0;
-       memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
+       acx->enabled = enable;
+       acx->num_groups = mc_list_len;
+       memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
 
        ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
                                   acx, sizeof(*acx));
@@ -846,12 +847,18 @@ int wl1251_acx_rate_policies(struct wl1251 *wl)
                return -ENOMEM;
 
        /* configure one default (one-size-fits-all) rate class */
-       acx->rate_class_cnt = 1;
+       acx->rate_class_cnt = 2;
        acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
        acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
        acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
        acx->rate_class[0].aflags = 0;
 
+       /* no-retry rate class */
+       acx->rate_class[1].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
+       acx->rate_class[1].short_retry_limit = 0;
+       acx->rate_class[1].long_retry_limit = 0;
+       acx->rate_class[1].aflags = 0;
+
        ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
        if (ret < 0) {
                wl1251_warning("Setting of rate policies failed: %d", ret);
@@ -960,6 +967,32 @@ out:
        return ret;
 }
 
+int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address)
+{
+       struct wl1251_acx_arp_filter *acx;
+       int ret;
+
+       wl1251_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
+
+       acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+       if (!acx)
+               return -ENOMEM;
+
+       acx->version = ACX_IPV4_VERSION;
+       acx->enable = enable;
+
+       if (enable)
+               memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);
+
+       ret = wl1251_cmd_configure(wl, ACX_ARP_IP_FILTER,
+                                  acx, sizeof(*acx));
+       if (ret < 0)
+               wl1251_warning("failed to set arp ip filter: %d", ret);
+
+       kfree(acx);
+       return ret;
+}
+
 int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
                      u8 aifs, u16 txop)
 {
index c2ba100f9b1ab3e659301f88328a4274beaf2047..2bdec38699f4f1a833e311020e0187a827c2ebcb 100644 (file)
@@ -350,8 +350,8 @@ struct acx_slot {
 } __packed;
 
 
-#define ADDRESS_GROUP_MAX      (8)
-#define ADDRESS_GROUP_MAX_LEN  (ETH_ALEN * ADDRESS_GROUP_MAX)
+#define ACX_MC_ADDRESS_GROUP_MAX       (8)
+#define ACX_MC_ADDRESS_GROUP_MAX_LEN   (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX)
 
 struct acx_dot11_grp_addr_tbl {
        struct acx_header header;
@@ -359,7 +359,7 @@ struct acx_dot11_grp_addr_tbl {
        u8 enabled;
        u8 num_groups;
        u8 pad[2];
-       u8 mac_table[ADDRESS_GROUP_MAX_LEN];
+       u8 mac_table[ACX_MC_ADDRESS_GROUP_MAX_LEN];
 } __packed;
 
 
@@ -1232,6 +1232,20 @@ struct wl1251_acx_bet_enable {
        u8 padding[2];
 } __packed;
 
+#define ACX_IPV4_VERSION 4
+#define ACX_IPV6_VERSION 6
+#define ACX_IPV4_ADDR_SIZE 4
+struct wl1251_acx_arp_filter {
+       struct acx_header header;
+       u8 version;     /* The IP version: 4 - IPv4, 6 - IPv6.*/
+       u8 enable;      /* 1 - ARP filtering is enabled, 0 - disabled */
+       u8 padding[2];
+       u8 address[16]; /* The IP address used to filter ARP packets.
+                          ARP packets that do not match this address are
+                          dropped. When the IP Version is 4, the last 12
+                          bytes of the the address are ignored. */
+} __attribute__((packed));
+
 struct wl1251_acx_ac_cfg {
        struct acx_header header;
 
@@ -1440,7 +1454,7 @@ int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
 int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth);
 int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len);
 int wl1251_acx_tx_power(struct wl1251 *wl, int power);
-int wl1251_acx_feature_cfg(struct wl1251 *wl);
+int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options);
 int wl1251_acx_mem_map(struct wl1251 *wl,
                       struct acx_header *mem_map, size_t len);
 int wl1251_acx_data_path_params(struct wl1251 *wl,
@@ -1449,7 +1463,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time);
 int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter);
 int wl1251_acx_pd_threshold(struct wl1251 *wl);
 int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
-int wl1251_acx_group_address_tbl(struct wl1251 *wl);
+int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
+                                void *mc_list, u32 mc_list_len);
 int wl1251_acx_service_period_timeout(struct wl1251 *wl);
 int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
 int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
@@ -1473,6 +1488,7 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl);
 int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim);
 int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
                          u8 max_consecutive);
+int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address);
 int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
                      u8 aifs, u16 txop);
 int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
index a2e5241382da3ddab3fd71920863a9cca12ea4d3..2000cd5360776470bc33a4ec76fa940ec79500e4 100644 (file)
@@ -299,7 +299,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
                ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
                ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
                REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
-               BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID;
+               BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID |
+               PS_REPORT_EVENT_ID;
 
        ret = wl1251_event_unmask(wl);
        if (ret < 0) {
index 6822b845efc15d5e2305bf468cf76c6bd83e1dce..223649bcaa5a6764cff615bd9f1716b16810cc00 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/crc7.h>
+#include <linux/etherdevice.h>
 
 #include "wl1251.h"
 #include "reg.h"
@@ -203,11 +204,11 @@ out:
        return ret;
 }
 
-int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
+int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable)
 {
        struct cmd_enabledisable_path *cmd;
        int ret;
-       u16 cmd_rx, cmd_tx;
+       u16 cmd_rx;
 
        wl1251_debug(DEBUG_CMD, "cmd data path");
 
@@ -219,13 +220,10 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
 
        cmd->channel = channel;
 
-       if (enable) {
+       if (enable)
                cmd_rx = CMD_ENABLE_RX;
-               cmd_tx = CMD_ENABLE_TX;
-       } else {
+       else
                cmd_rx = CMD_DISABLE_RX;
-               cmd_tx = CMD_DISABLE_TX;
-       }
 
        ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
        if (ret < 0) {
@@ -237,17 +235,38 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
        wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
                     enable ? "start" : "stop", channel);
 
+out:
+       kfree(cmd);
+       return ret;
+}
+
+int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable)
+{
+       struct cmd_enabledisable_path *cmd;
+       int ret;
+       u16 cmd_tx;
+
+       wl1251_debug(DEBUG_CMD, "cmd data path");
+
+       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       cmd->channel = channel;
+
+       if (enable)
+               cmd_tx = CMD_ENABLE_TX;
+       else
+               cmd_tx = CMD_DISABLE_TX;
+
        ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
-       if (ret < 0) {
+       if (ret < 0)
                wl1251_error("tx %s cmd for channel %d failed",
                             enable ? "start" : "stop", channel);
-               goto out;
-       }
-
-       wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
-                    enable ? "start" : "stop", channel);
+       else
+               wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
+                            enable ? "start" : "stop", channel);
 
-out:
        kfree(cmd);
        return ret;
 }
@@ -410,7 +429,9 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
        struct wl1251_cmd_scan *cmd;
        int i, ret = 0;
 
-       wl1251_debug(DEBUG_CMD, "cmd scan");
+       wl1251_debug(DEBUG_CMD, "cmd scan channels %d", n_channels);
+
+       WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS);
 
        cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
        if (!cmd)
@@ -421,6 +442,13 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
                                                    CFG_RX_MGMT_EN |
                                                    CFG_RX_BCN_EN);
        cmd->params.scan_options = 0;
+       /*
+        * Use high priority scan when not associated to prevent fw issue
+        * causing never-ending scans (sometimes 20+ minutes).
+        * Note: This bug may be caused by the fw's DTIM handling.
+        */
+       if (is_zero_ether_addr(wl->bssid))
+               cmd->params.scan_options |= WL1251_SCAN_OPT_PRIORITY_HIGH;
        cmd->params.num_channels = n_channels;
        cmd->params.num_probe_requests = n_probes;
        cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
index ee4f2b391822ac7b58da04e5c6fa6e52daef0813..d824ff9783116ac3db04d18a3736312b3d565f35 100644 (file)
@@ -35,7 +35,8 @@ int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len);
 int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len);
 int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
                   void *bitmap, u16 bitmap_len, u8 bitmap_control);
-int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable);
+int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable);
+int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable);
 int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
                    u16 beacon_interval, u8 dtim_interval);
 int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode);
@@ -167,6 +168,11 @@ struct cmd_read_write_memory {
 #define CMDMBOX_HEADER_LEN 4
 #define CMDMBOX_INFO_ELEM_HEADER_LEN 4
 
+#define WL1251_SCAN_OPT_PASSIVE                1
+#define WL1251_SCAN_OPT_5GHZ_BAND      2
+#define WL1251_SCAN_OPT_TRIGGERD_SCAN  4
+#define WL1251_SCAN_OPT_PRIORITY_HIGH  8
+
 #define WL1251_SCAN_MIN_DURATION 30000
 #define WL1251_SCAN_MAX_DURATION 60000
 
index 74ae8e1c2e334a3f61071209a2e9b6fd952014d4..db0105313745f08a02c9d408564c5d8029aa05ca 100644 (file)
@@ -46,6 +46,43 @@ static int wl1251_event_scan_complete(struct wl1251 *wl,
        return ret;
 }
 
+#define WL1251_PSM_ENTRY_RETRIES  3
+static int wl1251_event_ps_report(struct wl1251 *wl,
+                                 struct event_mailbox *mbox)
+{
+       int ret = 0;
+
+       wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status);
+
+       switch (mbox->ps_status) {
+       case EVENT_ENTER_POWER_SAVE_FAIL:
+               wl1251_debug(DEBUG_PSM, "PSM entry failed");
+
+               if (wl->station_mode != STATION_POWER_SAVE_MODE) {
+                       /* remain in active mode */
+                       wl->psm_entry_retry = 0;
+                       break;
+               }
+
+               if (wl->psm_entry_retry < WL1251_PSM_ENTRY_RETRIES) {
+                       wl->psm_entry_retry++;
+                       ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+               } else {
+                       wl1251_error("Power save entry failed, giving up");
+                       wl->psm_entry_retry = 0;
+               }
+               break;
+       case EVENT_ENTER_POWER_SAVE_SUCCESS:
+       case EVENT_EXIT_POWER_SAVE_FAIL:
+       case EVENT_EXIT_POWER_SAVE_SUCCESS:
+       default:
+               wl->psm_entry_retry = 0;
+               break;
+       }
+
+       return 0;
+}
+
 static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
 {
        wl1251_debug(DEBUG_EVENT, "MBOX DUMP:");
@@ -80,7 +117,14 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
                }
        }
 
-       if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
+       if (vector & PS_REPORT_EVENT_ID) {
+               wl1251_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
+               ret = wl1251_event_ps_report(wl, mbox);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (wl->vif && vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
                wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
 
                /* indicate to the stack, that beacons have been lost */
index 30eb5d150bf75d8ca8a653a4adc27f59f186d0a7..88570a5cd04210af6a890e0e39808fbc94e55e76 100644 (file)
@@ -112,6 +112,13 @@ struct event_mailbox {
        u8 padding[19];
 } __packed;
 
+enum {
+       EVENT_ENTER_POWER_SAVE_FAIL = 0,
+       EVENT_ENTER_POWER_SAVE_SUCCESS,
+       EVENT_EXIT_POWER_SAVE_FAIL,
+       EVENT_EXIT_POWER_SAVE_SUCCESS,
+};
+
 int wl1251_event_unmask(struct wl1251 *wl);
 void wl1251_event_mbox_config(struct wl1251 *wl);
 int wl1251_event_handle(struct wl1251 *wl, u8 mbox);
index 89b43d35473c662a6f5763c992dbb1f35e8f18c0..1d799bffaa9f35ab772057beae1ba067d8b406df 100644 (file)
@@ -33,7 +33,7 @@ int wl1251_hw_init_hwenc_config(struct wl1251 *wl)
 {
        int ret;
 
-       ret = wl1251_acx_feature_cfg(wl);
+       ret = wl1251_acx_feature_cfg(wl, 0);
        if (ret < 0) {
                wl1251_warning("couldn't set feature config");
                return ret;
@@ -127,7 +127,7 @@ int wl1251_hw_init_phy_config(struct wl1251 *wl)
        if (ret < 0)
                return ret;
 
-       ret = wl1251_acx_group_address_tbl(wl);
+       ret = wl1251_acx_group_address_tbl(wl, true, NULL, 0);
        if (ret < 0)
                return ret;
 
@@ -394,8 +394,13 @@ int wl1251_hw_init(struct wl1251 *wl)
        if (ret < 0)
                goto out_free_data_path;
 
-       /* Enable data path */
-       ret = wl1251_cmd_data_path(wl, wl->channel, 1);
+       /* Enable rx data path */
+       ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
+       if (ret < 0)
+               goto out_free_data_path;
+
+       /* Enable tx data path */
+       ret = wl1251_cmd_data_path_tx(wl, wl->channel, 1);
        if (ret < 0)
                goto out_free_data_path;
 
index 3291ffa952736ac9f6ac2784c758db39b498d37c..119c148f7740365a52833af33979a85350fabf14 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/netdevice.h>
 
 #include "wl1251.h"
 #include "wl12xx_80211.h"
@@ -479,10 +480,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
        wl->next_tx_complete = 0;
        wl->elp = false;
        wl->station_mode = STATION_ACTIVE_MODE;
+       wl->psm_entry_retry = 0;
        wl->tx_queue_stopped = false;
        wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
        wl->rssi_thold = 0;
        wl->channel = WL1251_DEFAULT_CHANNEL;
+       wl->monitor_present = false;
+       wl->joined = false;
 
        wl1251_debugfs_reset(wl);
 
@@ -521,7 +525,7 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
-       if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) {
+       if (!ether_addr_equal_unaligned(wl->mac_addr, vif->addr)) {
                memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
                SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
                ret = wl1251_acx_station_id(wl);
@@ -542,6 +546,7 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
        mutex_lock(&wl->mutex);
        wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface");
        wl->vif = NULL;
+       memset(wl->bssid, 0, ETH_ALEN);
        mutex_unlock(&wl->mutex);
 }
 
@@ -566,6 +571,11 @@ static int wl1251_build_qos_null_data(struct wl1251 *wl)
                                       sizeof(template));
 }
 
+static bool wl1251_can_do_pm(struct ieee80211_conf *conf, struct wl1251 *wl)
+{
+       return (conf->flags & IEEE80211_CONF_PS) && !wl->monitor_present;
+}
+
 static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
 {
        struct wl1251 *wl = hw->priv;
@@ -575,8 +585,10 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
        channel = ieee80211_frequency_to_channel(
                        conf->chandef.chan->center_freq);
 
-       wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
+       wl1251_debug(DEBUG_MAC80211,
+                    "mac80211 config ch %d monitor %s psm %s power %d",
                     channel,
+                    conf->flags & IEEE80211_CONF_MONITOR ? "on" : "off",
                     conf->flags & IEEE80211_CONF_PS ? "on" : "off",
                     conf->power_level);
 
@@ -586,16 +598,44 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
        if (ret < 0)
                goto out;
 
+       if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+               u32 mode;
+
+               if (conf->flags & IEEE80211_CONF_MONITOR) {
+                       wl->monitor_present = true;
+                       mode = DF_SNIFF_MODE_ENABLE | DF_ENCRYPTION_DISABLE;
+               } else {
+                       wl->monitor_present = false;
+                       mode = 0;
+               }
+
+               ret = wl1251_acx_feature_cfg(wl, mode);
+               if (ret < 0)
+                       goto out_sleep;
+       }
+
        if (channel != wl->channel) {
                wl->channel = channel;
 
-               ret = wl1251_join(wl, wl->bss_type, wl->channel,
-                                 wl->beacon_int, wl->dtim_period);
+               /*
+                * Use ENABLE_RX command for channel switching when no
+                * interface is present (monitor mode only).
+                * This leaves the tx path disabled in firmware, whereas
+                * the usual JOIN command seems to transmit some frames
+                * at firmware level.
+                */
+               if (wl->vif == NULL) {
+                       wl->joined = false;
+                       ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
+               } else {
+                       ret = wl1251_join(wl, wl->bss_type, wl->channel,
+                                         wl->beacon_int, wl->dtim_period);
+               }
                if (ret < 0)
                        goto out_sleep;
        }
 
-       if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
+       if (wl1251_can_do_pm(conf, wl) && !wl->psm_requested) {
                wl1251_debug(DEBUG_PSM, "psm enabled");
 
                wl->psm_requested = true;
@@ -611,8 +651,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
                ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
                if (ret < 0)
                        goto out_sleep;
-       } else if (!(conf->flags & IEEE80211_CONF_PS) &&
-                  wl->psm_requested) {
+       } else if (!wl1251_can_do_pm(conf, wl) && wl->psm_requested) {
                wl1251_debug(DEBUG_PSM, "psm disabled");
 
                wl->psm_requested = false;
@@ -648,6 +687,16 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
                wl->power_level = conf->power_level;
        }
 
+       /*
+        * Tell stack that connection is lost because hw encryption isn't
+        * supported in monitor mode.
+        * This requires temporary enabling of the hw connection monitor flag
+        */
+       if ((changed & IEEE80211_CONF_CHANGE_MONITOR) && wl->vif) {
+               wl->hw->flags |= IEEE80211_HW_CONNECTION_MONITOR;
+               ieee80211_connection_loss(wl->vif);
+       }
+
 out_sleep:
        wl1251_ps_elp_sleep(wl);
 
@@ -657,6 +706,44 @@ out:
        return ret;
 }
 
+struct wl1251_filter_params {
+       bool enabled;
+       int mc_list_length;
+       u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
+};
+
+static u64 wl1251_op_prepare_multicast(struct ieee80211_hw *hw,
+                                      struct netdev_hw_addr_list *mc_list)
+{
+       struct wl1251_filter_params *fp;
+       struct netdev_hw_addr *ha;
+       struct wl1251 *wl = hw->priv;
+
+       if (unlikely(wl->state == WL1251_STATE_OFF))
+               return 0;
+
+       fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
+       if (!fp) {
+               wl1251_error("Out of memory setting filters.");
+               return 0;
+       }
+
+       /* update multicast filtering parameters */
+       fp->mc_list_length = 0;
+       if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) {
+               fp->enabled = false;
+       } else {
+               fp->enabled = true;
+               netdev_hw_addr_list_for_each(ha, mc_list) {
+                       memcpy(fp->mc_list[fp->mc_list_length],
+                                       ha->addr, ETH_ALEN);
+                       fp->mc_list_length++;
+               }
+       }
+
+       return (u64)(unsigned long)fp;
+}
+
 #define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
                                  FIF_ALLMULTI | \
                                  FIF_FCSFAIL | \
@@ -667,8 +754,9 @@ out:
 
 static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
                                       unsigned int changed,
-                                      unsigned int *total,u64 multicast)
+                                      unsigned int *total, u64 multicast)
 {
+       struct wl1251_filter_params *fp = (void *)(unsigned long)multicast;
        struct wl1251 *wl = hw->priv;
        int ret;
 
@@ -677,9 +765,11 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
        *total &= WL1251_SUPPORTED_FILTERS;
        changed &= WL1251_SUPPORTED_FILTERS;
 
-       if (changed == 0)
+       if (changed == 0) {
                /* no filters which we support changed */
+               kfree(fp);
                return;
+       }
 
        mutex_lock(&wl->mutex);
 
@@ -716,6 +806,15 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
        if (ret < 0)
                goto out;
 
+       if (*total & FIF_ALLMULTI || *total & FIF_PROMISC_IN_BSS)
+               ret = wl1251_acx_group_address_tbl(wl, false, NULL, 0);
+       else if (fp)
+               ret = wl1251_acx_group_address_tbl(wl, fp->enabled,
+                                                  fp->mc_list,
+                                                  fp->mc_list_length);
+       if (ret < 0)
+               goto out;
+
        /* send filters to firmware */
        wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
 
@@ -723,6 +822,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
 
 out:
        mutex_unlock(&wl->mutex);
+       kfree(fp);
 }
 
 /* HW encryption */
@@ -802,12 +902,12 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        mutex_lock(&wl->mutex);
 
-       ret = wl1251_ps_elp_wakeup(wl);
-       if (ret < 0)
-               goto out_unlock;
-
        switch (cmd) {
        case SET_KEY:
+               if (wl->monitor_present) {
+                       ret = -EOPNOTSUPP;
+                       goto out_unlock;
+               }
                wl_cmd->key_action = KEY_ADD_OR_REPLACE;
                break;
        case DISABLE_KEY:
@@ -818,6 +918,10 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                break;
        }
 
+       ret = wl1251_ps_elp_wakeup(wl);
+       if (ret < 0)
+               goto out_unlock;
+
        ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr);
        if (ret < 0) {
                wl1251_error("Set KEY type failed");
@@ -930,6 +1034,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
        ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels,
                              req->n_channels, WL1251_SCAN_NUM_PROBES);
        if (ret < 0) {
+               wl1251_debug(DEBUG_SCAN, "scan failed %d", ret);
                wl->scanning = false;
                goto out_idle;
        }
@@ -977,6 +1082,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
 {
        struct wl1251 *wl = hw->priv;
        struct sk_buff *beacon, *skb;
+       bool enable;
        int ret;
 
        wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed");
@@ -1023,6 +1129,9 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        if (changed & BSS_CHANGED_ASSOC) {
+               /* Disable temporary enabled hw connection monitor flag */
+               wl->hw->flags &= ~IEEE80211_HW_CONNECTION_MONITOR;
+
                if (bss_conf->assoc) {
                        wl->beacon_int = bss_conf->beacon_int;
 
@@ -1075,6 +1184,17 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
                }
        }
 
+       if (changed & BSS_CHANGED_ARP_FILTER) {
+               __be32 addr = bss_conf->arp_addr_list[0];
+               WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
+
+               enable = bss_conf->arp_addr_cnt == 1 && bss_conf->assoc;
+               wl1251_acx_arp_ip_filter(wl, enable, addr);
+
+               if (ret < 0)
+                       goto out_sleep;
+       }
+
        if (changed & BSS_CHANGED_BEACON) {
                beacon = ieee80211_beacon_get(hw, vif);
                if (!beacon)
@@ -1245,6 +1365,7 @@ static const struct ieee80211_ops wl1251_ops = {
        .add_interface = wl1251_op_add_interface,
        .remove_interface = wl1251_op_remove_interface,
        .config = wl1251_op_config,
+       .prepare_multicast = wl1251_op_prepare_multicast,
        .configure_filter = wl1251_op_configure_filter,
        .tx = wl1251_op_tx,
        .set_key = wl1251_op_set_key,
@@ -1401,7 +1522,10 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
 
        INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
        wl->channel = WL1251_DEFAULT_CHANNEL;
+       wl->monitor_present = false;
+       wl->joined = false;
        wl->scanning = false;
+       wl->bss_type = MAX_BSS_TYPE;
        wl->default_key = 0;
        wl->listen_int = 1;
        wl->rx_counter = 0;
@@ -1413,6 +1537,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
        wl->elp = false;
        wl->station_mode = STATION_ACTIVE_MODE;
        wl->psm_requested = false;
+       wl->psm_entry_retry = 0;
        wl->tx_queue_stopped = false;
        wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
        wl->rssi_thold = 0;
@@ -1478,3 +1603,4 @@ MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
 MODULE_FIRMWARE(WL1251_FW_NAME);
+MODULE_FIRMWARE(WL1251_NVS_NAME);
index 23289d49dd31806210566fe2aa737154eecf482e..123c4bb50e0a0c2eff220c4509c2ece5aab7b365 100644 (file)
@@ -83,7 +83,7 @@ static void wl1251_rx_status(struct wl1251 *wl,
 
        status->flag |= RX_FLAG_MACTIME_START;
 
-       if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
+       if (!wl->monitor_present && (desc->flags & RX_DESC_ENCRYPTION_MASK)) {
                status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
 
                if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL)))
index 28121c590a2b1a62effa4c17b335b83264c99acf..81de83c6fcf625108b9cdb5dcd7145f1a741d143 100644 (file)
@@ -28,6 +28,7 @@
 #include "tx.h"
 #include "ps.h"
 #include "io.h"
+#include "event.h"
 
 static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
 {
@@ -89,8 +90,12 @@ static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr,
        /* 802.11 packets */
        tx_hdr->control.packet_type = 0;
 
-       if (control->flags & IEEE80211_TX_CTL_NO_ACK)
+       /* Also disable retry and ACK policy for injected packets */
+       if ((control->flags & IEEE80211_TX_CTL_NO_ACK) ||
+           (control->flags & IEEE80211_TX_CTL_INJECTED)) {
+               tx_hdr->control.rate_policy = 1;
                tx_hdr->control.ack_policy = 1;
+       }
 
        tx_hdr->control.tx_complete = 1;
 
@@ -277,6 +282,26 @@ static void wl1251_tx_trigger(struct wl1251 *wl)
                TX_STATUS_DATA_OUT_COUNT_MASK;
 }
 
+static void enable_tx_for_packet_injection(struct wl1251 *wl)
+{
+       int ret;
+
+       ret = wl1251_cmd_join(wl, BSS_TYPE_STA_BSS, wl->channel,
+                             wl->beacon_int, wl->dtim_period);
+       if (ret < 0) {
+               wl1251_warning("join failed");
+               return;
+       }
+
+       ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID, 100);
+       if (ret < 0) {
+               wl1251_warning("join timeout");
+               return;
+       }
+
+       wl->joined = true;
+}
+
 /* caller must hold wl->mutex */
 static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
 {
@@ -287,6 +312,9 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
        info = IEEE80211_SKB_CB(skb);
 
        if (info->control.hw_key) {
+               if (unlikely(wl->monitor_present))
+                       return -EINVAL;
+
                idx = info->control.hw_key->hw_key_idx;
                if (unlikely(wl->default_key != idx)) {
                        ret = wl1251_acx_default_key(wl, idx);
@@ -295,6 +323,10 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
                }
        }
 
+       /* Enable tx path in monitor mode for packet injection */
+       if ((wl->vif == NULL) && !wl->joined)
+               enable_tx_for_packet_injection(wl);
+
        ret = wl1251_tx_path_status(wl);
        if (ret < 0)
                return ret;
@@ -394,6 +426,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
        info = IEEE80211_SKB_CB(skb);
 
        if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+           !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
            (result->status == TX_SUCCESS))
                info->flags |= IEEE80211_TX_STAT_ACK;
 
index 2c3bd1bff3f68e08de48b42101c52606a472fa6a..235617a7716d59ff4a699427540c1ecb4a612178 100644 (file)
@@ -93,6 +93,7 @@ enum {
        } while (0)
 
 #define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN |  \
+                                 CFG_MC_FILTER_EN |    \
                                  CFG_BSSID_FILTER_EN)
 
 #define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN |  \
@@ -303,6 +304,8 @@ struct wl1251 {
        u8 bss_type;
        u8 listen_int;
        int channel;
+       bool monitor_present;
+       bool joined;
 
        void *target_mem_map;
        struct acx_data_path_params_resp *data_path;
@@ -368,6 +371,9 @@ struct wl1251 {
        /* PSM mode requested */
        bool psm_requested;
 
+       /* retry counter for PSM entries */
+       u8 psm_entry_retry;
+
        u16 beacon_int;
        u8 dtim_period;
 
index 38d2089f338a3277d8ff77126f3dd166524f84b8..d24d4a958c6731a44fe10d9c83ee32567c3fe7ed 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <linux/delay.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
@@ -44,6 +43,7 @@
 #include <linux/string.h>
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
+#include <linux/etherdevice.h>
 
 #include <net/iw_handler.h>
 
@@ -673,8 +673,7 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr)
                                matchflag = 1;
                        if (matchflag) {
                                for (i = 0; i < this->bss_cnt; i++) {
-                                       if (!memcmp(this->bss_set[i].bssid,
-                                                   sig.bssid, ETH_ALEN)) {
+                                       if (ether_addr_equal_unaligned(this->bss_set[i].bssid, sig.bssid)) {
                                                matchflag = 0;
                                                break;
                                        }
index eff79a37bc2aa2faa5ae35891dd84de560ee8da3..e7af261e91980a571ac537455942c2803fe96ab5 100644 (file)
@@ -532,9 +532,8 @@ void zd_mac_tx_failed(struct urb *urb)
                tx_hdr = (struct ieee80211_hdr *)skb->data;
 
                /* we skip all frames not matching the reported destination */
-               if (unlikely(memcmp(tx_hdr->addr1, tx_status->mac, ETH_ALEN))) {
+               if (unlikely(!ether_addr_equal(tx_hdr->addr1, tx_status->mac)))
                        continue;
-               }
 
                /* we skip all frames not matching the reported final rate */
 
@@ -997,7 +996,7 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
                    continue;
 
                tx_hdr = (struct ieee80211_hdr *)skb->data;
-               if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN)))
+               if (likely(ether_addr_equal(tx_hdr->addr2, rx_hdr->addr1)))
                {
                        found = 1;
                        break;
index ba30a6d9fefabf225631b731a1ce0fc73ea7653d..4c76bcb9a879d23ad98aae968d529450606db6f8 100644 (file)
@@ -101,6 +101,13 @@ struct xenvif_rx_meta {
 
 #define MAX_PENDING_REQS 256
 
+/* It's possible for an skb to have a maximal number of frags
+ * but still be less than MAX_BUFFER_OFFSET in size. Thus the
+ * worst-case number of copy operations is MAX_SKB_FRAGS per
+ * ring slot.
+ */
+#define MAX_GRANT_COPY_OPS (MAX_SKB_FRAGS * XEN_NETIF_RX_RING_SIZE)
+
 struct xenvif {
        /* Unique identifier for this interface. */
        domid_t          domid;
@@ -136,18 +143,19 @@ struct xenvif {
        char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */
        struct xen_netif_rx_back_ring rx;
        struct sk_buff_head rx_queue;
+       bool rx_queue_stopped;
        /* Set when the RX interrupt is triggered by the frontend.
         * The worker thread may need to wake the queue.
         */
        bool rx_event;
 
-       /* Given MAX_BUFFER_OFFSET of 4096 the worst case is that each
-        * head/fragment page uses 2 copy operations because it
-        * straddles two buffers in the frontend.
-        */
-       struct gnttab_copy grant_copy_op[2*XEN_NETIF_RX_RING_SIZE];
-       struct xenvif_rx_meta meta[2*XEN_NETIF_RX_RING_SIZE];
+       /* This array is allocated seperately as it is large */
+       struct gnttab_copy *grant_copy_op;
 
+       /* We create one meta structure per ring request we consume, so
+        * the maximum number is the same as the ring size.
+        */
+       struct xenvif_rx_meta meta[XEN_NETIF_RX_RING_SIZE];
 
        u8               fe_dev_addr[6];
 
index 1dcb9606e6e08f0ab1ac059d51d24b8833415a49..b9de31ea7fc48ac333f30dfa17041fdef893895a 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
+#include <linux/vmalloc.h>
 
 #include <xen/events.h>
 #include <asm/xen/hypercall.h>
@@ -307,6 +308,15 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
        SET_NETDEV_DEV(dev, parent);
 
        vif = netdev_priv(dev);
+
+       vif->grant_copy_op = vmalloc(sizeof(struct gnttab_copy) *
+                                    MAX_GRANT_COPY_OPS);
+       if (vif->grant_copy_op == NULL) {
+               pr_warn("Could not allocate grant copy space for %s\n", name);
+               free_netdev(dev);
+               return ERR_PTR(-ENOMEM);
+       }
+
        vif->domid  = domid;
        vif->handle = handle;
        vif->can_sg = 1;
@@ -488,6 +498,7 @@ void xenvif_free(struct xenvif *vif)
 
        unregister_netdev(vif->dev);
 
+       vfree(vif->grant_copy_op);
        free_netdev(vif->dev);
 
        module_put(THIS_MODULE);
index 611aebee4583679f4377658b65691a4e8fd0e29e..27385639b6e5609cf7b30625adaa0e4c31733cd8 100644 (file)
@@ -476,7 +476,8 @@ static void xenvif_rx_action(struct xenvif *vif)
        int ret;
        unsigned long offset;
        struct skb_cb_overlay *sco;
-       int need_to_notify = 0;
+       bool need_to_notify = false;
+       bool ring_full = false;
 
        struct netrx_pending_operations npo = {
                .copy  = vif->grant_copy_op,
@@ -508,7 +509,8 @@ static void xenvif_rx_action(struct xenvif *vif)
                /* If the skb may not fit then bail out now */
                if (!xenvif_rx_ring_slots_available(vif, max_slots_needed)) {
                        skb_queue_head(&vif->rx_queue, skb);
-                       need_to_notify = 1;
+                       need_to_notify = true;
+                       ring_full = true;
                        break;
                }
 
@@ -521,10 +523,12 @@ static void xenvif_rx_action(struct xenvif *vif)
 
        BUG_ON(npo.meta_prod > ARRAY_SIZE(vif->meta));
 
+       vif->rx_queue_stopped = !npo.copy_prod && ring_full;
+
        if (!npo.copy_prod)
                goto done;
 
-       BUG_ON(npo.copy_prod > ARRAY_SIZE(vif->grant_copy_op));
+       BUG_ON(npo.copy_prod > MAX_GRANT_COPY_OPS);
        gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod);
 
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
@@ -592,8 +596,7 @@ static void xenvif_rx_action(struct xenvif *vif)
 
                RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->rx, ret);
 
-               if (ret)
-                       need_to_notify = 1;
+               need_to_notify |= !!ret;
 
                npo.meta_cons += sco->meta_slots_used;
                dev_kfree_skb(skb);
@@ -1108,8 +1111,10 @@ static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        tcp_hdr(skb)->check =
@@ -1126,8 +1131,10 @@ static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        udp_hdr(skb)->check =
@@ -1249,8 +1256,10 @@ static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        tcp_hdr(skb)->check =
@@ -1267,8 +1276,10 @@ static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        udp_hdr(skb)->check =
@@ -1716,7 +1727,8 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
 
 static inline int rx_work_todo(struct xenvif *vif)
 {
-       return !skb_queue_empty(&vif->rx_queue) || vif->rx_event;
+       return (!skb_queue_empty(&vif->rx_queue) && !vif->rx_queue_stopped) ||
+               vif->rx_event;
 }
 
 static inline int tx_work_todo(struct xenvif *vif)
index de6f8990246fefc8aaef7c0e88e0371143ae9859..c6973f101a3e4ae9e00c604cd9e1708d1bd88485 100644 (file)
@@ -20,7 +20,7 @@ config OF_SELFTEST
        depends on OF_IRQ
        help
          This option builds in test cases for the device tree infrastructure
-         that are executed one at boot time, and the results dumped to the
+         that are executed once at boot time, and the results dumped to the
          console.
 
          If unsure, say N here, but this option is safe to enable.
index 4b9317bdb81ce85209573e6c28f86492e643962b..d3dd41c840f1cd8d6784e4a61382cb3e4987ad1a 100644 (file)
@@ -69,14 +69,6 @@ static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
                 (unsigned long long)cp, (unsigned long long)s,
                 (unsigned long long)da);
 
-       /*
-        * If the number of address cells is larger than 2 we assume the
-        * mapping doesn't specify a physical address. Rather, the address
-        * specifies an identifier that must match exactly.
-        */
-       if (na > 2 && memcmp(range, addr, na * 4) != 0)
-               return OF_BAD_ADDR;
-
        if (da < cp || da >= (cp + s))
                return OF_BAD_ADDR;
        return da - cp;
index 2fa024b97c4350c680e384c645dc17d0fc5dc177..758b4f8b30b7d237c92b6a541f01db535d37101b 100644 (file)
@@ -922,8 +922,16 @@ void __init unflatten_device_tree(void)
  */
 void __init unflatten_and_copy_device_tree(void)
 {
-       int size = __be32_to_cpu(initial_boot_params->totalsize);
-       void *dt = early_init_dt_alloc_memory_arch(size,
+       int size;
+       void *dt;
+
+       if (!initial_boot_params) {
+               pr_warn("No valid device tree found, continuing without\n");
+               return;
+       }
+
+       size = __be32_to_cpu(initial_boot_params->totalsize);
+       dt = early_init_dt_alloc_memory_arch(size,
                __alignof__(struct boot_param_header));
 
        if (dt) {
index 786b0b47fae46802503ecbecee5719887830c44c..27212402c53247819cf4edf09e576d2cc69f3136 100644 (file)
@@ -165,7 +165,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                if (of_get_property(ipar, "interrupt-controller", NULL) !=
                                NULL) {
                        pr_debug(" -> got it !\n");
-                       of_node_put(old);
                        return 0;
                }
 
@@ -250,8 +249,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                 * Successfully parsed an interrrupt-map translation; copy new
                 * interrupt specifier into the out_irq structure
                 */
-               of_node_put(out_irq->np);
-               out_irq->np = of_node_get(newpar);
+               out_irq->np = newpar;
 
                match_array = imap - newaddrsize - newintsize;
                for (i = 0; i < newintsize; i++)
@@ -268,7 +266,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
        }
  fail:
        of_node_put(ipar);
-       of_node_put(out_irq->np);
        of_node_put(newpar);
 
        return -EINVAL;
index a43b8523c61e13fbff9af821a92131390304fc49..875b7b6f0d2a48bfdac42f40d6927cf59e6cf552 100644 (file)
@@ -254,3 +254,23 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
        return IS_ERR(phy) ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_connect_fixed_link);
+
+/**
+ * of_phy_attach - Attach to a PHY without starting the state machine
+ * @dev: pointer to net_device claiming the phy
+ * @phy_np: Node pointer for the PHY
+ * @flags: flags to pass to the PHY
+ * @iface: PHY data interface type
+ */
+struct phy_device *of_phy_attach(struct net_device *dev,
+                                struct device_node *phy_np, u32 flags,
+                                phy_interface_t iface)
+{
+       struct phy_device *phy = of_phy_find_device(phy_np);
+
+       if (!phy)
+               return NULL;
+
+       return phy_attach_direct(dev, phy, flags, iface) ? NULL : phy;
+}
+EXPORT_SYMBOL(of_phy_attach);
index 8f9be2e099376981d7a4c39b87dbcc7de715a7ca..a208a457558c758a47ac7c0a2c43ca6e6426c85c 100644 (file)
@@ -30,6 +30,7 @@ static const char *phy_modes[] = {
        [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
        [PHY_INTERFACE_MODE_RTBI]       = "rtbi",
        [PHY_INTERFACE_MODE_SMII]       = "smii",
+       [PHY_INTERFACE_MODE_XGMII]      = "xgmii",
 };
 
 /**
index a344f3d52361f0eed4d2a0d1fdc81a957e3a7967..330ef2d065670eb91b84a6d553bdf1df2dabf79f 100644 (file)
@@ -24,8 +24,8 @@ config PHY_EXYNOS_MIPI_VIDEO
 config OMAP_USB2
        tristate "OMAP USB2 PHY Driver"
        depends on ARCH_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        select OMAP_CONTROL_USB
        help
          Enable this to support the transceiver that is part of SOC. This
@@ -36,8 +36,8 @@ config OMAP_USB2
 config TWL4030_USB
        tristate "TWL4030 USB Transceiver Driver"
        depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        help
          Enable this to support the USB OTG transceiver on TWL4030
          family chips (including the TWL5030 and TPS659x0 devices).
index 03cf8fb815543537fb14995fde36a5216706dab9..58e0e97390287364287eae1eecdf8b43ba7b72f1 100644 (file)
@@ -437,23 +437,18 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
        int id;
        struct phy *phy;
 
-       if (!dev) {
-               dev_WARN(dev, "no device provided for PHY\n");
-               ret = -EINVAL;
-               goto err0;
-       }
+       if (WARN_ON(!dev))
+               return ERR_PTR(-EINVAL);
 
        phy = kzalloc(sizeof(*phy), GFP_KERNEL);
-       if (!phy) {
-               ret = -ENOMEM;
-               goto err0;
-       }
+       if (!phy)
+               return ERR_PTR(-ENOMEM);
 
        id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL);
        if (id < 0) {
                dev_err(dev, "unable to get id\n");
                ret = id;
-               goto err0;
+               goto free_phy;
        }
 
        device_initialize(&phy->dev);
@@ -468,11 +463,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        ret = device_add(&phy->dev);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        if (pm_runtime_enabled(dev)) {
                pm_runtime_enable(&phy->dev);
@@ -481,12 +476,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        return phy;
 
-err1:
-       ida_remove(&phy_ida, phy->id);
+put_dev:
        put_device(&phy->dev);
+       ida_remove(&phy_ida, phy->id);
+free_phy:
        kfree(phy);
-
-err0:
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(phy_create);
index 2832576d8b12ee7c99e24896c3fe333dd8cffadc..114f5ef4b73abdbcd02e524a1a34f84aeeb5b7cb 100644 (file)
@@ -512,6 +512,7 @@ static const struct dev_pm_ops byt_gpio_pm_ops = {
 
 static const struct acpi_device_id byt_gpio_acpi_match[] = {
        { "INT33B2", 0 },
+       { "INT33FC", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
index 2a786c504460f5be0246c363fab622223ebd990e..3c6768378a94600bc487c61bc9d3fffcbf581750 100644 (file)
@@ -833,6 +833,11 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
        return 0;
 }
 
+static const struct x86_cpu_id energy_unit_quirk_ids[] = {
+       { X86_VENDOR_INTEL, 6, 0x37},/* VLV */
+       {}
+};
+
 static int rapl_check_unit(struct rapl_package *rp, int cpu)
 {
        u64 msr_val;
@@ -853,8 +858,11 @@ static int rapl_check_unit(struct rapl_package *rp, int cpu)
         * time unit: 1/time_unit_divisor Seconds
         */
        value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
-       rp->energy_unit_divisor = 1 << value;
-
+       /* some CPUs have different way to calculate energy unit */
+       if (x86_match_cpu(energy_unit_quirk_ids))
+               rp->energy_unit_divisor = 1000000 / (1 << value);
+       else
+               rp->energy_unit_divisor = 1 << value;
 
        value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
        rp->power_unit_divisor = 1 << value;
@@ -941,6 +949,7 @@ static void package_power_limit_irq_restore(int package_id)
 static const struct x86_cpu_id rapl_ids[] = {
        { X86_VENDOR_INTEL, 6, 0x2a},/* SNB */
        { X86_VENDOR_INTEL, 6, 0x2d},/* SNB EP */
+       { X86_VENDOR_INTEL, 6, 0x37},/* VLV */
        { X86_VENDOR_INTEL, 6, 0x3a},/* IVB */
        { X86_VENDOR_INTEL, 6, 0x45},/* HSW */
        /* TODO: Add more CPU IDs after testing */
index 596480022b0a4b88eb7a3d855e472200d5ab4fef..38a1257e76e1ec432c6cc81893b54a27ee30081a 100644 (file)
@@ -471,7 +471,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
                schedule_delayed_work(&tgt->sess_del_work, 0);
        else
                schedule_delayed_work(&tgt->sess_del_work,
-                   jiffies - sess->expires);
+                   sess->expires - jiffies);
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -550,13 +550,14 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
        struct scsi_qla_host *vha = tgt->vha;
        struct qla_hw_data *ha = vha->hw;
        struct qla_tgt_sess *sess;
-       unsigned long flags;
+       unsigned long flags, elapsed;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
        while (!list_empty(&tgt->del_sess_list)) {
                sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
                    del_list_entry);
-               if (time_after_eq(jiffies, sess->expires)) {
+               elapsed = jiffies;
+               if (time_after_eq(elapsed, sess->expires)) {
                        qlt_undelete_sess(sess);
 
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
@@ -566,7 +567,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
                        ha->tgt.tgt_ops->put_sess(sess);
                } else {
                        schedule_delayed_work(&tgt->sess_del_work,
-                           jiffies - sess->expires);
+                           sess->expires - elapsed);
                        break;
                }
        }
@@ -4290,6 +4291,7 @@ int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn,
                if (rc != 0) {
                        ha->tgt.tgt_ops = NULL;
                        ha->tgt.target_lport_ptr = NULL;
+                       scsi_host_put(host);
                }
                mutex_unlock(&qla_tgt_mutex);
                return rc;
index 50328de712fa6bb199fad05303bc28b05d46c6ed..937fc31971a785061e9273f849ed515360252063 100644 (file)
@@ -37,7 +37,7 @@ static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = {
        { "M25P32", 0x15, 0x10000, 64, },
        { "M25P64", 0x16, 0x10000, 128, },
        { "M25FL128", 0x17, 0x10000, 256, },
-       { 0 },
+       { NULL },
 };
 
 static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = {
@@ -55,7 +55,7 @@ static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = {
        { "SST25VF016", 0x41, 0x1000, 512, },
        { "SST25VF032", 0x4a, 0x1000, 1024, },
        { "SST25VF064", 0x4b, 0x1000, 2048, },
-       { 0 },
+       { NULL },
 };
 
 static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = {
@@ -66,7 +66,7 @@ static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = {
        { "AT45DB161", 0x2c, 512, 4096, },
        { "AT45DB321", 0x34, 512, 8192, },
        { "AT45DB642", 0x3c, 1024, 8192, },
-       { 0 },
+       { NULL },
 };
 
 static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode)
index 8f02bf66e20b2002b3b52655919a89f95c0fcad9..4964d2a2fc7d54ba099541b3f9c2c61be4799936 100644 (file)
@@ -446,7 +446,7 @@ int comedi_load_firmware(struct comedi_device *dev,
                release_firmware(fw);
        }
 
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 EXPORT_SYMBOL_GPL(comedi_load_firmware);
 
index 432e3f9c3301ecc7ce6f6d633913bf1e1e85f4e4..c55f234b29e6052e541dc7b7043d0a877682b4cb 100644 (file)
@@ -63,7 +63,8 @@ enum pci_8255_boardid {
        BOARD_ADLINK_PCI7296,
        BOARD_CB_PCIDIO24,
        BOARD_CB_PCIDIO24H,
-       BOARD_CB_PCIDIO48H,
+       BOARD_CB_PCIDIO48H_OLD,
+       BOARD_CB_PCIDIO48H_NEW,
        BOARD_CB_PCIDIO96H,
        BOARD_NI_PCIDIO96,
        BOARD_NI_PCIDIO96B,
@@ -106,11 +107,16 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = {
                .dio_badr       = 2,
                .n_8255         = 1,
        },
-       [BOARD_CB_PCIDIO48H] = {
+       [BOARD_CB_PCIDIO48H_OLD] = {
                .name           = "cb_pci-dio48h",
                .dio_badr       = 1,
                .n_8255         = 2,
        },
+       [BOARD_CB_PCIDIO48H_NEW] = {
+               .name           = "cb_pci-dio48h",
+               .dio_badr       = 2,
+               .n_8255         = 2,
+       },
        [BOARD_CB_PCIDIO96H] = {
                .name           = "cb_pci-dio96h",
                .dio_badr       = 2,
@@ -263,7 +269,10 @@ static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = {
        { PCI_VDEVICE(ADLINK, 0x7296), BOARD_ADLINK_PCI7296 },
        { PCI_VDEVICE(CB, 0x0028), BOARD_CB_PCIDIO24 },
        { PCI_VDEVICE(CB, 0x0014), BOARD_CB_PCIDIO24H },
-       { PCI_VDEVICE(CB, 0x000b), BOARD_CB_PCIDIO48H },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, 0x0000, 0x0000),
+         .driver_data = BOARD_CB_PCIDIO48H_OLD },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, PCI_VENDOR_ID_CB, 0x000b),
+         .driver_data = BOARD_CB_PCIDIO48H_NEW },
        { PCI_VDEVICE(CB, 0x0017), BOARD_CB_PCIDIO96H },
        { PCI_VDEVICE(NI, 0x0160), BOARD_NI_PCIDIO96 },
        { PCI_VDEVICE(NI, 0x1630), BOARD_NI_PCIDIO96B },
index 99421f90d1895f6a0691d4443c457f5aac2335db..0485d7f398672a61045367b7ac85a267b34b6e8d 100644 (file)
@@ -451,7 +451,12 @@ done:
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
                        BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
                .scan_index = idx,                                      \
-               .scan_type = IIO_ST('s', 16, 16, IIO_BE),               \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 16,                                 \
+                       .storagebits = 16,                              \
+                       .endianness = IIO_BE,                           \
+               },                                                      \
        }
 
 static const struct iio_chan_spec hmc5843_channels[] = {
index 6bd015ac9d683474a034924f8ffec3e752e1d382..96e4eee344ef602174acec2ce27cf57bfb0ce128 100644 (file)
@@ -88,8 +88,9 @@ static int imx_drm_driver_unload(struct drm_device *drm)
 
        imx_drm_device_put();
 
-       drm_mode_config_cleanup(imxdrm->drm);
+       drm_vblank_cleanup(imxdrm->drm);
        drm_kms_helper_poll_fini(imxdrm->drm);
+       drm_mode_config_cleanup(imxdrm->drm);
 
        return 0;
 }
@@ -199,8 +200,8 @@ static void imx_drm_driver_preclose(struct drm_device *drm,
        if (!file->is_master)
                return;
 
-       for (i = 0; i < 4; i++)
-               imx_drm_disable_vblank(drm , i);
+       for (i = 0; i < MAX_CRTC; i++)
+               imx_drm_disable_vblank(drm, i);
 }
 
 static const struct file_operations imx_drm_driver_fops = {
@@ -376,8 +377,6 @@ static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
        struct imx_drm_device *imxdrm = __imx_drm_device();
        int ret;
 
-       drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc,
-                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
        ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
        if (ret)
                return ret;
@@ -385,6 +384,9 @@ static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
        drm_crtc_helper_add(imx_drm_crtc->crtc,
                        imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
 
+       drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc,
+                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
+
        drm_mode_group_reinit(imxdrm->drm);
 
        return 0;
@@ -428,11 +430,11 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
        ret = drm_mode_group_init_legacy_group(imxdrm->drm,
                        &imxdrm->drm->primary->mode_group);
        if (ret)
-               goto err_init;
+               goto err_kms;
 
        ret = drm_vblank_init(imxdrm->drm, MAX_CRTC);
        if (ret)
-               goto err_init;
+               goto err_kms;
 
        /*
         * with vblank_disable_allowed = true, vblank interrupt will be disabled
@@ -441,12 +443,19 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
         */
        imxdrm->drm->vblank_disable_allowed = true;
 
-       if (!imx_drm_device_get())
+       if (!imx_drm_device_get()) {
                ret = -EINVAL;
+               goto err_vblank;
+       }
 
-       ret = 0;
+       mutex_unlock(&imxdrm->mutex);
+       return 0;
 
-err_init:
+err_vblank:
+       drm_vblank_cleanup(drm);
+err_kms:
+       drm_kms_helper_poll_fini(drm);
+       drm_mode_config_cleanup(drm);
        mutex_unlock(&imxdrm->mutex);
 
        return ret;
@@ -492,6 +501,15 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
 
        mutex_lock(&imxdrm->mutex);
 
+       /*
+        * The vblank arrays are dimensioned by MAX_CRTC - we can't
+        * pass IDs greater than this to those functions.
+        */
+       if (imxdrm->pipes >= MAX_CRTC) {
+               ret = -EINVAL;
+               goto err_busy;
+       }
+
        if (imxdrm->drm->open_count) {
                ret = -EBUSY;
                goto err_busy;
@@ -528,6 +546,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
        return 0;
 
 err_register:
+       list_del(&imx_drm_crtc->list);
        kfree(imx_drm_crtc);
 err_alloc:
 err_busy:
index 680f4c8fa0815481a410621eb616879dbb149109..2c44fef8d58b327df92e97667f0661c45e3e57d6 100644 (file)
@@ -114,7 +114,6 @@ struct imx_tve {
        struct drm_encoder encoder;
        struct imx_drm_encoder *imx_drm_encoder;
        struct device *dev;
-       spinlock_t enable_lock; /* serializes tve_enable/disable */
        spinlock_t lock;        /* register lock */
        bool enabled;
        int mode;
@@ -146,10 +145,8 @@ __releases(&tve->lock)
 
 static void tve_enable(struct imx_tve *tve)
 {
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&tve->enable_lock, flags);
        if (!tve->enabled) {
                tve->enabled = true;
                clk_prepare_enable(tve->clk);
@@ -169,23 +166,18 @@ static void tve_enable(struct imx_tve *tve)
                             TVE_CD_SM_IEN |
                             TVE_CD_LM_IEN |
                             TVE_CD_MON_END_IEN);
-
-       spin_unlock_irqrestore(&tve->enable_lock, flags);
 }
 
 static void tve_disable(struct imx_tve *tve)
 {
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&tve->enable_lock, flags);
        if (tve->enabled) {
                tve->enabled = false;
                ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
                                         TVE_IPU_CLK_EN | TVE_EN, 0);
                clk_disable_unprepare(tve->clk);
        }
-       spin_unlock_irqrestore(&tve->enable_lock, flags);
 }
 
 static int tve_setup_tvout(struct imx_tve *tve)
@@ -601,7 +593,6 @@ static int imx_tve_probe(struct platform_device *pdev)
 
        tve->dev = &pdev->dev;
        spin_lock_init(&tve->lock);
-       spin_lock_init(&tve->enable_lock);
 
        ddc_node = of_parse_phandle(np, "ddc", 0);
        if (ddc_node) {
index 7a22ce619ed264ba536de785650700b02f6d3ef3..97ca6924dbb3fce7b5db813aefb781adb273187a 100644 (file)
@@ -996,35 +996,35 @@ static const struct ipu_platform_reg client_reg[] = {
        },
 };
 
+static DEFINE_MUTEX(ipu_client_id_mutex);
 static int ipu_client_id;
 
-static int ipu_add_subdevice_pdata(struct device *dev,
-               const struct ipu_platform_reg *reg)
-{
-       struct platform_device *pdev;
-
-       pdev = platform_device_register_data(dev, reg->name, ipu_client_id++,
-                       &reg->pdata, sizeof(struct ipu_platform_reg));
-
-       return PTR_ERR_OR_ZERO(pdev);
-}
-
 static int ipu_add_client_devices(struct ipu_soc *ipu)
 {
-       int ret;
-       int i;
+       struct device *dev = ipu->dev;
+       unsigned i;
+       int id, ret;
+
+       mutex_lock(&ipu_client_id_mutex);
+       id = ipu_client_id;
+       ipu_client_id += ARRAY_SIZE(client_reg);
+       mutex_unlock(&ipu_client_id_mutex);
 
        for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
                const struct ipu_platform_reg *reg = &client_reg[i];
-               ret = ipu_add_subdevice_pdata(ipu->dev, reg);
-               if (ret)
+               struct platform_device *pdev;
+
+               pdev = platform_device_register_data(dev, reg->name,
+                       id++, &reg->pdata, sizeof(reg->pdata));
+
+               if (IS_ERR(pdev))
                        goto err_register;
        }
 
        return 0;
 
 err_register:
-       platform_device_unregister_children(to_platform_device(ipu->dev));
+       platform_device_unregister_children(to_platform_device(dev));
 
        return ret;
 }
index 6ce0af9977d8c0ccc053e98eb818a98ec8d990f7..5de5981b3bba9330c33dc1420deb011730bfefec 100644 (file)
@@ -448,7 +448,7 @@ int oz_cdev_start(struct oz_pd *pd, int resume)
        }
        spin_lock(&g_cdev.lock);
        if ((g_cdev.active_pd == NULL) &&
-               (memcmp(pd->mac_addr, g_cdev.active_addr, ETH_ALEN) == 0)) {
+               ether_addr_equal(pd->mac_addr, g_cdev.active_addr)) {
                oz_pd_get(pd);
                g_cdev.active_pd = pd;
                oz_dbg(ON, "Active PD arrived\n");
index 88714ec85705f3a771edb4ecc740d06a1a8bc452..19a2521ee17929893824ce74fe5d08b188225022 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/errno.h>
 #include <linux/ieee80211.h>
 #include "ozdbg.h"
@@ -180,7 +181,7 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
                spin_lock_bh(&g_polling_lock);
                list_for_each(e, &g_pd_list) {
                        pd2 = container_of(e, struct oz_pd, link);
-                       if (memcmp(pd2->mac_addr, pd_addr, ETH_ALEN) == 0) {
+                       if (ether_addr_equal(pd2->mac_addr, pd_addr)) {
                                free_pd = pd;
                                pd = pd2;
                                break;
@@ -597,7 +598,7 @@ struct oz_pd *oz_pd_find(const u8 *mac_addr)
        spin_lock_bh(&g_polling_lock);
        list_for_each(e, &g_pd_list) {
                pd = container_of(e, struct oz_pd, link);
-               if (memcmp(pd->mac_addr, mac_addr, ETH_ALEN) == 0) {
+               if (ether_addr_equal(pd->mac_addr, mac_addr)) {
                        atomic_inc(&pd->ref_count);
                        spin_unlock_bh(&g_polling_lock);
                        return pd;
index d70e9119e906cba0c0f38da61948ce745bc5d6e5..00867190413c78d1f3226348e5c68718077c0b9f 100644 (file)
@@ -465,6 +465,7 @@ int iscsit_del_np(struct iscsi_np *np)
                 */
                send_sig(SIGINT, np->np_thread, 1);
                kthread_stop(np->np_thread);
+               np->np_thread = NULL;
        }
 
        np->np_transport->iscsit_free_np(np);
@@ -823,24 +824,22 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
             (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) {
                /*
-                * Vmware ESX v3.0 uses a modified Cisco Initiator (v3.4.2)
-                * that adds support for RESERVE/RELEASE.  There is a bug
-                * add with this new functionality that sets R/W bits when
-                * neither CDB carries any READ or WRITE datapayloads.
+                * From RFC-3720 Section 10.3.1:
+                *
+                * "Either or both of R and W MAY be 1 when either the
+                *  Expected Data Transfer Length and/or Bidirectional Read
+                *  Expected Data Transfer Length are 0"
+                *
+                * For this case, go ahead and clear the unnecssary bits
+                * to avoid any confusion with ->data_direction.
                 */
-               if ((hdr->cdb[0] == 0x16) || (hdr->cdb[0] == 0x17)) {
-                       hdr->flags &= ~ISCSI_FLAG_CMD_READ;
-                       hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
-                       goto done;
-               }
+               hdr->flags &= ~ISCSI_FLAG_CMD_READ;
+               hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
 
-               pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
+               pr_warn("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
                        " set when Expected Data Transfer Length is 0 for"
-                       " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]);
-               return iscsit_add_reject_cmd(cmd,
-                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
+                       " CDB: 0x%02x, Fixing up flags\n", hdr->cdb[0]);
        }
-done:
 
        if (!(hdr->flags & ISCSI_FLAG_CMD_READ) &&
            !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) {
index e3318edb233dbe91b8e35f9fe1a7fff58508fb6b..1c0088fe9e99368c2dfb50b378dee6033cd42cab 100644 (file)
@@ -474,7 +474,8 @@ static ssize_t __iscsi_##prefix##_store_##name(                             \
                                                                        \
        if (!capable(CAP_SYS_ADMIN))                                    \
                return -EPERM;                                          \
-                                                                       \
+       if (count >= sizeof(auth->name))                                \
+               return -EINVAL;                                         \
        snprintf(auth->name, sizeof(auth->name), "%s", page);           \
        if (!strncmp("NULL", auth->name, 4))                            \
                auth->naf_flags &= ~flags;                              \
index 4eb93b2b6473bcce92f912908a0790485db15e85..e29279e6b577dd564e8271f95c171838ead5ca39 100644 (file)
@@ -1403,11 +1403,6 @@ old_sess_out:
 
 out:
        stop = kthread_should_stop();
-       if (!stop && signal_pending(current)) {
-               spin_lock_bh(&np->np_thread_lock);
-               stop = (np->np_thread_state == ISCSI_NP_THREAD_SHUTDOWN);
-               spin_unlock_bh(&np->np_thread_lock);
-       }
        /* Wait for another socket.. */
        if (!stop)
                return 1;
@@ -1415,7 +1410,6 @@ exit:
        iscsi_stop_login_thread_timer(np);
        spin_lock_bh(&np->np_thread_lock);
        np->np_thread_state = ISCSI_NP_THREAD_EXIT;
-       np->np_thread = NULL;
        spin_unlock_bh(&np->np_thread_lock);
 
        return 0;
index 207b340498a3645231dbb2ae449e48f052e3313f..d06de84b069bb0c283495bdf09da4b3e9b96ba2f 100644 (file)
@@ -1106,6 +1106,11 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size)
        dev->dev_attrib.block_size = block_size;
        pr_debug("dev[%p]: SE Device block_size changed to %u\n",
                        dev, block_size);
+
+       if (dev->dev_attrib.max_bytes_per_io)
+               dev->dev_attrib.hw_max_sectors =
+                       dev->dev_attrib.max_bytes_per_io / block_size;
+
        return 0;
 }
 
index 0e34cda3271e9bb3291b06a934c1ef7136488811..78241a53b555fc5600d0a6ffe7b8d8b4e15687d0 100644 (file)
@@ -66,9 +66,8 @@ static int fd_attach_hba(struct se_hba *hba, u32 host_id)
        pr_debug("CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic"
                " Target Core Stack %s\n", hba->hba_id, FD_VERSION,
                TARGET_CORE_MOD_VERSION);
-       pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic"
-               " MaxSectors: %u\n",
-               hba->hba_id, fd_host->fd_host_id, FD_MAX_SECTORS);
+       pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic\n",
+               hba->hba_id, fd_host->fd_host_id);
 
        return 0;
 }
@@ -220,7 +219,8 @@ static int fd_configure_device(struct se_device *dev)
        }
 
        dev->dev_attrib.hw_block_size = fd_dev->fd_block_size;
-       dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
+       dev->dev_attrib.max_bytes_per_io = FD_MAX_BYTES;
+       dev->dev_attrib.hw_max_sectors = FD_MAX_BYTES / fd_dev->fd_block_size;
        dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
 
        if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
index 37ffc5bd23992a5f1e1124b2c6eba9889e7119ff..d7772c167685fecc89caf699884198b9a9d9f999 100644 (file)
@@ -7,7 +7,10 @@
 #define FD_DEVICE_QUEUE_DEPTH  32
 #define FD_MAX_DEVICE_QUEUE_DEPTH 128
 #define FD_BLOCKSIZE           512
-#define FD_MAX_SECTORS         2048
+/*
+ * Limited by the number of iovecs (2048) per vfs_[writev,readv] call
+ */
+#define FD_MAX_BYTES           8388608
 
 #define RRF_EMULATE_CDB                0x01
 #define RRF_GOT_LBA            0x02
index f697f8baec5418d13484904bf3730880f90639fd..2a573de19a9fdceea07d233f15a699be6c10c770 100644 (file)
@@ -278,7 +278,6 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
        acl->se_tpg = tpg;
        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
-       spin_lock_init(&acl->stats_lock);
        acl->dynamic_node_acl = 1;
 
        tpg->se_tpg_tfo->set_default_node_attributes(acl);
@@ -406,7 +405,6 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
        acl->se_tpg = tpg;
        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
-       spin_lock_init(&acl->stats_lock);
 
        tpg->se_tpg_tfo->set_default_node_attributes(acl);
 
@@ -658,15 +656,9 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
        spin_lock_init(&lun->lun_sep_lock);
        init_completion(&lun->lun_ref_comp);
 
-       ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release);
-       if (ret < 0)
-               return ret;
-
        ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev);
-       if (ret < 0) {
-               percpu_ref_cancel_init(&lun->lun_ref);
+       if (ret < 0)
                return ret;
-       }
 
        return 0;
 }
index 268b62768f2b41eab5f7db4d4c5c8b9111f248b6..34aacaaae14ab9b595ea41744504c2cbc65b9ff3 100644 (file)
@@ -93,6 +93,7 @@ struct n_tty_data {
        size_t canon_head;
        size_t echo_head;
        size_t echo_commit;
+       size_t echo_mark;
        DECLARE_BITMAP(char_map, 256);
 
        /* private to n_tty_receive_overrun (single-threaded) */
@@ -336,6 +337,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
 {
        ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
        ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
+       ldata->echo_mark = 0;
        ldata->line_start = 0;
 
        ldata->erasing = 0;
@@ -787,6 +789,7 @@ static void commit_echoes(struct tty_struct *tty)
        size_t head;
 
        head = ldata->echo_head;
+       ldata->echo_mark = head;
        old = ldata->echo_commit - ldata->echo_tail;
 
        /* Process committed echoes if the accumulated # of bytes
@@ -811,10 +814,11 @@ static void process_echoes(struct tty_struct *tty)
        size_t echoed;
 
        if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
-           ldata->echo_commit == ldata->echo_tail)
+           ldata->echo_mark == ldata->echo_tail)
                return;
 
        mutex_lock(&ldata->output_lock);
+       ldata->echo_commit = ldata->echo_mark;
        echoed = __process_echoes(tty);
        mutex_unlock(&ldata->output_lock);
 
@@ -822,6 +826,7 @@ static void process_echoes(struct tty_struct *tty)
                tty->ops->flush_chars(tty);
 }
 
+/* NB: echo_mark and echo_head should be equivalent here */
 static void flush_echoes(struct tty_struct *tty)
 {
        struct n_tty_data *ldata = tty->disc_data;
index 4658e3e0ec4256d9b2e31f890ea72822abf47f93..06525f10e3641bc2140b140a50d8b994acd662d3 100644 (file)
@@ -96,7 +96,8 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
        if (offset == UART_LCR) {
                int tries = 1000;
                while (tries--) {
-                       if (value == p->serial_in(p, UART_LCR))
+                       unsigned int lcr = p->serial_in(p, UART_LCR);
+                       if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
                                return;
                        dw8250_force_idle(p);
                        writeb(value, p->membase + (UART_LCR << p->regshift));
@@ -132,7 +133,8 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
        if (offset == UART_LCR) {
                int tries = 1000;
                while (tries--) {
-                       if (value == p->serial_in(p, UART_LCR))
+                       unsigned int lcr = p->serial_in(p, UART_LCR);
+                       if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
                                return;
                        dw8250_force_idle(p);
                        writel(value, p->membase + (UART_LCR << p->regshift));
@@ -455,6 +457,8 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match);
 static const struct acpi_device_id dw8250_acpi_match[] = {
        { "INT33C4", 0 },
        { "INT33C5", 0 },
+       { "INT3434", 0 },
+       { "INT3435", 0 },
        { "80860F0A", 0 },
        { },
 };
index e46e9f3f19b90d34476b60a2e21aa656fc3c8fae..f619ad5b5eaefc891b6857c03edd942492198e18 100644 (file)
@@ -240,6 +240,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
                                        continue;
                        }
 
+#ifdef SUPPORT_SYSRQ
                        /*
                         * uart_handle_sysrq_char() doesn't work if
                         * spinlocked, for some reason
@@ -253,6 +254,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
                                }
                                spin_lock(&port->lock);
                        }
+#endif
 
                        port->icount.rx++;
 
index 22fad8ad5ac206c4cf22f820e9a4cf5c3f6cd8bd..d8a55e87877f06f3141602e4f08cdcb668c465b0 100644 (file)
@@ -86,11 +86,21 @@ static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem)
        return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
 }
 
+/*
+ * ldsem_cmpxchg() updates @*old with the last-known sem->count value.
+ * Returns 1 if count was successfully changed; @*old will have @new value.
+ * Returns 0 if count was not changed; @*old will have most recent sem->count
+ */
 static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem)
 {
-       long tmp = *old;
-       *old = atomic_long_cmpxchg(&sem->count, *old, new);
-       return *old == tmp;
+       long tmp = atomic_long_cmpxchg(&sem->count, *old, new);
+       if (tmp == *old) {
+               *old = new;
+               return 1;
+       } else {
+               *old = tmp;
+               return 0;
+       }
 }
 
 /*
index 5d8981c5235e50e42776cfb9f672977c11a61ef0..6e73f8cd60e513ca44de8d6bd00fe69085e4453f 100644 (file)
@@ -642,6 +642,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                        : CI_ROLE_GADGET;
        }
 
+       /* only update vbus status for peripheral */
+       if (ci->role == CI_ROLE_GADGET)
+               ci_handle_vbus_change(ci);
+
        ret = ci_role_start(ci, ci->role);
        if (ret) {
                dev_err(dev, "can't start %s role\n", ci_role(ci)->name);
index 59e6020ea7539e5e331364ac067c9a16f27855ba..526cd77563d8a89c29f5444901ee3ba366b1575a 100644 (file)
@@ -88,7 +88,8 @@ static int host_start(struct ci_hdrc *ci)
        return ret;
 
 disable_reg:
-       regulator_disable(ci->platdata->reg_vbus);
+       if (ci->platdata->reg_vbus)
+               regulator_disable(ci->platdata->reg_vbus);
 
 put_hcd:
        usb_put_hcd(hcd);
index b34c81969cba672a7e880f405f2445adf36b7e6f..69d20fbb38a26a32357cc9f5d7fc4f81efa08cca 100644 (file)
@@ -1795,9 +1795,6 @@ static int udc_start(struct ci_hdrc *ci)
        pm_runtime_no_callbacks(&ci->gadget.dev);
        pm_runtime_enable(&ci->gadget.dev);
 
-       /* Update ci->vbus_active */
-       ci_handle_vbus_change(ci);
-
        return retval;
 
 destroy_eps:
index 4d387596f3f0a6e531caa1a9049a383d605091b4..0b23a8639311b182ee9e2afddcec1cb888269257 100644 (file)
@@ -854,13 +854,11 @@ static int wdm_manage_power(struct usb_interface *intf, int on)
 {
        /* need autopm_get/put here to ensure the usbcore sees the new value */
        int rv = usb_autopm_get_interface(intf);
-       if (rv < 0)
-               goto err;
 
        intf->needs_remote_wakeup = on;
-       usb_autopm_put_interface(intf);
-err:
-       return rv;
+       if (!rv)
+               usb_autopm_put_interface(intf);
+       return 0;
 }
 
 static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
index 74f9cf02da070a6d1c23b643a56f76e3264fb8cd..a49217ae35333846bb76912666f0efa12bca6813 100644 (file)
@@ -455,9 +455,6 @@ static int dwc3_probe(struct platform_device *pdev)
        if (IS_ERR(regs))
                return PTR_ERR(regs);
 
-       usb_phy_set_suspend(dwc->usb2_phy, 0);
-       usb_phy_set_suspend(dwc->usb3_phy, 0);
-
        spin_lock_init(&dwc->lock);
        platform_set_drvdata(pdev, dwc);
 
@@ -488,6 +485,9 @@ static int dwc3_probe(struct platform_device *pdev)
                goto err0;
        }
 
+       usb_phy_set_suspend(dwc->usb2_phy, 0);
+       usb_phy_set_suspend(dwc->usb3_phy, 0);
+
        ret = dwc3_event_buffers_setup(dwc);
        if (ret) {
                dev_err(dwc->dev, "failed to setup event buffers\n");
@@ -569,6 +569,8 @@ err2:
        dwc3_event_buffers_cleanup(dwc);
 
 err1:
+       usb_phy_set_suspend(dwc->usb2_phy, 1);
+       usb_phy_set_suspend(dwc->usb3_phy, 1);
        dwc3_core_exit(dwc);
 
 err0:
index 418444ebb1b8bb1fd1862fc9233c7562c5c40d81..8c356af79409f9ef4647d141bc6aa5146791496b 100644 (file)
@@ -136,23 +136,27 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        struct ohci_hcd *ohci;
        int retval;
        struct usb_hcd *hcd = NULL;
-
-       if (pdev->num_resources != 2) {
-               pr_debug("hcd probe: invalid num_resources");
-               return -ENODEV;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int irq;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_dbg(dev, "hcd probe: missing memory resource\n");
+               return -ENXIO;
        }
 
-       if ((pdev->resource[0].flags != IORESOURCE_MEM)
-                       || (pdev->resource[1].flags != IORESOURCE_IRQ)) {
-               pr_debug("hcd probe: invalid resource type\n");
-               return -ENODEV;
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_dbg(dev, "hcd probe: missing irq resource\n");
+               return irq;
        }
 
        hcd = usb_create_hcd(driver, &pdev->dev, "at91");
        if (!hcd)
                return -ENOMEM;
-       hcd->rsrc_start = pdev->resource[0].start;
-       hcd->rsrc_len = resource_size(&pdev->resource[0]);
+       hcd->rsrc_start = res->start;
+       hcd->rsrc_len = resource_size(res);
 
        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
                pr_debug("request_mem_region failed\n");
@@ -199,7 +203,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        ohci->num_ports = board->ports;
        at91_start_hc(pdev);
 
-       retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (retval == 0)
                return retval;
 
index b8dffd59eb256e52786328e5e4f1919846a80d9c..73f5208714a4a4d8270bd85acd1ec625fb9abf71 100644 (file)
@@ -128,7 +128,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 * any other sleep) on Haswell machines with LPT and LPT-LP
                 * with the new Intel BIOS
                 */
-               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+               /* Limit the quirk to only known vendors, as this triggers
+                * yet another BIOS bug on some other machines
+                * https://bugzilla.kernel.org/show_bug.cgi?id=66171
+                */
+               if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)
+                       xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
index 08e2f39027ec00ae0a7c5ae07b46fdd1cdbfae8f..2b41c636a52a7a1ecf3ae0e3df622d141307c038 100644 (file)
@@ -19,8 +19,9 @@ config AB8500_USB
          in host mode, low speed.
 
 config FSL_USB2_OTG
-       bool "Freescale USB OTG Transceiver Driver"
+       tristate "Freescale USB OTG Transceiver Driver"
        depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
+       depends on USB
        select USB_OTG
        select USB_PHY
        help
@@ -29,6 +30,7 @@ config FSL_USB2_OTG
 config ISP1301_OMAP
        tristate "Philips ISP1301 with OMAP OTG"
        depends on I2C && ARCH_OMAP_OTG
+       depends on USB
        select USB_PHY
        help
          If you say yes here you get support for the Philips ISP1301
index 82232acf1ab61b17cfbe9d084c3ed2188d554b18..bbe4f8e6e8d7492be10cc54cfe2f37e8001f2db6 100644 (file)
@@ -876,7 +876,7 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
 
        tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
                resource_size(res));
-       if (!tegra_phy->regs) {
+       if (!tegra_phy->pad_regs) {
                dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n");
                return -ENOMEM;
        }
index 30e8a61552d4d0526d999c0b49651593f04a5530..bad57ce77ba508e0f6ff8c07fa516e9477606a3c 100644 (file)
@@ -127,7 +127,8 @@ static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
 
 static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
 {
-       u8 data, ret = 0;
+       u8 data;
+       int ret;
 
        ret = twl_i2c_read_u8(module, &data, address);
        if (ret >= 0)
index 496b7e39d5bee4d64ac91b7e0187cd1771fd565a..cc7a24154490b29ebb39d4b9d3e72785c4320285 100644 (file)
@@ -251,6 +251,7 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
 #define ZTE_PRODUCT_MC2718                     0xffe8
+#define ZTE_PRODUCT_AC2726                     0xfff1
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -1453,6 +1454,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
index fca4c752a4ed233199d82a787c0ebfbfff32e71c..eae2c873b39ff7dbb2ecd8d7624a1e2aec14e8ca 100644 (file)
@@ -281,8 +281,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x19d2, 0xfffd) },
        { USB_DEVICE(0x19d2, 0xfffc) },
        { USB_DEVICE(0x19d2, 0xfffb) },
-       /* AC2726, AC8710_V3 */
-       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfff1, 0xff, 0xff, 0xff) },
+       /* AC8710_V3 */
        { USB_DEVICE(0x19d2, 0xfff6) },
        { USB_DEVICE(0x19d2, 0xfff7) },
        { USB_DEVICE(0x19d2, 0xfff8) },
index c444654fc33fb6f7e858824eb8ed816186bf3bda..5c4a95b516cf9e576884c8f84e566f03b396facb 100644 (file)
@@ -285,7 +285,7 @@ static void update_balloon_size(struct virtio_balloon *vb)
 {
        __le32 actual = cpu_to_le32(vb->num_pages);
 
-       virtio_cwrite(vb->vdev, struct virtio_balloon_config, num_pages,
+       virtio_cwrite(vb->vdev, struct virtio_balloon_config, actual,
                      &actual);
 }
 
index 55ea73f7c70b52e49ca3b4f2b40f5baa064928e9..4c02e2b9410377d9e6b77fe1bc2b50d929774551 100644 (file)
@@ -350,17 +350,19 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
 
                pfn = page_to_pfn(page);
 
-               set_phys_to_machine(pfn, frame_list[i]);
-
 #ifdef CONFIG_XEN_HAVE_PVMMU
-               /* Link back into the page tables if not highmem. */
-               if (xen_pv_domain() && !PageHighMem(page)) {
-                       int ret;
-                       ret = HYPERVISOR_update_va_mapping(
-                               (unsigned long)__va(pfn << PAGE_SHIFT),
-                               mfn_pte(frame_list[i], PAGE_KERNEL),
-                               0);
-                       BUG_ON(ret);
+               if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+                       set_phys_to_machine(pfn, frame_list[i]);
+
+                       /* Link back into the page tables if not highmem. */
+                       if (!PageHighMem(page)) {
+                               int ret;
+                               ret = HYPERVISOR_update_va_mapping(
+                                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                                               mfn_pte(frame_list[i], PAGE_KERNEL),
+                                               0);
+                               BUG_ON(ret);
+                       }
                }
 #endif
 
@@ -378,7 +380,6 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
        enum bp_state state = BP_DONE;
        unsigned long  pfn, i;
        struct page   *page;
-       struct page   *scratch_page;
        int ret;
        struct xen_memory_reservation reservation = {
                .address_bits = 0,
@@ -411,27 +412,29 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 
                scrub_page(page);
 
+#ifdef CONFIG_XEN_HAVE_PVMMU
                /*
                 * Ballooned out frames are effectively replaced with
                 * a scratch frame.  Ensure direct mappings and the
                 * p2m are consistent.
                 */
-               scratch_page = get_balloon_scratch_page();
-#ifdef CONFIG_XEN_HAVE_PVMMU
-               if (xen_pv_domain() && !PageHighMem(page)) {
-                       ret = HYPERVISOR_update_va_mapping(
-                               (unsigned long)__va(pfn << PAGE_SHIFT),
-                               pfn_pte(page_to_pfn(scratch_page),
-                                       PAGE_KERNEL_RO), 0);
-                       BUG_ON(ret);
-               }
-#endif
                if (!xen_feature(XENFEAT_auto_translated_physmap)) {
                        unsigned long p;
+                       struct page   *scratch_page = get_balloon_scratch_page();
+
+                       if (!PageHighMem(page)) {
+                               ret = HYPERVISOR_update_va_mapping(
+                                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                                               pfn_pte(page_to_pfn(scratch_page),
+                                                       PAGE_KERNEL_RO), 0);
+                               BUG_ON(ret);
+                       }
                        p = page_to_pfn(scratch_page);
                        __set_phys_to_machine(pfn, pfn_to_mfn(p));
+
+                       put_balloon_scratch_page();
                }
-               put_balloon_scratch_page();
+#endif
 
                balloon_append(pfn_to_page(pfn));
        }
@@ -627,15 +630,17 @@ static int __init balloon_init(void)
        if (!xen_domain())
                return -ENODEV;
 
-       for_each_online_cpu(cpu)
-       {
-               per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL);
-               if (per_cpu(balloon_scratch_page, cpu) == NULL) {
-                       pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu);
-                       return -ENOMEM;
+       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+               for_each_online_cpu(cpu)
+               {
+                       per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL);
+                       if (per_cpu(balloon_scratch_page, cpu) == NULL) {
+                               pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu);
+                               return -ENOMEM;
+                       }
                }
+               register_cpu_notifier(&balloon_cpu_notifier);
        }
-       register_cpu_notifier(&balloon_cpu_notifier);
 
        pr_info("Initialising balloon driver\n");
 
index 028387192b608b04a9fd9483a9916404cb861f76..aa846a48f4009eaac8271a8a653716c27aa1dc01 100644 (file)
@@ -1176,7 +1176,8 @@ static int gnttab_setup(void)
                gnttab_shared.addr = xen_remap(xen_hvm_resume_frames,
                                                PAGE_SIZE * max_nr_gframes);
                if (gnttab_shared.addr == NULL) {
-                       pr_warn("Failed to ioremap gnttab share frames!\n");
+                       pr_warn("Failed to ioremap gnttab share frames (addr=0x%08lx)!\n",
+                                       xen_hvm_resume_frames);
                        return -ENOMEM;
                }
        }
index 8e74590fa1bb5d9149e17550c3f4ec7b74142983..569a13b9e856de5c3900050d583844f401243e96 100644 (file)
@@ -533,12 +533,17 @@ static void privcmd_close(struct vm_area_struct *vma)
 {
        struct page **pages = vma->vm_private_data;
        int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       int rc;
 
        if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages)
                return;
 
-       xen_unmap_domain_mfn_range(vma, numpgs, pages);
-       free_xenballooned_pages(numpgs, pages);
+       rc = xen_unmap_domain_mfn_range(vma, numpgs, pages);
+       if (rc == 0)
+               free_xenballooned_pages(numpgs, pages);
+       else
+               pr_crit("unable to unmap MFN range: leaking %d pages. rc=%d\n",
+                       numpgs, rc);
        kfree(pages);
 }
 
index 6efb7f6cb22e9ba5aabb5f111129ef69b7dac370..062a5f6a1448c6cff1cd1dc09e84db3f0d59cc27 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -244,9 +244,14 @@ static void aio_free_ring(struct kioctx *ctx)
        int i;
 
        for (i = 0; i < ctx->nr_pages; i++) {
+               struct page *page;
                pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i,
                                page_count(ctx->ring_pages[i]));
-               put_page(ctx->ring_pages[i]);
+               page = ctx->ring_pages[i];
+               if (!page)
+                       continue;
+               ctx->ring_pages[i] = NULL;
+               put_page(page);
        }
 
        put_aio_ring_file(ctx);
@@ -280,18 +285,38 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
        unsigned long flags;
        int rc;
 
+       rc = 0;
+
+       /* Make sure the old page hasn't already been changed */
+       spin_lock(&mapping->private_lock);
+       ctx = mapping->private_data;
+       if (ctx) {
+               pgoff_t idx;
+               spin_lock_irqsave(&ctx->completion_lock, flags);
+               idx = old->index;
+               if (idx < (pgoff_t)ctx->nr_pages) {
+                       if (ctx->ring_pages[idx] != old)
+                               rc = -EAGAIN;
+               } else
+                       rc = -EINVAL;
+               spin_unlock_irqrestore(&ctx->completion_lock, flags);
+       } else
+               rc = -EINVAL;
+       spin_unlock(&mapping->private_lock);
+
+       if (rc != 0)
+               return rc;
+
        /* Writeback must be complete */
        BUG_ON(PageWriteback(old));
-       put_page(old);
+       get_page(new);
 
-       rc = migrate_page_move_mapping(mapping, new, old, NULL, mode);
+       rc = migrate_page_move_mapping(mapping, new, old, NULL, mode, 1);
        if (rc != MIGRATEPAGE_SUCCESS) {
-               get_page(old);
+               put_page(new);
                return rc;
        }
 
-       get_page(new);
-
        /* We can potentially race against kioctx teardown here.  Use the
         * address_space's private data lock to protect the mapping's
         * private_data.
@@ -303,13 +328,24 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
                spin_lock_irqsave(&ctx->completion_lock, flags);
                migrate_page_copy(new, old);
                idx = old->index;
-               if (idx < (pgoff_t)ctx->nr_pages)
-                       ctx->ring_pages[idx] = new;
+               if (idx < (pgoff_t)ctx->nr_pages) {
+                       /* And only do the move if things haven't changed */
+                       if (ctx->ring_pages[idx] == old)
+                               ctx->ring_pages[idx] = new;
+                       else
+                               rc = -EAGAIN;
+               } else
+                       rc = -EINVAL;
                spin_unlock_irqrestore(&ctx->completion_lock, flags);
        } else
                rc = -EBUSY;
        spin_unlock(&mapping->private_lock);
 
+       if (rc == MIGRATEPAGE_SUCCESS)
+               put_page(old);
+       else
+               put_page(new);
+
        return rc;
 }
 #endif
@@ -326,7 +362,7 @@ static int aio_setup_ring(struct kioctx *ctx)
        struct aio_ring *ring;
        unsigned nr_events = ctx->max_reqs;
        struct mm_struct *mm = current->mm;
-       unsigned long size, populate;
+       unsigned long size, unused;
        int nr_pages;
        int i;
        struct file *file;
@@ -347,6 +383,20 @@ static int aio_setup_ring(struct kioctx *ctx)
                return -EAGAIN;
        }
 
+       ctx->aio_ring_file = file;
+       nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
+                       / sizeof(struct io_event);
+
+       ctx->ring_pages = ctx->internal_pages;
+       if (nr_pages > AIO_RING_PAGES) {
+               ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
+                                         GFP_KERNEL);
+               if (!ctx->ring_pages) {
+                       put_aio_ring_file(ctx);
+                       return -ENOMEM;
+               }
+       }
+
        for (i = 0; i < nr_pages; i++) {
                struct page *page;
                page = find_or_create_page(file->f_inode->i_mapping,
@@ -358,19 +408,14 @@ static int aio_setup_ring(struct kioctx *ctx)
                SetPageUptodate(page);
                SetPageDirty(page);
                unlock_page(page);
+
+               ctx->ring_pages[i] = page;
        }
-       ctx->aio_ring_file = file;
-       nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
-                       / sizeof(struct io_event);
+       ctx->nr_pages = i;
 
-       ctx->ring_pages = ctx->internal_pages;
-       if (nr_pages > AIO_RING_PAGES) {
-               ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
-                                         GFP_KERNEL);
-               if (!ctx->ring_pages) {
-                       put_aio_ring_file(ctx);
-                       return -ENOMEM;
-               }
+       if (unlikely(i != nr_pages)) {
+               aio_free_ring(ctx);
+               return -EAGAIN;
        }
 
        ctx->mmap_size = nr_pages * PAGE_SIZE;
@@ -379,9 +424,9 @@ static int aio_setup_ring(struct kioctx *ctx)
        down_write(&mm->mmap_sem);
        ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
                                       PROT_READ | PROT_WRITE,
-                                      MAP_SHARED | MAP_POPULATE, 0, &populate);
+                                      MAP_SHARED, 0, &unused);
+       up_write(&mm->mmap_sem);
        if (IS_ERR((void *)ctx->mmap_base)) {
-               up_write(&mm->mmap_sem);
                ctx->mmap_size = 0;
                aio_free_ring(ctx);
                return -EAGAIN;
@@ -389,27 +434,6 @@ static int aio_setup_ring(struct kioctx *ctx)
 
        pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base);
 
-       /* We must do this while still holding mmap_sem for write, as we
-        * need to be protected against userspace attempting to mremap()
-        * or munmap() the ring buffer.
-        */
-       ctx->nr_pages = get_user_pages(current, mm, ctx->mmap_base, nr_pages,
-                                      1, 0, ctx->ring_pages, NULL);
-
-       /* Dropping the reference here is safe as the page cache will hold
-        * onto the pages for us.  It is also required so that page migration
-        * can unmap the pages and get the right reference count.
-        */
-       for (i = 0; i < ctx->nr_pages; i++)
-               put_page(ctx->ring_pages[i]);
-
-       up_write(&mm->mmap_sem);
-
-       if (unlikely(ctx->nr_pages != nr_pages)) {
-               aio_free_ring(ctx);
-               return -EAGAIN;
-       }
-
        ctx->user_id = ctx->mmap_base;
        ctx->nr_events = nr_events; /* trusted copy */
 
@@ -652,7 +676,8 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
        aio_nr += ctx->max_reqs;
        spin_unlock(&aio_nr_lock);
 
-       percpu_ref_get(&ctx->users); /* io_setup() will drop this ref */
+       percpu_ref_get(&ctx->users);    /* io_setup() will drop this ref */
+       percpu_ref_get(&ctx->reqs);     /* free_ioctx_users() will drop this */
 
        err = ioctx_add_table(ctx, mm);
        if (err)
index 288534920fe5cc4960f99ae636777344c5d42db6..20d6697bd6386560a679dda5e8b8592a65d63798 100644 (file)
@@ -1493,6 +1493,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type,
                                sb->s_blocksize - offset : towrite;
 
                tmp_bh.b_state = 0;
+               tmp_bh.b_size = sb->s_blocksize;
                err = ext2_get_block(inode, blk, &tmp_bh, 1);
                if (err < 0)
                        goto out;
index e6185031c1ccb5d7ef6c35185d77e5b06d648a5d..ece55565b9cd35575c454d44656c63321d89e0f9 100644 (file)
@@ -268,6 +268,16 @@ struct ext4_io_submit {
 /* Translate # of blks to # of clusters */
 #define EXT4_NUM_B2C(sbi, blks)        (((blks) + (sbi)->s_cluster_ratio - 1) >> \
                                 (sbi)->s_cluster_bits)
+/* Mask out the low bits to get the starting block of the cluster */
+#define EXT4_PBLK_CMASK(s, pblk) ((pblk) &                             \
+                                 ~((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
+#define EXT4_LBLK_CMASK(s, lblk) ((lblk) &                             \
+                                 ~((ext4_lblk_t) (s)->s_cluster_ratio - 1))
+/* Get the cluster offset */
+#define EXT4_PBLK_COFF(s, pblk) ((pblk) &                              \
+                                ((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
+#define EXT4_LBLK_COFF(s, lblk) ((lblk) &                              \
+                                ((ext4_lblk_t) (s)->s_cluster_ratio - 1))
 
 /*
  * Structure of a blocks group descriptor
index 17ac112ab1012bd88ff32d145f27a29f025efdde..3fe29de832c825e390b8d59d818b5ec37a8eb61f 100644 (file)
@@ -259,6 +259,15 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
                if (WARN_ON_ONCE(err)) {
                        ext4_journal_abort_handle(where, line, __func__, bh,
                                                  handle, err);
+                       ext4_error_inode(inode, where, line,
+                                        bh->b_blocknr,
+                                        "journal_dirty_metadata failed: "
+                                        "handle type %u started at line %u, "
+                                        "credits %u/%u, errcode %d",
+                                        handle->h_type,
+                                        handle->h_line_no,
+                                        handle->h_requested_credits,
+                                        handle->h_buffer_credits, err);
                }
        } else {
                if (inode)
index 35f65cf4f318d72bce4e79995ddbc85d0e4bbfa3..4410cc3d6ee2cc817f947e09475e565cebb07211 100644 (file)
@@ -360,8 +360,10 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
 {
        ext4_fsblk_t block = ext4_ext_pblock(ext);
        int len = ext4_ext_get_actual_len(ext);
+       ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
+       ext4_lblk_t last = lblock + len - 1;
 
-       if (len == 0)
+       if (lblock > last)
                return 0;
        return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
 }
@@ -387,11 +389,26 @@ static int ext4_valid_extent_entries(struct inode *inode,
        if (depth == 0) {
                /* leaf entries */
                struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
+               struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+               ext4_fsblk_t pblock = 0;
+               ext4_lblk_t lblock = 0;
+               ext4_lblk_t prev = 0;
+               int len = 0;
                while (entries) {
                        if (!ext4_valid_extent(inode, ext))
                                return 0;
+
+                       /* Check for overlapping extents */
+                       lblock = le32_to_cpu(ext->ee_block);
+                       len = ext4_ext_get_actual_len(ext);
+                       if ((lblock <= prev) && prev) {
+                               pblock = ext4_ext_pblock(ext);
+                               es->s_last_error_block = cpu_to_le64(pblock);
+                               return 0;
+                       }
                        ext++;
                        entries--;
+                       prev = lblock + len - 1;
                }
        } else {
                struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh);
@@ -1834,8 +1851,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
        depth = ext_depth(inode);
        if (!path[depth].p_ext)
                goto out;
-       b2 = le32_to_cpu(path[depth].p_ext->ee_block);
-       b2 &= ~(sbi->s_cluster_ratio - 1);
+       b2 = EXT4_LBLK_CMASK(sbi, le32_to_cpu(path[depth].p_ext->ee_block));
 
        /*
         * get the next allocated block if the extent in the path
@@ -1845,7 +1861,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
                b2 = ext4_ext_next_allocated_block(path);
                if (b2 == EXT_MAX_BLOCKS)
                        goto out;
-               b2 &= ~(sbi->s_cluster_ratio - 1);
+               b2 = EXT4_LBLK_CMASK(sbi, b2);
        }
 
        /* check for wrap through zero on extent logical start block*/
@@ -2504,7 +2520,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
                 * extent, we have to mark the cluster as used (store negative
                 * cluster number in partial_cluster).
                 */
-               unaligned = pblk & (sbi->s_cluster_ratio - 1);
+               unaligned = EXT4_PBLK_COFF(sbi, pblk);
                if (unaligned && (ee_len == num) &&
                    (*partial_cluster != -((long long)EXT4_B2C(sbi, pblk))))
                        *partial_cluster = EXT4_B2C(sbi, pblk);
@@ -2598,7 +2614,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
                         * accidentally freeing it later on
                         */
                        pblk = ext4_ext_pblock(ex);
-                       if (pblk & (sbi->s_cluster_ratio - 1))
+                       if (EXT4_PBLK_COFF(sbi, pblk))
                                *partial_cluster =
                                        -((long long)EXT4_B2C(sbi, pblk));
                        ex--;
@@ -3753,7 +3769,7 @@ int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk)
 {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        ext4_lblk_t lblk_start, lblk_end;
-       lblk_start = lblk & (~(sbi->s_cluster_ratio - 1));
+       lblk_start = EXT4_LBLK_CMASK(sbi, lblk);
        lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
 
        return ext4_find_delalloc_range(inode, lblk_start, lblk_end);
@@ -3812,9 +3828,9 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
        trace_ext4_get_reserved_cluster_alloc(inode, lblk_start, num_blks);
 
        /* Check towards left side */
-       c_offset = lblk_start & (sbi->s_cluster_ratio - 1);
+       c_offset = EXT4_LBLK_COFF(sbi, lblk_start);
        if (c_offset) {
-               lblk_from = lblk_start & (~(sbi->s_cluster_ratio - 1));
+               lblk_from = EXT4_LBLK_CMASK(sbi, lblk_start);
                lblk_to = lblk_from + c_offset - 1;
 
                if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
@@ -3822,7 +3838,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
        }
 
        /* Now check towards right. */
-       c_offset = (lblk_start + num_blks) & (sbi->s_cluster_ratio - 1);
+       c_offset = EXT4_LBLK_COFF(sbi, lblk_start + num_blks);
        if (allocated_clusters && c_offset) {
                lblk_from = lblk_start + num_blks;
                lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1;
@@ -4030,7 +4046,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
                                     struct ext4_ext_path *path)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+       ext4_lblk_t c_offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
        ext4_lblk_t ex_cluster_start, ex_cluster_end;
        ext4_lblk_t rr_cluster_start;
        ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
@@ -4048,8 +4064,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
            (rr_cluster_start == ex_cluster_start)) {
                if (rr_cluster_start == ex_cluster_end)
                        ee_start += ee_len - 1;
-               map->m_pblk = (ee_start & ~(sbi->s_cluster_ratio - 1)) +
-                       c_offset;
+               map->m_pblk = EXT4_PBLK_CMASK(sbi, ee_start) + c_offset;
                map->m_len = min(map->m_len,
                                 (unsigned) sbi->s_cluster_ratio - c_offset);
                /*
@@ -4203,7 +4218,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
         */
        map->m_flags &= ~EXT4_MAP_FROM_CLUSTER;
        newex.ee_block = cpu_to_le32(map->m_lblk);
-       cluster_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+       cluster_offset = EXT4_LBLK_CMASK(sbi, map->m_lblk);
 
        /*
         * If we are doing bigalloc, check to see if the extent returned
@@ -4271,7 +4286,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
         * needed so that future calls to get_implied_cluster_alloc()
         * work correctly.
         */
-       offset = map->m_lblk & (sbi->s_cluster_ratio - 1);
+       offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
        ar.len = EXT4_NUM_B2C(sbi, offset+allocated);
        ar.goal -= offset;
        ar.logical -= offset;
index 0757634741187a568cc2255187bcd2cf250d852b..61d49ff22c81f844cb8bc6324ad3aa70d649fb7b 100644 (file)
@@ -1206,7 +1206,6 @@ static int ext4_journalled_write_end(struct file *file,
  */
 static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
 {
-       int retries = 0;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        struct ext4_inode_info *ei = EXT4_I(inode);
        unsigned int md_needed;
@@ -1218,7 +1217,6 @@ static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
         * in order to allocate nrblocks
         * worse case is one extent per block
         */
-repeat:
        spin_lock(&ei->i_block_reservation_lock);
        /*
         * ext4_calc_metadata_amount() has side effects, which we have
@@ -1238,10 +1236,6 @@ repeat:
                ei->i_da_metadata_calc_len = save_len;
                ei->i_da_metadata_calc_last_lblock = save_last_lblock;
                spin_unlock(&ei->i_block_reservation_lock);
-               if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
-                       cond_resched();
-                       goto repeat;
-               }
                return -ENOSPC;
        }
        ei->i_reserved_meta_blocks += md_needed;
@@ -1255,7 +1249,6 @@ repeat:
  */
 static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
 {
-       int retries = 0;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        struct ext4_inode_info *ei = EXT4_I(inode);
        unsigned int md_needed;
@@ -1277,7 +1270,6 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
         * in order to allocate nrblocks
         * worse case is one extent per block
         */
-repeat:
        spin_lock(&ei->i_block_reservation_lock);
        /*
         * ext4_calc_metadata_amount() has side effects, which we have
@@ -1297,10 +1289,6 @@ repeat:
                ei->i_da_metadata_calc_len = save_len;
                ei->i_da_metadata_calc_last_lblock = save_last_lblock;
                spin_unlock(&ei->i_block_reservation_lock);
-               if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
-                       cond_resched();
-                       goto repeat;
-               }
                dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
                return -ENOSPC;
        }
index 4d113efa024c8439f4000a0fa59ed643f2489166..04a5c7504be9d6dbe55174d451f559064a7a05cf 100644 (file)
@@ -3442,6 +3442,9 @@ static void ext4_mb_pa_callback(struct rcu_head *head)
 {
        struct ext4_prealloc_space *pa;
        pa = container_of(head, struct ext4_prealloc_space, u.pa_rcu);
+
+       BUG_ON(atomic_read(&pa->pa_count));
+       BUG_ON(pa->pa_deleted == 0);
        kmem_cache_free(ext4_pspace_cachep, pa);
 }
 
@@ -3455,11 +3458,13 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
        ext4_group_t grp;
        ext4_fsblk_t grp_blk;
 
-       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0)
-               return;
-
        /* in this short window concurrent discard can set pa_deleted */
        spin_lock(&pa->pa_lock);
+       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) {
+               spin_unlock(&pa->pa_lock);
+               return;
+       }
+
        if (pa->pa_deleted == 1) {
                spin_unlock(&pa->pa_lock);
                return;
@@ -4121,7 +4126,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
        ext4_get_group_no_and_offset(sb, goal, &group, &block);
 
        /* set up allocation goals */
-       ac->ac_b_ex.fe_logical = ar->logical & ~(sbi->s_cluster_ratio - 1);
+       ac->ac_b_ex.fe_logical = EXT4_LBLK_CMASK(sbi, ar->logical);
        ac->ac_status = AC_STATUS_CONTINUE;
        ac->ac_sb = sb;
        ac->ac_inode = ar->inode;
@@ -4663,7 +4668,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
         * blocks at the beginning or the end unless we are explicitly
         * requested to avoid doing so.
         */
-       overflow = block & (sbi->s_cluster_ratio - 1);
+       overflow = EXT4_PBLK_COFF(sbi, block);
        if (overflow) {
                if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
                        overflow = sbi->s_cluster_ratio - overflow;
@@ -4677,7 +4682,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
                        count += overflow;
                }
        }
-       overflow = count & (sbi->s_cluster_ratio - 1);
+       overflow = EXT4_LBLK_COFF(sbi, count);
        if (overflow) {
                if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
                        if (count > overflow)
index c977f4e4e63be6c4cf3b477f628e4fc7d323d1f5..1f7784de05b6c6afad4d7437202ceb6efeec3399 100644 (file)
@@ -792,7 +792,7 @@ static void ext4_put_super(struct super_block *sb)
        }
 
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        ext4_release_system_zone(sb);
        ext4_mb_release(sb);
        ext4_ext_release(sb);
@@ -3316,10 +3316,18 @@ int ext4_calculate_overhead(struct super_block *sb)
 }
 
 
-static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
+static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
 {
        ext4_fsblk_t resv_clusters;
 
+       /*
+        * There's no need to reserve anything when we aren't using extents.
+        * The space estimates are exact, there are no unwritten extents,
+        * hole punching doesn't need new metadata... This is needed especially
+        * to keep ext2/3 backward compatibility.
+        */
+       if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS))
+               return 0;
        /*
         * By default we reserve 2% or 4096 clusters, whichever is smaller.
         * This should cover the situations where we can not afford to run
@@ -3328,7 +3336,8 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
         * allocation would require 1, or 2 blocks, higher numbers are
         * very rare.
         */
-       resv_clusters = ext4_blocks_count(sbi->s_es) >> sbi->s_cluster_bits;
+       resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >>
+                       EXT4_SB(sb)->s_cluster_bits;
 
        do_div(resv_clusters, 50);
        resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
@@ -4071,10 +4080,10 @@ no_journal:
                         "available");
        }
 
-       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sbi));
+       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb));
        if (err) {
                ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
-                        "reserved pool", ext4_calculate_resv_clusters(sbi));
+                        "reserved pool", ext4_calculate_resv_clusters(sb));
                goto failed_mount4a;
        }
 
@@ -4184,7 +4193,7 @@ failed_mount_wq:
        }
 failed_mount3:
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        if (sbi->s_flex_groups)
                ext4_kvfree(sbi->s_flex_groups);
        percpu_counter_destroy(&sbi->s_freeclusters_counter);
index 52032647dd4a32f7c8efaea95227634071f8d7d3..5fa344afb49ae8642be889ce2b3f69d176af548e 100644 (file)
@@ -702,7 +702,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        read_lock(&journal->j_state_lock);
 #ifdef CONFIG_JBD2_DEBUG
        if (!tid_geq(journal->j_commit_request, tid)) {
-               printk(KERN_EMERG
+               printk(KERN_ERR
                       "%s: error: j_commit_request=%d, tid=%d\n",
                       __func__, journal->j_commit_request, tid);
        }
@@ -718,10 +718,8 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        }
        read_unlock(&journal->j_state_lock);
 
-       if (unlikely(is_journal_aborted(journal))) {
-               printk(KERN_EMERG "journal commit I/O error\n");
+       if (unlikely(is_journal_aborted(journal)))
                err = -EIO;
-       }
        return err;
 }
 
@@ -1527,13 +1525,13 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) &&
            JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                /* Can't have checksum v1 and v2 on at the same time! */
-               printk(KERN_ERR "JBD: Can't enable checksumming v1 and v2 "
+               printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 "
                       "at the same time!\n");
                goto out;
        }
 
        if (!jbd2_verify_csum_type(journal, sb)) {
-               printk(KERN_ERR "JBD: Unknown checksum type\n");
+               printk(KERN_ERR "JBD2: Unknown checksum type\n");
                goto out;
        }
 
@@ -1541,7 +1539,7 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
                if (IS_ERR(journal->j_chksum_driver)) {
-                       printk(KERN_ERR "JBD: Cannot load crc32c driver.\n");
+                       printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
                        err = PTR_ERR(journal->j_chksum_driver);
                        journal->j_chksum_driver = NULL;
                        goto out;
@@ -1550,7 +1548,7 @@ static int journal_get_superblock(journal_t *journal)
 
        /* Check superblock checksum */
        if (!jbd2_superblock_csum_verify(journal, sb)) {
-               printk(KERN_ERR "JBD: journal checksum error\n");
+               printk(KERN_ERR "JBD2: journal checksum error\n");
                goto out;
        }
 
@@ -1836,7 +1834,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
                        journal->j_chksum_driver = crypto_alloc_shash("crc32c",
                                                                      0, 0);
                        if (IS_ERR(journal->j_chksum_driver)) {
-                               printk(KERN_ERR "JBD: Cannot load crc32c "
+                               printk(KERN_ERR "JBD2: Cannot load crc32c "
                                       "driver.\n");
                                journal->j_chksum_driver = NULL;
                                return 0;
@@ -2645,7 +2643,7 @@ static void __exit journal_exit(void)
 #ifdef CONFIG_JBD2_DEBUG
        int n = atomic_read(&nr_journal_heads);
        if (n)
-               printk(KERN_EMERG "JBD2: leaked %d journal_heads!\n", n);
+               printk(KERN_ERR "JBD2: leaked %d journal_heads!\n", n);
 #endif
        jbd2_remove_jbd_stats_proc_entry();
        jbd2_journal_destroy_caches();
index 3929c50428b1a289d4024fcbe673276f63ff97c0..3b6bb19d60b17abceadec4c38df5d3570c0fcba9 100644 (file)
@@ -594,7 +594,7 @@ static int do_one_pass(journal_t *journal,
                                                be32_to_cpu(tmp->h_sequence))) {
                                                brelse(obh);
                                                success = -EIO;
-                                               printk(KERN_ERR "JBD: Invalid "
+                                               printk(KERN_ERR "JBD2: Invalid "
                                                       "checksum recovering "
                                                       "block %llu in log\n",
                                                       blocknr);
index 7aa9a32573bba885d166e484c367bffc06bcd9e2..8360674c85bcb98af88d6aaff3ee4c46fe6f31bf 100644 (file)
@@ -932,7 +932,7 @@ repeat:
                                        jbd2_alloc(jh2bh(jh)->b_size,
                                                         GFP_NOFS);
                                if (!frozen_buffer) {
-                                       printk(KERN_EMERG
+                                       printk(KERN_ERR
                                               "%s: OOM for frozen_buffer\n",
                                               __func__);
                                        JBUFFER_TRACE(jh, "oom!");
@@ -1166,7 +1166,7 @@ repeat:
        if (!jh->b_committed_data) {
                committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
                if (!committed_data) {
-                       printk(KERN_EMERG "%s: No memory for committed data\n",
+                       printk(KERN_ERR "%s: No memory for committed data\n",
                                __func__);
                        err = -ENOMEM;
                        goto out;
@@ -1290,7 +1290,10 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                 * once a transaction -bzzz
                 */
                jh->b_modified = 1;
-               J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+               if (handle->h_buffer_credits <= 0) {
+                       ret = -ENOSPC;
+                       goto out_unlock_bh;
+               }
                handle->h_buffer_credits--;
        }
 
@@ -1305,7 +1308,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "fastpath");
                if (unlikely(jh->b_transaction !=
                             journal->j_running_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_running_transaction (%p, %u)",
                               journal->j_devname,
@@ -1332,7 +1335,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "already on other transaction");
                if (unlikely(jh->b_transaction !=
                             journal->j_committing_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_committing_transaction (%p, %u)",
                               journal->j_devname,
@@ -1345,7 +1348,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                        ret = -EINVAL;
                }
                if (unlikely(jh->b_next_transaction != transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_next_transaction (%llu, %p, %u) != "
                               "transaction (%p, %u)",
                               journal->j_devname,
@@ -1373,7 +1376,6 @@ out_unlock_bh:
        jbd2_journal_put_journal_head(jh);
 out:
        JBUFFER_TRACE(jh, "exit");
-       WARN_ON(ret);   /* All errors are bugs, so dump the stack */
        return ret;
 }
 
index b8e93a40a5d3342767a26959858d24f2a24274c0..78c3c2097787a1be2ea2bd1757a6c6e5554df72c 100644 (file)
@@ -443,8 +443,11 @@ int pstore_register(struct pstore_info *psi)
                pstore_get_records(0);
 
        kmsg_dump_register(&pstore_dumper);
-       pstore_register_console();
-       pstore_register_ftrace();
+
+       if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
+               pstore_register_console();
+               pstore_register_ftrace();
+       }
 
        if (pstore_update_ms >= 0) {
                pstore_timer.expires = jiffies +
index b94f93685093edb4f2d189238989d3024fffa246..35e7d08fe629dfcb79553bcdcdf39af03b5e4960 100644 (file)
@@ -609,7 +609,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
        struct sysfs_open_file *of;
-       bool has_read, has_write, has_mmap;
+       bool has_read, has_write;
        int error = -EACCES;
 
        /* need attr_sd for attr and ops, its parent for kobj */
@@ -621,7 +621,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 
                has_read = battr->read || battr->mmap;
                has_write = battr->write || battr->mmap;
-               has_mmap = battr->mmap;
        } else {
                const struct sysfs_ops *ops = sysfs_file_ops(attr_sd);
 
@@ -633,7 +632,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 
                has_read = ops->show;
                has_write = ops->store;
-               has_mmap = false;
        }
 
        /* check perms and supported operations */
@@ -661,9 +659,9 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
         * open file has a separate mutex, it's okay as long as those don't
         * happen on the same file.  At this point, we can't easily give
         * each file a separate locking class.  Let's differentiate on
-        * whether the file has mmap or not for now.
+        * whether the file is bin or not for now.
         */
-       if (has_mmap)
+       if (sysfs_is_bin(attr_sd))
                mutex_init(&of->mutex);
        else
                mutex_init(&of->mutex);
index 3ef11b22e7505c380feb6597113d5b150f7b1afb..3b2c14b6f0fb13efd7a3aa89abc05d0a8334a5ff 100644 (file)
@@ -1635,7 +1635,7 @@ xfs_bmap_last_extent(
  * blocks at the end of the file which do not start at the previous data block,
  * we will try to align the new blocks at stripe unit boundaries.
  *
- * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be
+ * Returns 1 in bma->aeof if the file (fork) is empty as any new write will be
  * at, or past the EOF.
  */
 STATIC int
@@ -1650,9 +1650,14 @@ xfs_bmap_isaeof(
        bma->aeof = 0;
        error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec,
                                     &is_empty);
-       if (error || is_empty)
+       if (error)
                return error;
 
+       if (is_empty) {
+               bma->aeof = 1;
+               return 0;
+       }
+
        /*
         * Check if we are allocation or past the last extent, or at least into
         * the last delayed allocated extent.
@@ -3643,10 +3648,19 @@ xfs_bmap_btalloc(
        int             isaligned;
        int             tryagain;
        int             error;
+       int             stripe_align;
 
        ASSERT(ap->length);
 
        mp = ap->ip->i_mount;
+
+       /* stripe alignment for allocation is determined by mount parameters */
+       stripe_align = 0;
+       if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
+               stripe_align = mp->m_swidth;
+       else if (mp->m_dalign)
+               stripe_align = mp->m_dalign;
+
        align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
        if (unlikely(align)) {
                error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
@@ -3655,6 +3669,8 @@ xfs_bmap_btalloc(
                ASSERT(!error);
                ASSERT(ap->length);
        }
+
+
        nullfb = *ap->firstblock == NULLFSBLOCK;
        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
        if (nullfb) {
@@ -3730,7 +3746,7 @@ xfs_bmap_btalloc(
         */
        if (!ap->flist->xbf_low && ap->aeof) {
                if (!ap->offset) {
-                       args.alignment = mp->m_dalign;
+                       args.alignment = stripe_align;
                        atype = args.type;
                        isaligned = 1;
                        /*
@@ -3755,13 +3771,13 @@ xfs_bmap_btalloc(
                         * of minlen+alignment+slop doesn't go up
                         * between the calls.
                         */
-                       if (blen > mp->m_dalign && blen <= args.maxlen)
-                               nextminlen = blen - mp->m_dalign;
+                       if (blen > stripe_align && blen <= args.maxlen)
+                               nextminlen = blen - stripe_align;
                        else
                                nextminlen = args.minlen;
-                       if (nextminlen + mp->m_dalign > args.minlen + 1)
+                       if (nextminlen + stripe_align > args.minlen + 1)
                                args.minalignslop =
-                                       nextminlen + mp->m_dalign -
+                                       nextminlen + stripe_align -
                                        args.minlen - 1;
                        else
                                args.minalignslop = 0;
@@ -3783,7 +3799,7 @@ xfs_bmap_btalloc(
                 */
                args.type = atype;
                args.fsbno = ap->blkno;
-               args.alignment = mp->m_dalign;
+               args.alignment = stripe_align;
                args.minlen = nextminlen;
                args.minalignslop = 0;
                isaligned = 1;
index 5887e41c0323ae85f867cc9bc83bbdf8c1e41cd1..1394106ed22db9db61542f5183023f98ef1ca817 100644 (file)
@@ -1187,7 +1187,12 @@ xfs_zero_remaining_bytes(
                XFS_BUF_UNWRITE(bp);
                XFS_BUF_READ(bp);
                XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
-               xfsbdstrat(mp, bp);
+
+               if (XFS_FORCED_SHUTDOWN(mp)) {
+                       error = XFS_ERROR(EIO);
+                       break;
+               }
+               xfs_buf_iorequest(bp);
                error = xfs_buf_iowait(bp);
                if (error) {
                        xfs_buf_ioerror_alert(bp,
@@ -1200,7 +1205,12 @@ xfs_zero_remaining_bytes(
                XFS_BUF_UNDONE(bp);
                XFS_BUF_UNREAD(bp);
                XFS_BUF_WRITE(bp);
-               xfsbdstrat(mp, bp);
+
+               if (XFS_FORCED_SHUTDOWN(mp)) {
+                       error = XFS_ERROR(EIO);
+                       break;
+               }
+               xfs_buf_iorequest(bp);
                error = xfs_buf_iowait(bp);
                if (error) {
                        xfs_buf_ioerror_alert(bp,
index c7f0b77dcb0090046b84eda27c68d870af25d45a..afe7645e4b2b8b7746665ed35a0d55da6ce11e3b 100644 (file)
@@ -698,7 +698,11 @@ xfs_buf_read_uncached(
        bp->b_flags |= XBF_READ;
        bp->b_ops = ops;
 
-       xfsbdstrat(target->bt_mount, bp);
+       if (XFS_FORCED_SHUTDOWN(target->bt_mount)) {
+               xfs_buf_relse(bp);
+               return NULL;
+       }
+       xfs_buf_iorequest(bp);
        xfs_buf_iowait(bp);
        return bp;
 }
@@ -1089,7 +1093,7 @@ xfs_bioerror(
  * This is meant for userdata errors; metadata bufs come with
  * iodone functions attached, so that we can track down errors.
  */
-STATIC int
+int
 xfs_bioerror_relse(
        struct xfs_buf  *bp)
 {
@@ -1152,7 +1156,7 @@ xfs_bwrite(
        ASSERT(xfs_buf_islocked(bp));
 
        bp->b_flags |= XBF_WRITE;
-       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q);
+       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q | XBF_WRITE_FAIL);
 
        xfs_bdstrat_cb(bp);
 
@@ -1164,25 +1168,6 @@ xfs_bwrite(
        return error;
 }
 
-/*
- * Wrapper around bdstrat so that we can stop data from going to disk in case
- * we are shutting down the filesystem.  Typically user data goes thru this
- * path; one of the exceptions is the superblock.
- */
-void
-xfsbdstrat(
-       struct xfs_mount        *mp,
-       struct xfs_buf          *bp)
-{
-       if (XFS_FORCED_SHUTDOWN(mp)) {
-               trace_xfs_bdstrat_shut(bp, _RET_IP_);
-               xfs_bioerror_relse(bp);
-               return;
-       }
-
-       xfs_buf_iorequest(bp);
-}
-
 STATIC void
 _xfs_buf_ioend(
        xfs_buf_t               *bp,
@@ -1516,6 +1501,12 @@ xfs_wait_buftarg(
                        struct xfs_buf *bp;
                        bp = list_first_entry(&dispose, struct xfs_buf, b_lru);
                        list_del_init(&bp->b_lru);
+                       if (bp->b_flags & XBF_WRITE_FAIL) {
+                               xfs_alert(btp->bt_mount,
+"Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n"
+"Please run xfs_repair to determine the extent of the problem.",
+                                       (long long)bp->b_bn);
+                       }
                        xfs_buf_rele(bp);
                }
                if (loop++ != 0)
@@ -1799,7 +1790,7 @@ __xfs_buf_delwri_submit(
 
        blk_start_plug(&plug);
        list_for_each_entry_safe(bp, n, io_list, b_list) {
-               bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC);
+               bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL);
                bp->b_flags |= XBF_WRITE;
 
                if (!wait) {
index e65683361017745eff61e245ee72896d2e6ff8df..1cf21a4a9f221de465299bf820fa710c3b3aa40e 100644 (file)
@@ -45,6 +45,7 @@ typedef enum {
 #define XBF_ASYNC       (1 << 4) /* initiator will not wait for completion */
 #define XBF_DONE        (1 << 5) /* all pages in the buffer uptodate */
 #define XBF_STALE       (1 << 6) /* buffer has been staled, do not find it */
+#define XBF_WRITE_FAIL  (1 << 24)/* async writes have failed on this buffer */
 
 /* I/O hints for the BIO layer */
 #define XBF_SYNCIO      (1 << 10)/* treat this buffer as synchronous I/O */
@@ -70,6 +71,7 @@ typedef unsigned int xfs_buf_flags_t;
        { XBF_ASYNC,            "ASYNC" }, \
        { XBF_DONE,             "DONE" }, \
        { XBF_STALE,            "STALE" }, \
+       { XBF_WRITE_FAIL,       "WRITE_FAIL" }, \
        { XBF_SYNCIO,           "SYNCIO" }, \
        { XBF_FUA,              "FUA" }, \
        { XBF_FLUSH,            "FLUSH" }, \
@@ -80,6 +82,7 @@ typedef unsigned int xfs_buf_flags_t;
        { _XBF_DELWRI_Q,        "DELWRI_Q" }, \
        { _XBF_COMPOUND,        "COMPOUND" }
 
+
 /*
  * Internal state flags.
  */
@@ -269,9 +272,6 @@ extern void xfs_buf_unlock(xfs_buf_t *);
 
 /* Buffer Read and Write Routines */
 extern int xfs_bwrite(struct xfs_buf *bp);
-
-extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
-
 extern void xfs_buf_ioend(xfs_buf_t *, int);
 extern void xfs_buf_ioerror(xfs_buf_t *, int);
 extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
@@ -282,6 +282,8 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
 #define xfs_buf_zero(bp, off, len) \
            xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
 
+extern int xfs_bioerror_relse(struct xfs_buf *);
+
 static inline int xfs_buf_geterror(xfs_buf_t *bp)
 {
        return bp ? bp->b_error : ENOMEM;
@@ -301,7 +303,8 @@ extern void xfs_buf_terminate(void);
 
 #define XFS_BUF_ZEROFLAGS(bp) \
        ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC| \
-                           XBF_SYNCIO|XBF_FUA|XBF_FLUSH))
+                           XBF_SYNCIO|XBF_FUA|XBF_FLUSH| \
+                           XBF_WRITE_FAIL))
 
 void xfs_buf_stale(struct xfs_buf *bp);
 #define XFS_BUF_UNSTALE(bp)    ((bp)->b_flags &= ~XBF_STALE)
index a64f67ba25d3c99c748e1d4a8f84f7648e3dd651..2227b9b050bb30248d986b343dd33e42c7978529 100644 (file)
@@ -496,6 +496,14 @@ xfs_buf_item_unpin(
        }
 }
 
+/*
+ * Buffer IO error rate limiting. Limit it to no more than 10 messages per 30
+ * seconds so as to not spam logs too much on repeated detection of the same
+ * buffer being bad..
+ */
+
+DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10);
+
 STATIC uint
 xfs_buf_item_push(
        struct xfs_log_item     *lip,
@@ -524,6 +532,14 @@ xfs_buf_item_push(
 
        trace_xfs_buf_item_push(bip);
 
+       /* has a previous flush failed due to IO errors? */
+       if ((bp->b_flags & XBF_WRITE_FAIL) &&
+           ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) {
+               xfs_warn(bp->b_target->bt_mount,
+"Detected failing async write on buffer block 0x%llx. Retrying async write.\n",
+                        (long long)bp->b_bn);
+       }
+
        if (!xfs_buf_delwri_queue(bp, buffer_list))
                rval = XFS_ITEM_FLUSHING;
        xfs_buf_unlock(bp);
@@ -1096,8 +1112,9 @@ xfs_buf_iodone_callbacks(
 
                xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */
 
-               if (!XFS_BUF_ISSTALE(bp)) {
-                       bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE;
+               if (!(bp->b_flags & (XBF_STALE|XBF_WRITE_FAIL))) {
+                       bp->b_flags |= XBF_WRITE | XBF_ASYNC |
+                                      XBF_DONE | XBF_WRITE_FAIL;
                        xfs_buf_iorequest(bp);
                } else {
                        xfs_buf_relse(bp);
index 56369d4509d5603cff44adeb17902324a547f48b..48c7d18f68c3fb23a89a31a955fc9250fbd63108 100644 (file)
@@ -2067,12 +2067,12 @@ xfs_dir2_node_lookup(
  */
 int                                            /* error */
 xfs_dir2_node_removename(
-       xfs_da_args_t           *args)          /* operation arguments */
+       struct xfs_da_args      *args)          /* operation arguments */
 {
-       xfs_da_state_blk_t      *blk;           /* leaf block */
+       struct xfs_da_state_blk *blk;           /* leaf block */
        int                     error;          /* error return value */
        int                     rval;           /* operation return value */
-       xfs_da_state_t          *state;         /* btree cursor */
+       struct xfs_da_state     *state;         /* btree cursor */
 
        trace_xfs_dir2_node_removename(args);
 
@@ -2084,19 +2084,18 @@ xfs_dir2_node_removename(
        state->mp = args->dp->i_mount;
        state->blocksize = state->mp->m_dirblksize;
        state->node_ents = state->mp->m_dir_node_ents;
-       /*
-        * Look up the entry we're deleting, set up the cursor.
-        */
+
+       /* Look up the entry we're deleting, set up the cursor. */
        error = xfs_da3_node_lookup_int(state, &rval);
        if (error)
-               rval = error;
-       /*
-        * Didn't find it, upper layer screwed up.
-        */
+               goto out_free;
+
+       /* Didn't find it, upper layer screwed up. */
        if (rval != EEXIST) {
-               xfs_da_state_free(state);
-               return rval;
+               error = rval;
+               goto out_free;
        }
+
        blk = &state->path.blk[state->path.active - 1];
        ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
        ASSERT(state->extravalid);
@@ -2107,7 +2106,7 @@ xfs_dir2_node_removename(
        error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
                &state->extrablk, &rval);
        if (error)
-               return error;
+               goto out_free;
        /*
         * Fix the hash values up the btree.
         */
@@ -2122,6 +2121,7 @@ xfs_dir2_node_removename(
         */
        if (!error)
                error = xfs_dir2_node_to_leaf(state);
+out_free:
        xfs_da_state_free(state);
        return error;
 }
index 27e0e544e9635ba47281279c68670f7e568a7a58..104455b8046c4bd9ea11855c917b7b46c4573361 100644 (file)
@@ -618,7 +618,8 @@ xfs_setattr_nonsize(
                }
                if (!gid_eq(igid, gid)) {
                        if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
-                               ASSERT(!XFS_IS_PQUOTA_ON(mp));
+                               ASSERT(xfs_sb_version_has_pquotino(&mp->m_sb) ||
+                                      !XFS_IS_PQUOTA_ON(mp));
                                ASSERT(mask & ATTR_GID);
                                ASSERT(gdqp);
                                olddquot2 = xfs_qm_vop_chown(tp, ip,
index b6b669df40f3ab335e75cd3a67903601be0128a4..eae16920655b4569af25e9567682019ba301533d 100644 (file)
@@ -193,7 +193,10 @@ xlog_bread_noalign(
        bp->b_io_length = nbblks;
        bp->b_error = 0;
 
-       xfsbdstrat(log->l_mp, bp);
+       if (XFS_FORCED_SHUTDOWN(log->l_mp))
+               return XFS_ERROR(EIO);
+
+       xfs_buf_iorequest(bp);
        error = xfs_buf_iowait(bp);
        if (error)
                xfs_buf_ioerror_alert(bp, __func__);
@@ -4397,7 +4400,13 @@ xlog_do_recover(
        XFS_BUF_READ(bp);
        XFS_BUF_UNASYNC(bp);
        bp->b_ops = &xfs_sb_buf_ops;
-       xfsbdstrat(log->l_mp, bp);
+
+       if (XFS_FORCED_SHUTDOWN(log->l_mp)) {
+               xfs_buf_relse(bp);
+               return XFS_ERROR(EIO);
+       }
+
+       xfs_buf_iorequest(bp);
        error = xfs_buf_iowait(bp);
        if (error) {
                xfs_buf_ioerror_alert(bp, __func__);
index 14a4996cfec6cb4fbeaa1d3f8432548ebb57d48b..dd88f0e27bd8ce1119d2606c256117d4d2488b9c 100644 (file)
@@ -134,8 +134,6 @@ xfs_qm_dqpurge(
 {
        struct xfs_mount        *mp = dqp->q_mount;
        struct xfs_quotainfo    *qi = mp->m_quotainfo;
-       struct xfs_dquot        *gdqp = NULL;
-       struct xfs_dquot        *pdqp = NULL;
 
        xfs_dqlock(dqp);
        if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
@@ -143,21 +141,6 @@ xfs_qm_dqpurge(
                return EAGAIN;
        }
 
-       /*
-        * If this quota has a hint attached, prepare for releasing it now.
-        */
-       gdqp = dqp->q_gdquot;
-       if (gdqp) {
-               xfs_dqlock(gdqp);
-               dqp->q_gdquot = NULL;
-       }
-
-       pdqp = dqp->q_pdquot;
-       if (pdqp) {
-               xfs_dqlock(pdqp);
-               dqp->q_pdquot = NULL;
-       }
-
        dqp->dq_flags |= XFS_DQ_FREEING;
 
        xfs_dqflock(dqp);
@@ -206,11 +189,47 @@ xfs_qm_dqpurge(
        XFS_STATS_DEC(xs_qm_dquot_unused);
 
        xfs_qm_dqdestroy(dqp);
+       return 0;
+}
+
+/*
+ * Release the group or project dquot pointers the user dquots maybe carrying
+ * around as a hint, and proceed to purge the user dquot cache if requested.
+*/
+STATIC int
+xfs_qm_dqpurge_hints(
+       struct xfs_dquot        *dqp,
+       void                    *data)
+{
+       struct xfs_dquot        *gdqp = NULL;
+       struct xfs_dquot        *pdqp = NULL;
+       uint                    flags = *((uint *)data);
+
+       xfs_dqlock(dqp);
+       if (dqp->dq_flags & XFS_DQ_FREEING) {
+               xfs_dqunlock(dqp);
+               return EAGAIN;
+       }
+
+       /* If this quota has a hint attached, prepare for releasing it now */
+       gdqp = dqp->q_gdquot;
+       if (gdqp)
+               dqp->q_gdquot = NULL;
+
+       pdqp = dqp->q_pdquot;
+       if (pdqp)
+               dqp->q_pdquot = NULL;
+
+       xfs_dqunlock(dqp);
 
        if (gdqp)
-               xfs_qm_dqput(gdqp);
+               xfs_qm_dqrele(gdqp);
        if (pdqp)
-               xfs_qm_dqput(pdqp);
+               xfs_qm_dqrele(pdqp);
+
+       if (flags & XFS_QMOPT_UQUOTA)
+               return xfs_qm_dqpurge(dqp, NULL);
+
        return 0;
 }
 
@@ -222,8 +241,18 @@ xfs_qm_dqpurge_all(
        struct xfs_mount        *mp,
        uint                    flags)
 {
-       if (flags & XFS_QMOPT_UQUOTA)
-               xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge, NULL);
+       /*
+        * We have to release group/project dquot hint(s) from the user dquot
+        * at first if they are there, otherwise we would run into an infinite
+        * loop while walking through radix tree to purge other type of dquots
+        * since their refcount is not zero if the user dquot refers to them
+        * as hint.
+        *
+        * Call the special xfs_qm_dqpurge_hints() will end up go through the
+        * general xfs_qm_dqpurge() against user dquot cache if requested.
+        */
+       xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge_hints, &flags);
+
        if (flags & XFS_QMOPT_GQUOTA)
                xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge, NULL);
        if (flags & XFS_QMOPT_PQUOTA)
@@ -2082,24 +2111,21 @@ xfs_qm_vop_create_dqattach(
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
-       if (udqp) {
+       if (udqp && XFS_IS_UQUOTA_ON(mp)) {
                ASSERT(ip->i_udquot == NULL);
-               ASSERT(XFS_IS_UQUOTA_ON(mp));
                ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
 
                ip->i_udquot = xfs_qm_dqhold(udqp);
                xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (gdqp) {
+       if (gdqp && XFS_IS_GQUOTA_ON(mp)) {
                ASSERT(ip->i_gdquot == NULL);
-               ASSERT(XFS_IS_GQUOTA_ON(mp));
                ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
                ip->i_gdquot = xfs_qm_dqhold(gdqp);
                xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (pdqp) {
+       if (pdqp && XFS_IS_PQUOTA_ON(mp)) {
                ASSERT(ip->i_pdquot == NULL);
-               ASSERT(XFS_IS_PQUOTA_ON(mp));
                ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
 
                ip->i_pdquot = xfs_qm_dqhold(pdqp);
index c035d11b7734196c4fd689121d945e598a8d6d7a..647b6f1d8923fee484ada5eea3e2e68d47df8286 100644 (file)
@@ -314,7 +314,18 @@ xfs_trans_read_buf_map(
                        ASSERT(bp->b_iodone == NULL);
                        XFS_BUF_READ(bp);
                        bp->b_ops = ops;
-                       xfsbdstrat(tp->t_mountp, bp);
+
+                       /*
+                        * XXX(hch): clean up the error handling here to be less
+                        * of a mess..
+                        */
+                       if (XFS_FORCED_SHUTDOWN(mp)) {
+                               trace_xfs_bdstrat_shut(bp, _RET_IP_);
+                               xfs_bioerror_relse(bp);
+                       } else {
+                               xfs_buf_iorequest(bp);
+                       }
+
                        error = xfs_buf_iowait(bp);
                        if (error) {
                                xfs_buf_ioerror_alert(bp, __func__);
index f330d28e4d0eaf4d8e681bb905f52ff72465bea7..db09234589409760b91cb9e696472a3e828476f9 100644 (file)
@@ -217,7 +217,7 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #endif
 
 #ifndef pte_accessible
-# define pte_accessible(pte)           ((void)(pte),1)
+# define pte_accessible(mm, pte)       ((void)(pte), 1)
 #endif
 
 #ifndef flush_tlb_fix_spurious_fault
@@ -599,11 +599,10 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
        barrier();
 #endif
-       if (pmd_none(pmdval))
+       if (pmd_none(pmdval) || pmd_trans_huge(pmdval))
                return 1;
        if (unlikely(pmd_bad(pmdval))) {
-               if (!pmd_trans_huge(pmdval))
-                       pmd_clear_bad(pmd);
+               pmd_clear_bad(pmd);
                return 1;
        }
        return 0;
index 669fef5c745a3fe98145a87d21a588cb64835c15..3e0fbe44176328193cf849fd039d70e91694a4ca 100644 (file)
@@ -3,6 +3,6 @@
 
 #include <uapi/linux/auxvec.h>
 
-#define AT_VECTOR_SIZE_BASE 19 /* NEW_AUX_ENT entries in auxiliary table */
+#define AT_VECTOR_SIZE_BASE 20 /* NEW_AUX_ENT entries in auxiliary table */
   /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */
 #endif /* _LINUX_AUXVEC_H */
index 4d043c30216fc978f1d78bd1425177efef623186..0b3bb16c705a2eadc841d56bf177a900e7a8166e 100644 (file)
@@ -418,7 +418,14 @@ static inline void bcma_maskset16(struct bcma_device *cc,
        bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
 }
 
-extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid);
+extern struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
+                                              u8 unit);
+static inline struct bcma_device *bcma_find_core(struct bcma_bus *bus,
+                                                u16 coreid)
+{
+       return bcma_find_core_unit(bus, coreid, 0);
+}
+
 extern bool bcma_core_is_enabled(struct bcma_device *core);
 extern void bcma_core_disable(struct bcma_device *core, u32 flags);
 extern int bcma_core_enable(struct bcma_device *core, u32 flags);
index b613ffd402d1bdd38747e45e26260b28a4355768..7b99d717411d2b5ef3c14c0b2668a9c3bfe036e2 100644 (file)
@@ -31,7 +31,7 @@ SUBSYS(devices)
 SUBSYS(freezer)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_NET_CLS_CGROUP)
+#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_NET_CLASSID)
 SUBSYS(net_cls)
 #endif
 
@@ -43,7 +43,7 @@ SUBSYS(blkio)
 SUBSYS(perf)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_NETPRIO_CGROUP)
+#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_NET_PRIO)
 SUBSYS(net_prio)
 #endif
 
index ea22721ba269e6d49611fd8ad745ffc363e57ad0..7c8b20b120eac680f27e3cd1e99630b1fe521799 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_IF_MACVLAN_H
 
 #include <linux/if_link.h>
+#include <linux/if_vlan.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
 #include <linux/netlink.h>
@@ -24,28 +25,6 @@ static inline struct socket *macvtap_get_socket(struct file *f)
 struct macvlan_port;
 struct macvtap_queue;
 
-/**
- *     struct macvlan_pcpu_stats - MACVLAN percpu stats
- *     @rx_packets: number of received packets
- *     @rx_bytes: number of received bytes
- *     @rx_multicast: number of received multicast packets
- *     @tx_packets: number of transmitted packets
- *     @tx_bytes: number of transmitted bytes
- *     @syncp: synchronization point for 64bit counters
- *     @rx_errors: number of rx errors
- *     @tx_dropped: number of tx dropped packets
- */
-struct macvlan_pcpu_stats {
-       u64                     rx_packets;
-       u64                     rx_bytes;
-       u64                     rx_multicast;
-       u64                     tx_packets;
-       u64                     tx_bytes;
-       struct u64_stats_sync   syncp;
-       u32                     rx_errors;
-       u32                     tx_dropped;
-};
-
 /*
  * Maximum times a macvtap device can be opened. This can be used to
  * configure the number of receive queue, e.g. for multiqueue virtio.
@@ -62,7 +41,7 @@ struct macvlan_dev {
        struct macvlan_port     *port;
        struct net_device       *lowerdev;
        void                    *fwd_priv;
-       struct macvlan_pcpu_stats __percpu *pcpu_stats;
+       struct vlan_pcpu_stats __percpu *pcpu_stats;
 
        DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
 
@@ -84,7 +63,7 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
                                    bool multicast)
 {
        if (likely(success)) {
-               struct macvlan_pcpu_stats *pcpu_stats;
+               struct vlan_pcpu_stats *pcpu_stats;
 
                pcpu_stats = this_cpu_ptr(vlan->pcpu_stats);
                u64_stats_update_begin(&pcpu_stats->syncp);
@@ -111,9 +90,6 @@ extern void macvlan_dellink(struct net_device *dev, struct list_head *head);
 
 extern int macvlan_link_register(struct rtnl_link_ops *ops);
 
-extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
-                                     struct net_device *dev);
-
 #if IS_ENABLED(CONFIG_MACVLAN)
 static inline struct net_device *
 macvlan_dev_real_dev(const struct net_device *dev)
index f4e56ecd0b1ab49b0e09594e16fe996165168d11..712710bc05803f7fa7b47014d55e1471be18d837 100644 (file)
 #define for_each_ip_tunnel_rcu(pos, start) \
        for (pos = rcu_dereference(start); pos; pos = rcu_dereference(pos->next))
 
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
-       u64     rx_packets;
-       u64     rx_bytes;
-       u64     tx_packets;
-       u64     tx_bytes;
-       struct u64_stats_sync   syncp;
-};
-
 #endif /* _IF_TUNNEL_H_ */
index f252deb99454fa06e4892ab1100e41aea0968d84..bbedfb56bd66074545503f12e161ee2cc640eb58 100644 (file)
@@ -82,25 +82,6 @@ static inline int is_vlan_dev(struct net_device *dev)
 #define vlan_tx_tag_get(__skb)         ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
 #define vlan_tx_tag_get_id(__skb)      ((__skb)->vlan_tci & VLAN_VID_MASK)
 
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-
-extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
-                                              __be16 vlan_proto, u16 vlan_id);
-extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
-extern u16 vlan_dev_vlan_id(const struct net_device *dev);
-
-/**
- *     struct vlan_priority_tci_mapping - vlan egress priority mappings
- *     @priority: skb priority
- *     @vlan_qos: vlan priority: (skb->priority << 13) & 0xE000
- *     @next: pointer to next struct
- */
-struct vlan_priority_tci_mapping {
-       u32                                     priority;
-       u16                                     vlan_qos;
-       struct vlan_priority_tci_mapping        *next;
-};
-
 /**
  *     struct vlan_pcpu_stats - VLAN percpu rx/tx stats
  *     @rx_packets: number of received packets
@@ -123,6 +104,25 @@ struct vlan_pcpu_stats {
        u32                     tx_dropped;
 };
 
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+
+extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
+                                              __be16 vlan_proto, u16 vlan_id);
+extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
+extern u16 vlan_dev_vlan_id(const struct net_device *dev);
+
+/**
+ *     struct vlan_priority_tci_mapping - vlan egress priority mappings
+ *     @priority: skb priority
+ *     @vlan_qos: vlan priority: (skb->priority << 13) & 0xE000
+ *     @next: pointer to next struct
+ */
+struct vlan_priority_tci_mapping {
+       u32                                     priority;
+       u16                                     vlan_qos;
+       struct vlan_priority_tci_mapping        *next;
+};
+
 struct proc_dir_entry;
 struct netpoll;
 
index 2cf55afbcd4e388dbb8bf3bbcd4babaecc1325aa..9a715cfa1fe3c227124b99a75b00c3e5ade22e44 100644 (file)
@@ -133,33 +133,10 @@ struct net_lro_mgr {
 void lro_receive_skb(struct net_lro_mgr *lro_mgr,
                     struct sk_buff *skb,
                     void *priv);
-
-/*
- * Processes a fragment list
- *
- * This functions aggregate fragments and generate SKBs do pass
- * the packets to the stack.
- *
- * @lro_mgr: LRO manager to use
- * @frags: Fragment to be processed. Must contain entire header in first
- *         element.
- * @len: Length of received data
- * @true_size: Actual size of memory the fragment is consuming
- * @priv: Private data that may be used by driver functions
- *        (for example get_tcp_ip_hdr)
- */
-
-void lro_receive_frags(struct net_lro_mgr *lro_mgr,
-                      struct skb_frag_struct *frags,
-                      int len, int true_size, void *priv, __wsum sum);
-
 /*
  * Forward all aggregated SKBs held by lro_mgr to network stack
  */
 
 void lro_flush_all(struct net_lro_mgr *lro_mgr);
 
-void lro_flush_pkt(struct net_lro_mgr *lro_mgr,
-                  struct iphdr *iph, struct tcphdr *tcph);
-
 #endif
index 0e23c26485f457cf2380818a18b00c1175bc02ae..9b503376738fac8e25e9fa71b286b4c341295d76 100644 (file)
@@ -418,6 +418,7 @@ enum {
        ATA_HORKAGE_DUMP_ID     = (1 << 16),    /* dump IDENTIFY data */
        ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17),  /* Set max sects to 65535 */
        ATA_HORKAGE_ATAPI_DMADIR = (1 << 18),   /* device requires dmadir */
+       ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19),    /* don't use queued TRIM */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
index c8929c3832db26d00d80f96e524afbb0e75c4df1..4bfde0e99ed5169d7220204c39070faa387f57ab 100644 (file)
@@ -19,7 +19,7 @@
 
 #define USE_CMPXCHG_LOCKREF \
        (IS_ENABLED(CONFIG_ARCH_USE_CMPXCHG_LOCKREF) && \
-        IS_ENABLED(CONFIG_SMP) && !BLOATED_SPINLOCKS)
+        IS_ENABLED(CONFIG_SMP) && SPINLOCK_SIZE <= 4)
 
 struct lockref {
        union {
index 3d15c838116c67bcdab17b141a6a9f7618fe1b71..b42963bc81dd9835c5b7cb7811a1558038d70899 100644 (file)
@@ -70,9 +70,6 @@ extern int mdio45_nway_restart(const struct mdio_if_info *mdio);
 extern void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
                                      struct ethtool_cmd *ecmd,
                                      u32 npage_adv, u32 npage_lpa);
-extern void
-mdio45_ethtool_spauseparam_an(const struct mdio_if_info *mdio,
-                             const struct ethtool_pauseparam *ecmd);
 
 /**
  * mdio45_ethtool_gset - get settings for ETHTOOL_GSET
index f5096b58b20d3ef64618e18ca37e1083b97af252..f015c059e159f1f8cad2da7b88dd26cdcbfd637d 100644 (file)
@@ -55,7 +55,8 @@ extern int migrate_huge_page_move_mapping(struct address_space *mapping,
                                  struct page *newpage, struct page *page);
 extern int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode);
+               struct buffer_head *head, enum migrate_mode mode,
+               int extra_count);
 #else
 
 static inline void putback_lru_pages(struct list_head *l) {}
@@ -90,10 +91,19 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping,
 #endif /* CONFIG_MIGRATION */
 
 #ifdef CONFIG_NUMA_BALANCING
+extern bool pmd_trans_migrating(pmd_t pmd);
+extern void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd);
 extern int migrate_misplaced_page(struct page *page,
                                  struct vm_area_struct *vma, int node);
 extern bool migrate_ratelimited(int node);
 #else
+static inline bool pmd_trans_migrating(pmd_t pmd)
+{
+       return false;
+}
+static inline void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd)
+{
+}
 static inline int migrate_misplaced_page(struct page *page,
                                         struct vm_area_struct *vma, int node)
 {
index 8df61bc5da00ff9d751727c42ee93b2c6ad7de9f..b0ec0fe035c0da27b3e8ffce43741781ae01c469 100644 (file)
@@ -180,6 +180,7 @@ enum {
        MLX4_SET_PORT_GID_TABLE = 0x5,
        MLX4_SET_PORT_PRIO2TC   = 0x8,
        MLX4_SET_PORT_SCHEDULER = 0x9,
+       MLX4_SET_PORT_VXLAN     = 0xB
 };
 
 enum {
index 98fa492cf40655fe69d21a0a6c20c6756e7f02ed..5dd0d70a06895b49e1d83db28968d0ebfdb179e0 100644 (file)
@@ -81,7 +81,12 @@ struct mlx4_ts_cqe {
 } __packed;
 
 enum {
+       MLX4_CQE_L2_TUNNEL_IPOK         = 1 << 31,
        MLX4_CQE_VLAN_PRESENT_MASK      = 1 << 29,
+       MLX4_CQE_L2_TUNNEL              = 1 << 27,
+       MLX4_CQE_L2_TUNNEL_CSUM         = 1 << 26,
+       MLX4_CQE_L2_TUNNEL_IPV4         = 1 << 25,
+
        MLX4_CQE_QPN_MASK               = 0xffffff,
 };
 
index 294b7c58fe95eb952fbfd983304801940be39daf..c99ecf6d2c675f53dc127058638ea5f9d501cb8d 100644 (file)
@@ -118,6 +118,11 @@ static inline const char *mlx4_steering_mode_str(int steering_mode)
        }
 }
 
+enum {
+       MLX4_TUNNEL_OFFLOAD_MODE_NONE,
+       MLX4_TUNNEL_OFFLOAD_MODE_VXLAN
+};
+
 enum {
        MLX4_DEV_CAP_FLAG_RC            = 1LL <<  0,
        MLX4_DEV_CAP_FLAG_UC            = 1LL <<  1,
@@ -160,7 +165,8 @@ enum {
        MLX4_DEV_CAP_FLAG2_TS                   = 1LL <<  5,
        MLX4_DEV_CAP_FLAG2_VLAN_CONTROL         = 1LL <<  6,
        MLX4_DEV_CAP_FLAG2_FSM                  = 1LL <<  7,
-       MLX4_DEV_CAP_FLAG2_UPDATE_QP            = 1LL <<  8
+       MLX4_DEV_CAP_FLAG2_UPDATE_QP            = 1LL <<  8,
+       MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS       = 1LL <<  9
 };
 
 enum {
@@ -455,6 +461,7 @@ struct mlx4_caps {
        u32                     function_caps;  /* VFs must be aware of these */
        u16                     hca_core_clock;
        u64                     phys_port_id[MLX4_MAX_PORTS + 1];
+       int                     tunnel_offload_mode;
 };
 
 struct mlx4_buf_list {
@@ -909,6 +916,7 @@ enum mlx4_net_trans_rule_id {
        MLX4_NET_TRANS_RULE_ID_IPV4,
        MLX4_NET_TRANS_RULE_ID_TCP,
        MLX4_NET_TRANS_RULE_ID_UDP,
+       MLX4_NET_TRANS_RULE_ID_VXLAN,
        MLX4_NET_TRANS_RULE_NUM, /* should be last */
 };
 
@@ -966,6 +974,12 @@ struct mlx4_spec_ib {
        u8      dst_gid_msk[16];
 };
 
+struct mlx4_spec_vxlan {
+       __be32 vni;
+       __be32 vni_mask;
+
+};
+
 struct mlx4_spec_list {
        struct  list_head list;
        enum    mlx4_net_trans_rule_id id;
@@ -974,6 +988,7 @@ struct mlx4_spec_list {
                struct mlx4_spec_ib ib;
                struct mlx4_spec_ipv4 ipv4;
                struct mlx4_spec_tcp_udp tcp_udp;
+               struct mlx4_spec_vxlan vxlan;
        };
 };
 
@@ -1060,6 +1075,15 @@ struct mlx4_net_trans_rule_hw_ipv4 {
        __be32  src_ip_msk;
 } __packed;
 
+struct mlx4_net_trans_rule_hw_vxlan {
+       u8      size;
+       u8      rsvd;
+       __be16  id;
+       __be32  rsvd1;
+       __be32  vni;
+       __be32  vni_mask;
+} __packed;
+
 struct _rule_hw {
        union {
                struct {
@@ -1071,9 +1095,19 @@ struct _rule_hw {
                struct mlx4_net_trans_rule_hw_ib ib;
                struct mlx4_net_trans_rule_hw_ipv4 ipv4;
                struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp;
+               struct mlx4_net_trans_rule_hw_vxlan vxlan;
        };
 };
 
+enum {
+       VXLAN_STEER_BY_OUTER_MAC        = 1 << 0,
+       VXLAN_STEER_BY_OUTER_VLAN       = 1 << 1,
+       VXLAN_STEER_BY_VSID_VNI         = 1 << 2,
+       VXLAN_STEER_BY_INNER_MAC        = 1 << 3,
+       VXLAN_STEER_BY_INNER_VLAN       = 1 << 4,
+};
+
+
 int mlx4_flow_steer_promisc_add(struct mlx4_dev *dev, u8 port, u32 qpn,
                                enum mlx4_net_trans_promisc_mode mode);
 int mlx4_flow_steer_promisc_remove(struct mlx4_dev *dev, u8 port,
@@ -1096,6 +1130,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
 int mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc);
 int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
                u8 *pg, u16 *ratelimit);
+int mlx4_SET_PORT_VXLAN(struct mlx4_dev *dev, u8 port, u8 steering);
 int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
 void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
index 6d351473c29200526a98bbbf275b479f79cfa146..59f8ba84568bef4a4e17ed21240c163d6953a912 100644 (file)
@@ -109,6 +109,10 @@ enum {
        MLX4_RSS_TCP_IPV4                       = 1 << 4,
        MLX4_RSS_IPV4                           = 1 << 5,
 
+       MLX4_RSS_BY_OUTER_HEADERS               = 0 << 6,
+       MLX4_RSS_BY_INNER_HEADERS               = 2 << 6,
+       MLX4_RSS_BY_INNER_HEADERS_IPONLY        = 3 << 6,
+
        /* offset of mlx4_rss_context within mlx4_qp_context.pri_path */
        MLX4_RSS_OFFSET_IN_QPC_PRI_PATH         = 0x24,
        /* offset of being RSS indirection QP within mlx4_qp_context.flags */
@@ -252,6 +256,8 @@ enum { /* param3 */
 
 enum {
        MLX4_WQE_CTRL_NEC               = 1 << 29,
+       MLX4_WQE_CTRL_IIP               = 1 << 28,
+       MLX4_WQE_CTRL_ILP               = 1 << 27,
        MLX4_WQE_CTRL_FENCE             = 1 << 6,
        MLX4_WQE_CTRL_CQ_UPDATE         = 3 << 2,
        MLX4_WQE_CTRL_SOLICITED         = 1 << 1,
index 1cedd000cf293f4486575b87086b01e2ee1b26e5..35527173cf50c71baeba5f549007c5903bc8ea06 100644 (file)
@@ -1317,7 +1317,7 @@ static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long a
 #endif /* CONFIG_MMU && !__ARCH_HAS_4LEVEL_HACK */
 
 #if USE_SPLIT_PTE_PTLOCKS
-#if BLOATED_SPINLOCKS
+#if ALLOC_SPLIT_PTLOCKS
 extern bool ptlock_alloc(struct page *page);
 extern void ptlock_free(struct page *page);
 
@@ -1325,7 +1325,7 @@ static inline spinlock_t *ptlock_ptr(struct page *page)
 {
        return page->ptl;
 }
-#else /* BLOATED_SPINLOCKS */
+#else /* ALLOC_SPLIT_PTLOCKS */
 static inline bool ptlock_alloc(struct page *page)
 {
        return true;
@@ -1339,7 +1339,7 @@ static inline spinlock_t *ptlock_ptr(struct page *page)
 {
        return &page->ptl;
 }
-#endif /* BLOATED_SPINLOCKS */
+#endif /* ALLOC_SPLIT_PTLOCKS */
 
 static inline spinlock_t *pte_lockptr(struct mm_struct *mm, pmd_t *pmd)
 {
index bd299418a934e21b99c303af82a7c2f427bbf915..290901a8c1de9f0193ae3e2c640c070623431081 100644 (file)
@@ -26,6 +26,7 @@ struct address_space;
 #define USE_SPLIT_PTE_PTLOCKS  (NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS)
 #define USE_SPLIT_PMD_PTLOCKS  (USE_SPLIT_PTE_PTLOCKS && \
                IS_ENABLED(CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK))
+#define ALLOC_SPLIT_PTLOCKS    (SPINLOCK_SIZE > BITS_PER_LONG/8)
 
 /*
  * Each physical page in the system has a struct page associated with
@@ -155,7 +156,7 @@ struct page {
                                                 * system if PG_buddy is set.
                                                 */
 #if USE_SPLIT_PTE_PTLOCKS
-#if BLOATED_SPINLOCKS
+#if ALLOC_SPLIT_PTLOCKS
                spinlock_t *ptl;
 #else
                spinlock_t ptl;
@@ -442,6 +443,14 @@ struct mm_struct {
 
        /* numa_scan_seq prevents two threads setting pte_numa */
        int numa_scan_seq;
+#endif
+#if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
+       /*
+        * An operation with batched TLB flushing is going on. Anything that
+        * can move process memory needs to flush the TLB when moving a
+        * PROT_NONE or PROT_NUMA mapped page.
+        */
+       bool tlb_flush_pending;
 #endif
        struct uprobes_state uprobes_state;
 };
@@ -459,4 +468,45 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm)
        return mm->cpu_vm_mask_var;
 }
 
+#if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
+/*
+ * Memory barriers to keep this state in sync are graciously provided by
+ * the page table locks, outside of which no page table modifications happen.
+ * The barriers below prevent the compiler from re-ordering the instructions
+ * around the memory barriers that are already present in the code.
+ */
+static inline bool mm_tlb_flush_pending(struct mm_struct *mm)
+{
+       barrier();
+       return mm->tlb_flush_pending;
+}
+static inline void set_tlb_flush_pending(struct mm_struct *mm)
+{
+       mm->tlb_flush_pending = true;
+
+       /*
+        * Guarantee that the tlb_flush_pending store does not leak into the
+        * critical section updating the page tables
+        */
+       smp_mb__before_spinlock();
+}
+/* Clearing is done after a TLB flush, which also provides a barrier. */
+static inline void clear_tlb_flush_pending(struct mm_struct *mm)
+{
+       barrier();
+       mm->tlb_flush_pending = false;
+}
+#else
+static inline bool mm_tlb_flush_pending(struct mm_struct *mm)
+{
+       return false;
+}
+static inline void set_tlb_flush_pending(struct mm_struct *mm)
+{
+}
+static inline void clear_tlb_flush_pending(struct mm_struct *mm)
+{
+}
+#endif
+
 #endif /* _LINUX_MM_TYPES_H */
index 9f03feedc8e71e044e66f60f3cf7c3b863676ad4..d8836623f36afcbd0aa88949c27a9f3c7000fa38 100644 (file)
 /*
  * Vendors and devices.  Sort key: vendor first, device next.
  */
+#define SDIO_VENDOR_ID_BROADCOM                        0x02d0
+#define SDIO_DEVICE_ID_BROADCOM_43143          43143
+#define SDIO_DEVICE_ID_BROADCOM_43241          0x4324
+#define SDIO_DEVICE_ID_BROADCOM_4329           0x4329
+#define SDIO_DEVICE_ID_BROADCOM_4330           0x4330
+#define SDIO_DEVICE_ID_BROADCOM_4334           0x4334
+#define SDIO_DEVICE_ID_BROADCOM_4335_4339      0x4335
+#define SDIO_DEVICE_ID_BROADCOM_43362          43362
+
 #define SDIO_VENDOR_ID_INTEL                   0x0089
 #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX     0x1402
 #define SDIO_DEVICE_ID_INTEL_IWMC3200WIFI      0x1403
index 88afa8048a7c27d0712b636316ba78f46da1bb93..a2a70cc70e7b0643b69a9b180907f190c25133b1 100644 (file)
@@ -1409,7 +1409,7 @@ struct net_device {
        union {
                void                            *ml_priv;
                struct pcpu_lstats __percpu     *lstats; /* loopback stats */
-               struct pcpu_tstats __percpu     *tstats; /* tunnel stats */
+               struct pcpu_sw_netstats __percpu        *tstats;
                struct pcpu_dstats __percpu     *dstats; /* dummy stats */
                struct pcpu_vstats __percpu     *vstats; /* veth stats */
        };
@@ -1444,7 +1444,7 @@ struct net_device {
        /* max exchange id for FCoE LRO by ddp */
        unsigned int            fcoe_ddp_xid;
 #endif
-#if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
+#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
        struct netprio_map __rcu *priomap;
 #endif
        /* phy device may attach itself for hardware timestamping */
@@ -1632,7 +1632,10 @@ struct napi_gro_cb {
        int data_offset;
 
        /* This is non-zero if the packet cannot be merged with the new skb. */
-       int flush;
+       u16     flush;
+
+       /* Save the IP ID here and check when we get to the transport layer */
+       u16     flush_id;
 
        /* Number of segments aggregated. */
        u16     count;
@@ -1651,6 +1654,9 @@ struct napi_gro_cb {
        /* Used in ipv6_gro_receive() */
        int     proto;
 
+       /* used to support CHECKSUM_COMPLETE for tunneling protocols */
+       __wsum  csum;
+
        /* used in skb_gro_receive() slow path */
        struct sk_buff *last;
 };
@@ -1685,6 +1691,15 @@ struct packet_offload {
        struct list_head         list;
 };
 
+/* often modified stats are per cpu, other are shared (netdev->stats) */
+struct pcpu_sw_netstats {
+       u64     rx_packets;
+       u64     rx_bytes;
+       u64     tx_packets;
+       u64     tx_bytes;
+       struct u64_stats_sync   syncp;
+};
+
 #include <linux/notifier.h>
 
 /* netdevice notifier chain. Please remember to update the rtnetlink
@@ -1741,8 +1756,6 @@ netdev_notifier_info_to_dev(const struct netdev_notifier_info *info)
        return info->dev;
 }
 
-int call_netdevice_notifiers_info(unsigned long val, struct net_device *dev,
-                                 struct netdev_notifier_info *info);
 int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
 
 
@@ -1809,7 +1822,6 @@ void dev_remove_pack(struct packet_type *pt);
 void __dev_remove_pack(struct packet_type *pt);
 void dev_add_offload(struct packet_offload *po);
 void dev_remove_offload(struct packet_offload *po);
-void __dev_remove_offload(struct packet_offload *po);
 
 struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short flags,
                                        unsigned short mask);
@@ -1894,6 +1906,14 @@ static inline void *skb_gro_network_header(struct sk_buff *skb)
               skb_network_offset(skb);
 }
 
+static inline void skb_gro_postpull_rcsum(struct sk_buff *skb,
+                                       const void *start, unsigned int len)
+{
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               NAPI_GRO_CB(skb)->csum = csum_sub(NAPI_GRO_CB(skb)->csum,
+                                                 csum_partial(start, len, 0));
+}
+
 static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
                                  unsigned short type,
                                  const void *daddr, const void *saddr,
@@ -1915,6 +1935,15 @@ static inline int dev_parse_header(const struct sk_buff *skb,
        return dev->header_ops->parse(skb, haddr);
 }
 
+static inline int dev_rebuild_header(struct sk_buff *skb)
+{
+       const struct net_device *dev = skb->dev;
+
+       if (!dev->header_ops || !dev->header_ops->rebuild)
+               return 0;
+       return dev->header_ops->rebuild(skb);
+}
+
 typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
 int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
 static inline int unregister_gifconf(unsigned int family)
@@ -2425,6 +2454,8 @@ gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb);
 void napi_gro_flush(struct napi_struct *napi, bool flush_old);
 struct sk_buff *napi_get_frags(struct napi_struct *napi);
 gro_result_t napi_gro_frags(struct napi_struct *napi);
+struct packet_offload *gro_find_receive_by_type(__be16 type);
+struct packet_offload *gro_find_complete_by_type(__be16 type);
 
 static inline void napi_free_frags(struct napi_struct *napi)
 {
@@ -2867,7 +2898,6 @@ extern int                weight_p;
 extern int             bpf_jit_enable;
 
 bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev);
-bool netdev_has_any_upper_dev(struct net_device *dev);
 struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
                                                     struct list_head **iter);
 
@@ -2907,8 +2937,6 @@ int netdev_master_upper_dev_link_private(struct net_device *dev,
                                         void *private);
 void netdev_upper_dev_unlink(struct net_device *dev,
                             struct net_device *upper_dev);
-void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
-                                      struct net_device *lower_dev);
 void *netdev_lower_dev_get_private(struct net_device *dev,
                                   struct net_device *lower_dev);
 int skb_checksum_help(struct sk_buff *skb);
@@ -3036,6 +3064,19 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
        dev->gso_max_size = size;
 }
 
+static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
+                                       int pulled_hlen, u16 mac_offset,
+                                       int mac_len)
+{
+       skb->protocol = protocol;
+       skb->encapsulation = 1;
+       skb_push(skb, pulled_hlen);
+       skb_reset_transport_header(skb);
+       skb->mac_header = mac_offset;
+       skb->network_header = skb->mac_header + mac_len;
+       skb->mac_len = mac_len;
+}
+
 static inline bool netif_is_macvlan(struct net_device *dev)
 {
        return dev->priv_flags & IFF_MACVLAN;
index c7174b8166749501739684d2a938b031b9d4784d..0c7d01eae56cf8626d2d1fc55242b3cbae0ba1ad 100644 (file)
@@ -331,7 +331,6 @@ extern ip_set_id_t ip_set_get_byname(struct net *net,
                                     const char *name, struct ip_set **set);
 extern void ip_set_put_byindex(struct net *net, ip_set_id_t index);
 extern const char *ip_set_name_byindex(struct net *net, ip_set_id_t index);
-extern ip_set_id_t ip_set_nfnl_get(struct net *net, const char *name);
 extern ip_set_id_t ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index);
 extern void ip_set_nfnl_put(struct net *net, ip_set_id_t index);
 
index 7a6c396a263bfff866f28f0ae9bbd6bc48003028..aad8eeaf416d4bbf6d7ae6a4b40a27d4c346f1c4 100644 (file)
@@ -62,7 +62,6 @@ extern void netlink_kernel_release(struct sock *sk);
 extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
 extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
 extern void __netlink_clear_multicast_users(struct sock *sk, unsigned int group);
-extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group);
 extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
 extern int netlink_has_listeners(struct sock *sk, unsigned int group);
 extern struct sk_buff *netlink_alloc_skb(struct sock *ssk, unsigned int size,
@@ -168,7 +167,6 @@ struct netlink_tap {
 };
 
 extern int netlink_add_tap(struct netlink_tap *nt);
-extern int __netlink_remove_tap(struct netlink_tap *nt);
 extern int netlink_remove_tap(struct netlink_tap *nt);
 
 #endif /* __LINUX_NETLINK_H */
index 8163107b94b4ebacd0c0080e168b6920b068b469..6fe8464ed767f0dac6481a6ffc7b39ecaebdd648 100644 (file)
@@ -19,6 +19,9 @@ extern struct phy_device *of_phy_connect(struct net_device *dev,
                                         struct device_node *phy_np,
                                         void (*hndlr)(struct net_device *),
                                         u32 flags, phy_interface_t iface);
+struct phy_device *of_phy_attach(struct net_device *dev,
+                                struct device_node *phy_np, u32 flags,
+                                phy_interface_t iface);
 extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
                                         void (*hndlr)(struct net_device *),
                                         phy_interface_t iface);
@@ -44,6 +47,13 @@ static inline struct phy_device *of_phy_connect(struct net_device *dev,
        return NULL;
 }
 
+static inline struct phy_device *of_phy_attach(struct net_device *dev,
+                                              struct device_node *phy_np,
+                                              u32 flags, phy_interface_t iface)
+{
+       return NULL;
+}
+
 static inline struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
                                                           void (*hndlr)(struct net_device *),
                                                           phy_interface_t iface)
index 57e890abe1f09220c777b5403c782cd6792872d6..a5fc7d01aad61049164f920f90a6f20df1cbc22d 100644 (file)
@@ -69,6 +69,7 @@
        __PCPU_DUMMY_ATTRS char __pcpu_scope_##name;                    \
        extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;            \
        __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;                   \
+       extern __PCPU_ATTRS(sec) __typeof__(type) name;                 \
        __PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak                 \
        __typeof__(type) name
 #else
index 73384ff3b5e50550bd5b705c3023133708dcee96..565188ca328f31841a4c8b718db2c4fd08238278 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * include/linux/phy.h
- *
  * Framework and drivers for configuring and reading different PHYs
  * Based on code in sungem_phy.c and gianfar_phy.c
  *
@@ -75,6 +73,7 @@ typedef enum {
        PHY_INTERFACE_MODE_RGMII_TXID,
        PHY_INTERFACE_MODE_RTBI,
        PHY_INTERFACE_MODE_SMII,
+       PHY_INTERFACE_MODE_XGMII,
 } phy_interface_t;
 
 
@@ -240,7 +239,7 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
  * - phy_stop moves to HALTED
  */
 enum phy_state {
-       PHY_DOWN=0,
+       PHY_DOWN = 0,
        PHY_STARTING,
        PHY_READY,
        PHY_PENDING,
@@ -284,8 +283,6 @@ struct phy_c45_device_ids {
  * 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.
- * adjust_state: Callback for the enet driver to respond to
- * changes in the state machine.
  *
  * speed, duplex, pause, supported, advertising, lp_advertising,
  * and autoneg are used like in mii_if_info
@@ -366,8 +363,6 @@ struct phy_device {
        struct net_device *attached_dev;
 
        void (*adjust_link)(struct net_device *dev);
-
-       void (*adjust_state)(struct net_device *dev);
 };
 #define to_phy_device(d) container_of(d, struct phy_device, dev)
 
@@ -493,6 +488,24 @@ struct phy_fixup {
        int (*run)(struct phy_device *phydev);
 };
 
+/**
+ * phy_read_mmd - Convenience function for reading a register
+ * from an MMD on a given PHY.
+ * @phydev: The phy_device struct
+ * @devad: The MMD to read from
+ * @regnum: The register on the MMD to read
+ *
+ * Same rules as for phy_read();
+ */
+static inline int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
+{
+       if (!phydev->is_c45)
+               return -EOPNOTSUPP;
+
+       return mdiobus_read(phydev->bus, phydev->addr,
+                           MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff));
+}
+
 /**
  * phy_read - Convenience function for reading a given PHY register
  * @phydev: the phy_device struct
@@ -543,22 +556,46 @@ static inline bool phy_is_internal(struct phy_device *phydev)
        return phydev->is_internal;
 }
 
+/**
+ * phy_write_mmd - Convenience function for writing a register
+ * on an MMD on a given PHY.
+ * @phydev: The phy_device struct
+ * @devad: The MMD to read from
+ * @regnum: The register on the MMD to read
+ * @val: value to write to @regnum
+ *
+ * Same rules as for phy_write();
+ */
+static inline int phy_write_mmd(struct phy_device *phydev, int devad,
+                               u32 regnum, u16 val)
+{
+       if (!phydev->is_c45)
+               return -EOPNOTSUPP;
+
+       regnum = MII_ADDR_C45 | ((devad & 0x1f) << 16) | (regnum & 0xffff);
+
+       return mdiobus_write(phydev->bus, phydev->addr, regnum, val);
+}
+
 struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
-               bool is_c45, struct phy_c45_device_ids *c45_ids);
+                                    bool is_c45,
+                                    struct phy_c45_device_ids *c45_ids);
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
 int phy_device_register(struct phy_device *phy);
 int phy_init_hw(struct phy_device *phydev);
 int phy_suspend(struct phy_device *phydev);
 int phy_resume(struct phy_device *phydev);
-struct phy_device * phy_attach(struct net_device *dev,
-               const char *bus_id, phy_interface_t interface);
+struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
+                             phy_interface_t interface);
 struct phy_device *phy_find_first(struct mii_bus *bus);
+int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
+                     u32 flags, phy_interface_t interface);
 int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
-               void (*handler)(struct net_device *),
-               phy_interface_t interface);
-struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
-               void (*handler)(struct net_device *),
-               phy_interface_t interface);
+                      void (*handler)(struct net_device *),
+                      phy_interface_t interface);
+struct phy_device *phy_connect(struct net_device *dev, const char *bus_id,
+                              void (*handler)(struct net_device *),
+                              phy_interface_t interface);
 void phy_disconnect(struct phy_device *phydev);
 void phy_detach(struct phy_device *phydev);
 void phy_start(struct phy_device *phydev);
@@ -567,7 +604,8 @@ int phy_start_aneg(struct phy_device *phydev);
 
 int phy_stop_interrupts(struct phy_device *phydev);
 
-static inline int phy_read_status(struct phy_device *phydev) {
+static inline int phy_read_status(struct phy_device *phydev)
+{
        return phydev->drv->read_status(phydev);
 }
 
@@ -585,31 +623,29 @@ int phy_drivers_register(struct phy_driver *new_driver, int n);
 void phy_state_machine(struct work_struct *work);
 void phy_change(struct work_struct *work);
 void phy_mac_interrupt(struct phy_device *phydev, int new_link);
-void phy_start_machine(struct phy_device *phydev,
-               void (*handler)(struct net_device *));
+void phy_start_machine(struct phy_device *phydev);
 void phy_stop_machine(struct phy_device *phydev);
 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
 int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
-int phy_mii_ioctl(struct phy_device *phydev,
-               struct ifreq *ifr, int cmd);
+int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);
 int phy_start_interrupts(struct phy_device *phydev);
 void phy_print_status(struct phy_device *phydev);
 void phy_device_free(struct phy_device *phydev);
 
 int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
-               int (*run)(struct phy_device *));
+                      int (*run)(struct phy_device *));
 int phy_register_fixup_for_id(const char *bus_id,
-               int (*run)(struct phy_device *));
+                             int (*run)(struct phy_device *));
 int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
-               int (*run)(struct phy_device *));
-int phy_scan_fixups(struct phy_device *phydev);
+                              int (*run)(struct phy_device *));
 
 int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
 int phy_get_eee_err(struct phy_device *phydev);
 int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data);
 int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data);
 int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
-void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
+void phy_ethtool_get_wol(struct phy_device *phydev,
+                        struct ethtool_wolinfo *wol);
 
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
index 88af1ac28ead25e878fa357e1e8b4e9f24be20fd..a395159725d5719def01674f3c77c22db8a75823 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/mach-netx/include/mach/eth.h
- *
  * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
  *
  * This program is free software; you can redistribute it and/or modify
@@ -17,8 +15,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef ASMARM_ARCH_ETH_H
-#define ASMARM_ARCH_ETH_H
+#ifndef __ETH_NETX_H
+#define __ETH_NETX_H
 
 struct netxeth_platform_data {
        unsigned int xcno;      /* number of xmac/xpec engine this eth uses */
index 694925837a1645bb7297cc9254efee7173a32197..26fb95ce5080dec51eb9c1f654ac81af87e53a07 100644 (file)
@@ -87,6 +87,13 @@ struct va_format {
  */
 #define HW_ERR         "[Hardware Error]: "
 
+/*
+ * DEPRECATED
+ * Add this to a message whenever you want to warn user space about the use
+ * of a deprecated aspect of an API so they can stop using it
+ */
+#define DEPRECATED     "[Deprecated]: "
+
 /*
  * Dummy printk for disabled debugging statements to use whilst maintaining
  * gcc's format and side-effect checking.
index abd437d0a8a7eeac72297ad5306ca071993d8f58..ece0c6bbfcc5617f394092ec027f39ce3abc629d 100644 (file)
@@ -51,6 +51,7 @@ struct pstore_info {
        char            *buf;
        size_t          bufsize;
        struct mutex    read_mutex;     /* serialize open/read/close */
+       int             flags;
        int             (*open)(struct pstore_info *psi);
        int             (*close)(struct pstore_info *psi);
        ssize_t         (*read)(u64 *id, enum pstore_type_id *type,
@@ -70,6 +71,8 @@ struct pstore_info {
        void            *data;
 };
 
+#define        PSTORE_FLAGS_FRAGILE    1
+
 #ifdef CONFIG_PSTORE
 extern int pstore_register(struct pstore_info *);
 extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
index 8e00f9f6f96395b3e209192259b6af58f7078143..9e7db9e73cc13ffc04d05b02c9c5ea0d877be7e9 100644 (file)
@@ -43,6 +43,7 @@ extern int unregister_reboot_notifier(struct notifier_block *);
  * Architecture-specific implementations of sys_reboot commands.
  */
 
+extern void migrate_to_reboot_cpu(void);
 extern void machine_restart(char *cmd);
 extern void machine_halt(void);
 extern void machine_power_off(void);
index 939428ad25acb506297c1726faaee83d60d047c4..8e3e66ac0a5215d221042e15e631fb2fe2fb51d1 100644 (file)
@@ -24,6 +24,11 @@ extern int rtnl_trylock(void);
 extern int rtnl_is_locked(void);
 #ifdef CONFIG_PROVE_LOCKING
 extern int lockdep_rtnl_is_held(void);
+#else
+static inline int lockdep_rtnl_is_held(void)
+{
+       return 1;
+}
 #endif /* #ifdef CONFIG_PROVE_LOCKING */
 
 /**
index c5cd016f5120a455e995ab2eca36cc7c833134ec..d97f2d07d02b71a967488bd445d2e91dd0b51c58 100644 (file)
@@ -827,7 +827,7 @@ static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb)
  */
 static inline int skb_queue_empty(const struct sk_buff_head *list)
 {
-       return list->next == (struct sk_buff *)list;
+       return list->next == (const struct sk_buff *) list;
 }
 
 /**
@@ -840,7 +840,7 @@ static inline int skb_queue_empty(const struct sk_buff_head *list)
 static inline bool skb_queue_is_last(const struct sk_buff_head *list,
                                     const struct sk_buff *skb)
 {
-       return skb->next == (struct sk_buff *)list;
+       return skb->next == (const struct sk_buff *) list;
 }
 
 /**
@@ -853,7 +853,7 @@ static inline bool skb_queue_is_last(const struct sk_buff_head *list,
 static inline bool skb_queue_is_first(const struct sk_buff_head *list,
                                      const struct sk_buff *skb)
 {
-       return skb->prev == (struct sk_buff *)list;
+       return skb->prev == (const struct sk_buff *) list;
 }
 
 /**
@@ -1715,6 +1715,11 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
        skb->mac_header += offset;
 }
 
+static inline void skb_pop_mac_header(struct sk_buff *skb)
+{
+       skb->mac_header = skb->network_header;
+}
+
 static inline void skb_probe_transport_header(struct sk_buff *skb,
                                              const int offset_hint)
 {
@@ -2440,6 +2445,9 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
                    struct pipe_inode_info *pipe, unsigned int len,
                    unsigned int flags);
 void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
+unsigned int skb_zerocopy_headlen(const struct sk_buff *from);
+void skb_zerocopy(struct sk_buff *to, const struct sk_buff *from,
+                 int len, int hlen);
 void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len);
 int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
 void skb_scrub_packet(struct sk_buff *skb, bool xnet);
@@ -2621,6 +2629,10 @@ static inline void sw_tx_timestamp(struct sk_buff *skb)
  * Ethernet MAC Drivers should call this function in their hard_xmit()
  * function immediately before giving the sk_buff to the MAC hardware.
  *
+ * Specifically, one should make absolutely sure that this function is
+ * called before TX completion of this packet can trigger.  Otherwise
+ * the packet could potentially already be freed.
+ *
  * @skb: A socket buffer.
  */
 static inline void skb_tx_timestamp(struct sk_buff *skb)
index 445ef7519dc28625e7cb19dd698c1918f36b90bf..5d488a65ad20222b780f73838bcde6dabfa37935 100644 (file)
@@ -305,8 +305,6 @@ struct ucred {
 /* IPX options */
 #define IPX_TYPE       1
 
-extern void cred_to_ucred(struct pid *pid, const struct cred *cred, struct ucred *ucred);
-
 extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
                               int offset, int len);
 extern int csum_partial_copy_fromiovecend(unsigned char *kdata, 
index d68633452d9b070ce12056e5a17dc40f1f148c4d..4ad0706d40ebecf98e1ca95483a79f9dd44e903c 100644 (file)
@@ -248,7 +248,10 @@ struct tcp_sock {
        struct sk_buff* lost_skb_hint;
        struct sk_buff *retransmit_skb_hint;
 
-       struct sk_buff_head     out_of_order_queue; /* Out of order segments go here */
+       /* OOO segments go in this list. Note that socket lock must be held,
+        * as we do not use sk_buff_head lock.
+        */
+       struct sk_buff_head     out_of_order_queue;
 
        /* SACKs data, these 2 need to be together (see tcp_options_write) */
        struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
index 77d5d8156efc75cdfb0999513b637be5414e9ef5..e171387512b3cb56277e9cdb21e9e21fb1342ecb 100644 (file)
@@ -39,6 +39,7 @@ struct tcf_hashinfo {
        struct hlist_head       *htab;
        unsigned int            hmask;
        spinlock_t              lock;
+       u32                     index;
 };
 
 static inline unsigned int tcf_hash(u32 index, unsigned int hmask)
@@ -51,6 +52,7 @@ static inline int tcf_hashinfo_init(struct tcf_hashinfo *hf, unsigned int mask)
        int i;
 
        spin_lock_init(&hf->lock);
+       hf->index = 0;
        hf->hmask = mask;
        hf->htab = kzalloc((mask + 1) * sizeof(struct hlist_head),
                           GFP_KERNEL);
@@ -71,10 +73,6 @@ static inline void tcf_hashinfo_destroy(struct tcf_hashinfo *hf)
 #define ACT_P_CREATED 1
 #define ACT_P_DELETED 1
 
-struct tcf_act_hdr {
-       struct tcf_common       common;
-};
-
 struct tc_action {
        void                    *priv;
        const struct tc_action_ops      *ops;
@@ -105,16 +103,12 @@ struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo);
 void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo);
 int tcf_hash_release(struct tcf_common *p, int bind,
                     struct tcf_hashinfo *hinfo);
-int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
-                      int type, struct tc_action *a);
-u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo);
-int tcf_hash_search(struct tc_action *a, u32 index);
+u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo);
 struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a,
                                  int bind, struct tcf_hashinfo *hinfo);
 struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
                                   struct tc_action *a, int size,
-                                  int bind, u32 *idx_gen,
-                                  struct tcf_hashinfo *hinfo);
+                                  int bind, struct tcf_hashinfo *hinfo);
 void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo);
 
 int tcf_register_action(struct tc_action_ops *a);
index 7509d9da4e3631ee9f00fba4d27922ace90cb9ae..73c49864076b3370f015d11616f02c47a2768ff0 100644 (file)
@@ -62,6 +62,5 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
                           const unsigned char *src_hw,
                           const unsigned char *target_hw);
 void arp_xmit(struct sk_buff *skb);
-int arp_invalidate(struct net_device *dev, __be32 ip);
 
 #endif /* _ARP_H */
index cc2da73055fadba14268593a9a7457c44b9f0c78..66c1cd87bfe7f9b9d117db340f736884f9d0c4c1 100644 (file)
@@ -83,7 +83,8 @@
 enum {
        HCI_QUIRK_RESET_ON_CLOSE,
        HCI_QUIRK_RAW_DEVICE,
-       HCI_QUIRK_FIXUP_BUFFER_SIZE
+       HCI_QUIRK_FIXUP_BUFFER_SIZE,
+       HCI_QUIRK_BROKEN_STORED_LINK_KEY,
 };
 
 /* HCI device flags */
@@ -131,6 +132,7 @@ enum {
        HCI_PERIODIC_INQ,
        HCI_FAST_CONNECTABLE,
        HCI_BREDR_ENABLED,
+       HCI_6LOWPAN_ENABLED,
 };
 
 /* A mask for the flags that are supposed to remain when a reset happens
index b796161fb04e8f02b0de6f398fee59d8d464150b..f2f0cf5865c40a9b92f7a98eb4c53c6834a34d29 100644 (file)
@@ -448,6 +448,7 @@ enum {
        HCI_CONN_SSP_ENABLED,
        HCI_CONN_POWER_SAVE,
        HCI_CONN_REMOTE_OOB,
+       HCI_CONN_6LOWPAN,
 };
 
 static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
index e149e992fdae9d9b113b349c1db5d062a72d5971..dbc4a89984ca67287715a8279b2d9793e7d2eebe 100644 (file)
@@ -136,6 +136,7 @@ struct l2cap_conninfo {
 #define L2CAP_FC_L2CAP         0x02
 #define L2CAP_FC_CONNLESS      0x04
 #define L2CAP_FC_A2MP          0x08
+#define L2CAP_FC_6LOWPAN        0x3e /* reserved and temporary value */
 
 /* L2CAP Control Field bit masks */
 #define L2CAP_CTRL_SAR                 0xC000
index e9abc7b536cdebb5434caae1cbd487378ad0dfe1..56c597793d6d380cb90c80c5d17f73fe87a63eb6 100644 (file)
@@ -747,6 +747,8 @@ enum station_parameters_apply_mask {
  * @supported_channels_len: number of supported channels
  * @supported_oper_classes: supported oper classes in IEEE 802.11 format
  * @supported_oper_classes_len: number of supported operating classes
+ * @opmode_notif: operating mode field from Operating Mode Notification
+ * @opmode_notif_used: information if operating mode field is used
  */
 struct station_parameters {
        const u8 *supported_rates;
@@ -770,6 +772,8 @@ struct station_parameters {
        u8 supported_channels_len;
        const u8 *supported_oper_classes;
        u8 supported_oper_classes_len;
+       u8 opmode_notif;
+       bool opmode_notif_used;
 };
 
 /**
@@ -1762,7 +1766,8 @@ enum wiphy_params_flags {
 struct cfg80211_bitrate_mask {
        struct {
                u32 legacy;
-               u8 mcs[IEEE80211_HT_MCS_MASK_LEN];
+               u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN];
+               u16 vht_mcs[NL80211_VHT_NSS_MAX];
        } control[IEEE80211_NUM_BANDS];
 };
 /**
@@ -1966,6 +1971,50 @@ struct cfg80211_mgmt_tx_params {
        bool dont_wait_for_ack;
 };
 
+/**
+ * struct cfg80211_dscp_exception - DSCP exception
+ *
+ * @dscp: DSCP value that does not adhere to the user priority range definition
+ * @up: user priority value to which the corresponding DSCP value belongs
+ */
+struct cfg80211_dscp_exception {
+       u8 dscp;
+       u8 up;
+};
+
+/**
+ * struct cfg80211_dscp_range - DSCP range definition for user priority
+ *
+ * @low: lowest DSCP value of this user priority range, inclusive
+ * @high: highest DSCP value of this user priority range, inclusive
+ */
+struct cfg80211_dscp_range {
+       u8 low;
+       u8 high;
+};
+
+/* QoS Map Set element length defined in IEEE Std 802.11-2012, 8.4.2.97 */
+#define IEEE80211_QOS_MAP_MAX_EX       21
+#define IEEE80211_QOS_MAP_LEN_MIN      16
+#define IEEE80211_QOS_MAP_LEN_MAX \
+       (IEEE80211_QOS_MAP_LEN_MIN + 2 * IEEE80211_QOS_MAP_MAX_EX)
+
+/**
+ * struct cfg80211_qos_map - QoS Map Information
+ *
+ * This struct defines the Interworking QoS map setting for DSCP values
+ *
+ * @num_des: number of DSCP exceptions (0..21)
+ * @dscp_exception: optionally up to maximum of 21 DSCP exceptions from
+ *     the user priority DSCP range definition
+ * @up: DSCP range definition for a particular user priority
+ */
+struct cfg80211_qos_map {
+       u8 num_des;
+       struct cfg80211_dscp_exception dscp_exception[IEEE80211_QOS_MAP_MAX_EX];
+       struct cfg80211_dscp_range up[8];
+};
+
 /**
  * struct cfg80211_ops - backend description for wireless configuration
  *
@@ -2208,6 +2257,8 @@ struct cfg80211_mgmt_tx_params {
  * @set_coalesce: Set coalesce parameters.
  *
  * @channel_switch: initiate channel-switch procedure (with CSA)
+ *
+ * @set_qos_map: Set QoS mapping information to the driver
  */
 struct cfg80211_ops {
        int     (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2449,6 +2500,9 @@ struct cfg80211_ops {
        int     (*channel_switch)(struct wiphy *wiphy,
                                  struct net_device *dev,
                                  struct cfg80211_csa_settings *params);
+       int     (*set_qos_map)(struct wiphy *wiphy,
+                              struct net_device *dev,
+                              struct cfg80211_qos_map *qos_map);
 };
 
 /*
@@ -2675,6 +2729,34 @@ struct wiphy_coalesce_support {
        int max_pkt_offset;
 };
 
+/**
+ * enum wiphy_vendor_command_flags - validation flags for vendor commands
+ * @WIPHY_VENDOR_CMD_NEED_WDEV: vendor command requires wdev
+ * @WIPHY_VENDOR_CMD_NEED_NETDEV: vendor command requires netdev
+ * @WIPHY_VENDOR_CMD_NEED_RUNNING: interface/wdev must be up & running
+ *     (must be combined with %_WDEV or %_NETDEV)
+ */
+enum wiphy_vendor_command_flags {
+       WIPHY_VENDOR_CMD_NEED_WDEV = BIT(0),
+       WIPHY_VENDOR_CMD_NEED_NETDEV = BIT(1),
+       WIPHY_VENDOR_CMD_NEED_RUNNING = BIT(2),
+};
+
+/**
+ * struct wiphy_vendor_command - vendor command definition
+ * @info: vendor command identifying information, as used in nl80211
+ * @flags: flags, see &enum wiphy_vendor_command_flags
+ * @doit: callback for the operation, note that wdev is %NULL if the
+ *     flags didn't ask for a wdev and non-%NULL otherwise; the data
+ *     pointer may be %NULL if userspace provided no data at all
+ */
+struct wiphy_vendor_command {
+       struct nl80211_vendor_cmd_info info;
+       u32 flags;
+       int (*doit)(struct wiphy *wiphy, struct wireless_dev *wdev,
+                   const void *data, int data_len);
+};
+
 /**
  * struct wiphy - wireless hardware description
  * @reg_notifier: the driver's regulatory notification callback,
@@ -2788,6 +2870,11 @@ struct wiphy_coalesce_support {
  * @extended_capabilities_mask: mask of the valid values
  * @extended_capabilities_len: length of the extended capabilities
  * @coalesce: packet coalescing support information
+ *
+ * @vendor_commands: array of vendor commands supported by the hardware
+ * @n_vendor_commands: number of vendor commands
+ * @vendor_events: array of vendor events supported by the hardware
+ * @n_vendor_events: number of vendor events
  */
 struct wiphy {
        /* assign these fields before you register the wiphy */
@@ -2899,6 +2986,10 @@ struct wiphy {
 
        const struct wiphy_coalesce_support *coalesce;
 
+       const struct wiphy_vendor_command *vendor_commands;
+       const struct nl80211_vendor_cmd_info *vendor_events;
+       int n_vendor_commands, n_vendor_events;
+
        char priv[0] __aligned(NETDEV_ALIGN);
 };
 
@@ -3390,9 +3481,11 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 /**
  * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
  * @skb: the data frame
+ * @qos_map: Interworking QoS mapping or %NULL if not in use
  * Return: The 802.1p/1d tag.
  */
-unsigned int cfg80211_classify8021d(struct sk_buff *skb);
+unsigned int cfg80211_classify8021d(struct sk_buff *skb,
+                                   struct cfg80211_qos_map *qos_map);
 
 /**
  * cfg80211_find_ie - find information element in data
@@ -3843,6 +3936,121 @@ void wiphy_rfkill_start_polling(struct wiphy *wiphy);
  */
 void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
 
+/**
+ * DOC: Vendor commands
+ *
+ * Occasionally, there are special protocol or firmware features that
+ * can't be implemented very openly. For this and similar cases, the
+ * vendor command functionality allows implementing the features with
+ * (typically closed-source) userspace and firmware, using nl80211 as
+ * the configuration mechanism.
+ *
+ * A driver supporting vendor commands must register them as an array
+ * in struct wiphy, with handlers for each one, each command has an
+ * OUI and sub command ID to identify it.
+ *
+ * Note that this feature should not be (ab)used to implement protocol
+ * features that could openly be shared across drivers. In particular,
+ * it must never be required to use vendor commands to implement any
+ * "normal" functionality that higher-level userspace like connection
+ * managers etc. need.
+ */
+
+struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
+                                          enum nl80211_commands cmd,
+                                          enum nl80211_attrs attr,
+                                          int approxlen);
+
+struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
+                                          enum nl80211_commands cmd,
+                                          enum nl80211_attrs attr,
+                                          int vendor_event_idx,
+                                          int approxlen, gfp_t gfp);
+
+void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp);
+
+/**
+ * cfg80211_vendor_cmd_alloc_reply_skb - allocate vendor command reply
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ *     be put into the skb
+ *
+ * This function allocates and pre-fills an skb for a reply to
+ * a vendor command. Since it is intended for a reply, calling
+ * it outside of a vendor command's doit() operation is invalid.
+ *
+ * The returned skb is pre-filled with some identifying data in
+ * a way that any data that is put into the skb (with skb_put(),
+ * nla_put() or similar) will end up being within the
+ * %NL80211_ATTR_VENDOR_DATA attribute, so all that needs to be done
+ * with the skb is adding data for the corresponding userspace tool
+ * which can then read that data out of the vendor data attribute.
+ * You must not modify the skb in any other way.
+ *
+ * When done, call cfg80211_vendor_cmd_reply() with the skb and return
+ * its error code as the result of the doit() operation.
+ *
+ * Return: An allocated and pre-filled skb. %NULL if any errors happen.
+ */
+static inline struct sk_buff *
+cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int approxlen)
+{
+       return __cfg80211_alloc_reply_skb(wiphy, NL80211_CMD_VENDOR,
+                                         NL80211_ATTR_VENDOR_DATA, approxlen);
+}
+
+/**
+ * cfg80211_vendor_cmd_reply - send the reply skb
+ * @skb: The skb, must have been allocated with
+ *     cfg80211_vendor_cmd_alloc_reply_skb()
+ *
+ * Since calling this function will usually be the last thing
+ * before returning from the vendor command doit() you should
+ * return the error code.  Note that this function consumes the
+ * skb regardless of the return value.
+ *
+ * Return: An error code or 0 on success.
+ */
+int cfg80211_vendor_cmd_reply(struct sk_buff *skb);
+
+/**
+ * cfg80211_vendor_event_alloc - allocate vendor-specific event skb
+ * @wiphy: the wiphy
+ * @event_idx: index of the vendor event in the wiphy's vendor_events
+ * @approxlen: an upper bound of the length of the data that will
+ *     be put into the skb
+ * @gfp: allocation flags
+ *
+ * This function allocates and pre-fills an skb for an event on the
+ * vendor-specific multicast group.
+ *
+ * When done filling the skb, call cfg80211_vendor_event() with the
+ * skb to send the event.
+ *
+ * Return: An allocated and pre-filled skb. %NULL if any errors happen.
+ */
+static inline struct sk_buff *
+cfg80211_vendor_event_alloc(struct wiphy *wiphy, int approxlen,
+                           int event_idx, gfp_t gfp)
+{
+       return __cfg80211_alloc_event_skb(wiphy, NL80211_CMD_VENDOR,
+                                         NL80211_ATTR_VENDOR_DATA,
+                                         event_idx, approxlen, gfp);
+}
+
+/**
+ * cfg80211_vendor_event - send the event
+ * @skb: The skb, must have been allocated with cfg80211_vendor_event_alloc()
+ * @gfp: allocation flags
+ *
+ * This function sends the given @skb, which must have been allocated
+ * by cfg80211_vendor_event_alloc(), as an event. It always consumes it.
+ */
+static inline void cfg80211_vendor_event(struct sk_buff *skb, gfp_t gfp)
+{
+       __cfg80211_send_event_skb(skb, gfp);
+}
+
 #ifdef CONFIG_NL80211_TESTMODE
 /**
  * DOC: Test mode
@@ -3878,8 +4086,12 @@ void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
  *
  * Return: An allocated and pre-filled skb. %NULL if any errors happen.
  */
-struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
-                                                 int approxlen);
+static inline struct sk_buff *
+cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, int approxlen)
+{
+       return __cfg80211_alloc_reply_skb(wiphy, NL80211_CMD_TESTMODE,
+                                         NL80211_ATTR_TESTDATA, approxlen);
+}
 
 /**
  * cfg80211_testmode_reply - send the reply skb
@@ -3893,7 +4105,10 @@ struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
  *
  * Return: An error code or 0 on success.
  */
-int cfg80211_testmode_reply(struct sk_buff *skb);
+static inline int cfg80211_testmode_reply(struct sk_buff *skb)
+{
+       return cfg80211_vendor_cmd_reply(skb);
+}
 
 /**
  * cfg80211_testmode_alloc_event_skb - allocate testmode event
@@ -3916,8 +4131,13 @@ int cfg80211_testmode_reply(struct sk_buff *skb);
  *
  * Return: An allocated and pre-filled skb. %NULL if any errors happen.
  */
-struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
-                                                 int approxlen, gfp_t gfp);
+static inline struct sk_buff *
+cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, int approxlen, gfp_t gfp)
+{
+       return __cfg80211_alloc_event_skb(wiphy, NL80211_CMD_TESTMODE,
+                                         NL80211_ATTR_TESTDATA, -1,
+                                         approxlen, gfp);
+}
 
 /**
  * cfg80211_testmode_event - send the event
@@ -3929,7 +4149,10 @@ struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
  * by cfg80211_testmode_alloc_event_skb(), as an event. It always
  * consumes it.
  */
-void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp);
+static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
+{
+       __cfg80211_send_event_skb(skb, gfp);
+}
 
 #define CFG80211_TESTMODE_CMD(cmd)     .testmode_cmd = (cmd),
 #define CFG80211_TESTMODE_DUMP(cmd)    .testmode_dump = (cmd),
index 33d03b648646ce04114c73c65853a0b19b548fa4..9cf2d5ef38d967ad7d67202bbd82f3bd933a31dd 100644 (file)
 #include <linux/cgroup.h>
 #include <linux/hardirq.h>
 #include <linux/rcupdate.h>
+#include <net/sock.h>
 
-#if IS_ENABLED(CONFIG_NET_CLS_CGROUP)
-struct cgroup_cls_state
-{
+#ifdef CONFIG_CGROUP_NET_CLASSID
+struct cgroup_cls_state {
        struct cgroup_subsys_state css;
        u32 classid;
 };
 
-void sock_update_classid(struct sock *sk);
+struct cgroup_cls_state *task_cls_state(struct task_struct *p);
 
-#if IS_BUILTIN(CONFIG_NET_CLS_CGROUP)
 static inline u32 task_cls_classid(struct task_struct *p)
 {
        u32 classid;
@@ -41,33 +40,18 @@ static inline u32 task_cls_classid(struct task_struct *p)
 
        return classid;
 }
-#elif IS_MODULE(CONFIG_NET_CLS_CGROUP)
-static inline u32 task_cls_classid(struct task_struct *p)
-{
-       struct cgroup_subsys_state *css;
-       u32 classid = 0;
-
-       if (in_interrupt())
-               return 0;
-
-       rcu_read_lock();
-       css = task_css(p, net_cls_subsys_id);
-       if (css)
-               classid = container_of(css,
-                                      struct cgroup_cls_state, css)->classid;
-       rcu_read_unlock();
 
-       return classid;
-}
-#endif
-#else /* !CGROUP_NET_CLS_CGROUP */
 static inline void sock_update_classid(struct sock *sk)
 {
-}
+       u32 classid;
 
-static inline u32 task_cls_classid(struct task_struct *p)
+       classid = task_cls_classid(current);
+       if (classid != sk->sk_classid)
+               sk->sk_classid = classid;
+}
+#else /* !CONFIG_CGROUP_NET_CLASSID */
+static inline void sock_update_classid(struct sock *sk)
 {
-       return 0;
 }
-#endif /* CGROUP_NET_CLS_CGROUP */
+#endif /* CONFIG_CGROUP_NET_CLASSID */
 #endif  /* _NET_CLS_CGROUP_H */
index 1b177ed803b7aa99045fec46e6449b29b76ac323..93695f0e22a54a7e4fa16f6934b1e085e75e1a7b 100644 (file)
@@ -73,6 +73,7 @@ struct genl_family {
  * @attrs: netlink attributes
  * @_net: network namespace
  * @user_ptr: user pointers
+ * @dst_sk: destination socket
  */
 struct genl_info {
        u32                     snd_seq;
@@ -85,6 +86,7 @@ struct genl_info {
        struct net *            _net;
 #endif
        void *                  user_ptr[2];
+       struct sock *           dst_sk;
 };
 
 static inline struct net *genl_info_net(struct genl_info *info)
@@ -177,6 +179,8 @@ void genl_notify(struct genl_family *family,
                 struct sk_buff *skb, struct net *net, u32 portid,
                 u32 group, struct nlmsghdr *nlh, gfp_t flags);
 
+struct sk_buff *genlmsg_new_unicast(size_t payload, struct genl_info *info,
+                                   gfp_t flags);
 void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
                  struct genl_family *family, int flags, u8 cmd);
 
index dcd9ae3270d386b06d7565cfb8b7c4bb59dde740..70046a0b0b89c13d0f71f6180ed64e7dacf869e6 100644 (file)
@@ -33,9 +33,6 @@ struct gre_cisco_protocol {
 int gre_cisco_register(struct gre_cisco_protocol *proto);
 int gre_cisco_unregister(struct gre_cisco_protocol *proto);
 
-int gre_offload_init(void);
-void gre_offload_exit(void);
-
 void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
                      int hdr_len);
 
index f4e127af4e179dd022007ed4a416ab32c9146533..6efe73c79c526d5ebb0cddc09cd45df41aee73cb 100644 (file)
@@ -163,7 +163,6 @@ void inet_putpeer(struct inet_peer *p);
 bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
 
 void inetpeer_invalidate_tree(struct inet_peer_base *);
-void inetpeer_invalidate_family(int family);
 
 /*
  * temporary check to make sure we dont access rid, ip_id_count, tcp_ts,
index 535664477c4a0d339f6ba92051aa3bd9cd1f7dd5..0dab95c2e4d59f096f481456581b931718216fff 100644 (file)
@@ -263,6 +263,39 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
                 !(dst_metric_locked(dst, RTAX_MTU)));
 }
 
+static inline bool ip_sk_accept_pmtu(const struct sock *sk)
+{
+       return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE;
+}
+
+static inline bool ip_sk_use_pmtu(const struct sock *sk)
+{
+       return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE;
+}
+
+static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
+                                                   bool forwarding)
+{
+       struct net *net = dev_net(dst->dev);
+
+       if (net->ipv4.sysctl_ip_fwd_use_pmtu ||
+           dst_metric_locked(dst, RTAX_MTU) ||
+           !forwarding)
+               return dst_mtu(dst);
+
+       return min(dst->dev->mtu, IP_MAX_MTU);
+}
+
+static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb)
+{
+       if (!skb->sk || ip_sk_use_pmtu(skb->sk)) {
+               bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
+               return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
+       } else {
+               return min(skb_dst(skb)->dev->mtu, IP_MAX_MTU);
+       }
+}
+
 void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
 
 static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk)
index 2182525e4d742ccf225ec5832e1958560f2f2238..aca0c2709fd6b9771a743810e5078ead2659bd4f 100644 (file)
@@ -282,7 +282,7 @@ struct fib6_node *fib6_locate(struct fib6_node *root,
                              const struct in6_addr *saddr, int src_len);
 
 void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
-                   int prune, void *arg);
+                   void *arg);
 
 int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info);
 
index c2626ce1f2ad73a336eccf11dcb8760287fe5085..017badb1aec7e8648a6f71d473862b730a78b4e8 100644 (file)
@@ -51,26 +51,6 @@ static inline unsigned int rt6_flags2srcprefs(int flags)
        return (flags >> 3) & 7;
 }
 
-void rt6_bind_peer(struct rt6_info *rt, int create);
-
-static inline struct inet_peer *__rt6_get_peer(struct rt6_info *rt, int create)
-{
-       if (rt6_has_peer(rt))
-               return rt6_peer_ptr(rt);
-
-       rt6_bind_peer(rt, create);
-       return (rt6_has_peer(rt) ? rt6_peer_ptr(rt) : NULL);
-}
-
-static inline struct inet_peer *rt6_get_peer(struct rt6_info *rt)
-{
-       return __rt6_get_peer(rt, 0);
-}
-
-static inline struct inet_peer *rt6_get_peer_create(struct rt6_info *rt)
-{
-       return __rt6_get_peer(rt, 1);
-}
 
 void ip6_route_input(struct sk_buff *skb);
 
@@ -172,6 +152,13 @@ static inline bool ipv6_unicast_destination(const struct sk_buff *skb)
        return rt->rt6i_flags & RTF_LOCAL;
 }
 
+static inline bool ipv6_anycast_destination(const struct sk_buff *skb)
+{
+       struct rt6_info *rt = (struct rt6_info *) skb_dst(skb);
+
+       return rt->rt6i_flags & RTF_ANYCAST;
+}
+
 int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
 
 static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
index 6d1549c4893cbec83ab2aec280b08c650dff0cfd..a5593dab6af7fe0081700a2eaf5ff0e57d603ca7 100644 (file)
@@ -79,7 +79,7 @@ static inline void ip6tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        err = ip6_local_out(skb);
 
        if (net_xmit_eval(err) == 0) {
-               struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats);
+               struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
                u64_stats_update_begin(&tstats->syncp);
                tstats->tx_bytes += pkt_len;
                tstats->tx_packets++;
index 732f8c6ae975877ccd9c5873369f9be6490f06e9..cd729becbb077d217675736ffcd6597316dc8332 100644 (file)
@@ -38,6 +38,11 @@ struct ip_tunnel_prl_entry {
        struct rcu_head                 rcu_head;
 };
 
+struct ip_tunnel_dst {
+       struct dst_entry __rcu          *dst;
+       spinlock_t                      lock;
+};
+
 struct ip_tunnel {
        struct ip_tunnel __rcu  *next;
        struct hlist_node hash_node;
@@ -54,6 +59,8 @@ struct ip_tunnel {
        int             hlen;           /* Precalculated header length */
        int             mlink;
 
+       struct ip_tunnel_dst __percpu *dst_cache;
+
        struct ip_tunnel_parm parms;
 
        /* for SIT */
@@ -155,10 +162,10 @@ struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum,
 
 static inline void iptunnel_xmit_stats(int err,
                                       struct net_device_stats *err_stats,
-                                      struct pcpu_tstats __percpu *stats)
+                                      struct pcpu_sw_netstats __percpu *stats)
 {
        if (err > 0) {
-               struct pcpu_tstats *tstats = this_cpu_ptr(stats);
+               struct pcpu_sw_netstats *tstats = this_cpu_ptr(stats);
 
                u64_stats_update_begin(&tstats->syncp);
                tstats->tx_bytes += err;
index e600b89811aa055edf8b6bf571a30b1d7b918c09..12079c65ea3ed69b3c361cd83efd3908eac5841f 100644 (file)
@@ -267,9 +267,6 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);
 int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
                               struct icmp6hdr *thdr, int len);
 
-struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
-                                     struct sock *sk, struct flowi6 *fl6);
-
 int ip6_ra_control(struct sock *sk, int sel);
 
 int ipv6_parse_hopopts(struct sk_buff *skb);
@@ -839,7 +836,6 @@ static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
 
 #ifdef CONFIG_SYSCTL
 extern struct ctl_table ipv6_route_table_template[];
-extern struct ctl_table ipv6_icmp_table_template[];
 
 struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
 struct ctl_table *ipv6_route_sysctl_init(struct net *net);
index 68490cbc8a659de87fefbfe1d80f8b29bed85dbc..e8e61d4fb45838e82c5469a0b060f4c1fd3e9adb 100644 (file)
@@ -93,7 +93,6 @@ struct hlist_nulls_head *llc_sk_laddr_hash(struct llc_sap *sap,
 #define LLC_DEST_CONN            2      /* Type 2 goes here */
 
 extern struct list_head llc_sap_list;
-extern spinlock_t llc_sap_list_lock;
 
 int llc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
            struct net_device *orig_dev);
index 31e2de7d57c5d6c210e1b445b19551407fd31b6c..c0f0a13ed8183e58029aec1d12097aa1efb085f0 100644 (file)
 #define LLC_S_PF_IS_1(pdu)     ((pdu->ctrl_2 & LLC_S_PF_BIT_MASK) ? 1 : 0)
 
 #define PDU_SUPV_GET_Nr(pdu)   ((pdu->ctrl_2 & 0xFE) >> 1)
-#define PDU_GET_NEXT_Vr(sn)    (++sn & ~LLC_2_SEQ_NBR_MODULO)
+#define PDU_GET_NEXT_Vr(sn)    (((sn) + 1) & ~LLC_2_SEQ_NBR_MODULO)
 
 /* FRMR information field macros */
 
index 3cd408b326de7400b00e6284be2524955beefe27..f838af816b56cd26909752b650178450c9e47eef 100644 (file)
@@ -1162,6 +1162,19 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
        return false;
 }
 
+/**
+ * wdev_to_ieee80211_vif - return a vif struct from a wdev
+ * @wdev: the wdev to get the vif for
+ *
+ * This can be used by mac80211 drivers with direct cfg80211 APIs
+ * (like the vendor commands) that get a wdev.
+ *
+ * Note that this function may return %NULL if the given wdev isn't
+ * associated with a vif that the driver knows about (e.g. monitor
+ * or AP_VLAN interfaces.)
+ */
+struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
+
 /**
  * enum ieee80211_key_flags - key flags
  *
@@ -1600,6 +1613,9 @@ enum ieee80211_hw_flags {
  * @extra_tx_headroom: headroom to reserve in each transmit skb
  *     for use by the driver (e.g. for transmit headers.)
  *
+ * @extra_beacon_tailroom: tailroom to reserve in each beacon tx skb.
+ *     Can be used by drivers to add extra IEs.
+ *
  * @channel_change_time: time (in microseconds) it takes to change channels.
  *
  * @max_signal: Maximum value for signal (rssi) in RX information, used
@@ -1682,6 +1698,7 @@ struct ieee80211_hw {
        void *priv;
        u32 flags;
        unsigned int extra_tx_headroom;
+       unsigned int extra_beacon_tailroom;
        int channel_change_time;
        int vif_data_size;
        int sta_data_size;
@@ -2398,9 +2415,6 @@ enum ieee80211_roc_type {
  *     See the section "Frame filtering" for more information.
  *     This callback must be implemented and can sleep.
  *
- * @set_multicast_list: Configure the device's interface specific RX multicast
- *     filter. This callback is optional. This callback must be atomic.
- *
  * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
  *     must be set or cleared for a given STA. Must be atomic.
  *
@@ -2485,7 +2499,11 @@ enum ieee80211_roc_type {
  *     AP, IBSS/WDS/mesh peer etc. This callback can sleep.
  *
  * @sta_remove: Notifies low level driver about removal of an associated
- *     station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
+ *     station, AP, IBSS/WDS/mesh peer etc. Note that after the callback
+ *     returns it isn't safe to use the pointer, not even RCU protected;
+ *     no RCU grace period is guaranteed between returning here and freeing
+ *     the station. See @sta_pre_rcu_remove if needed.
+ *     This callback can sleep.
  *
  * @sta_add_debugfs: Drivers can use this callback to add debugfs files
  *     when a station is added to mac80211's station list. This callback
@@ -2504,7 +2522,17 @@ enum ieee80211_roc_type {
  *     station (which can be the AP, a client, IBSS/WDS/mesh peer etc.)
  *     This callback is mutually exclusive with @sta_add/@sta_remove.
  *     It must not fail for down transitions but may fail for transitions
- *     up the list of states.
+ *     up the list of states. Also note that after the callback returns it
+ *     isn't safe to use the pointer, not even RCU protected - no RCU grace
+ *     period is guaranteed between returning here and freeing the station.
+ *     See @sta_pre_rcu_remove if needed.
+ *     The callback can sleep.
+ *
+ * @sta_pre_rcu_remove: Notify driver about station removal before RCU
+ *     synchronisation. This is useful if a driver needs to have station
+ *     pointers protected using RCU, it can then use this call to clear
+ *     the pointers instead of waiting for an RCU grace period to elapse
+ *     in @sta_state.
  *     The callback can sleep.
  *
  * @sta_rc_update: Notifies the driver of changes to the bitrates that can be
@@ -2764,10 +2792,6 @@ struct ieee80211_ops {
                                 unsigned int changed_flags,
                                 unsigned int *total_flags,
                                 u64 multicast);
-       void (*set_multicast_list)(struct ieee80211_hw *hw,
-                                  struct ieee80211_vif *vif, bool allmulti,
-                                  struct netdev_hw_addr_list *mc_list);
-
        int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
                       bool set);
        int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -2821,6 +2845,9 @@ struct ieee80211_ops {
                         struct ieee80211_sta *sta,
                         enum ieee80211_sta_state old_state,
                         enum ieee80211_sta_state new_state);
+       void (*sta_pre_rcu_remove)(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif,
+                                  struct ieee80211_sta *sta);
        void (*sta_rc_update)(struct ieee80211_hw *hw,
                              struct ieee80211_vif *vif,
                              struct ieee80211_sta *sta,
@@ -4625,4 +4652,51 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
                              struct ieee80211_vif *vif, struct sk_buff *skb,
                              int band, struct ieee80211_sta **sta);
 
+/**
+ * struct ieee80211_noa_data - holds temporary data for tracking P2P NoA state
+ *
+ * @next_tsf: TSF timestamp of the next absent state change
+ * @has_next_tsf: next absent state change event pending
+ *
+ * @absent: descriptor bitmask, set if GO is currently absent
+ *
+ * private:
+ *
+ * @count: count fields from the NoA descriptors
+ * @desc: adjusted data from the NoA
+ */
+struct ieee80211_noa_data {
+       u32 next_tsf;
+       bool has_next_tsf;
+
+       u8 absent;
+
+       u8 count[IEEE80211_P2P_NOA_DESC_MAX];
+       struct {
+               u32 start;
+               u32 duration;
+               u32 interval;
+       } desc[IEEE80211_P2P_NOA_DESC_MAX];
+};
+
+/**
+ * ieee80211_parse_p2p_noa - initialize NoA tracking data from P2P IE
+ *
+ * @attr: P2P NoA IE
+ * @data: NoA tracking data
+ * @tsf: current TSF timestamp
+ *
+ * Return: number of successfully parsed descriptors
+ */
+int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr,
+                           struct ieee80211_noa_data *data, u32 tsf);
+
+/**
+ * ieee80211_update_p2p_noa - get next pending P2P GO absent state change
+ *
+ * @data: NoA tracking data
+ * @tsf: current TSF timestamp
+ */
+void ieee80211_update_p2p_noa(struct ieee80211_noa_data *data, u32 tsf);
+
 #endif /* MAC80211_H */
index 6c3d12e2949f908c3927cb4bfe29ac30c49e1e4a..981c327374da3f80475042d81623a91295c9a00f 100644 (file)
@@ -19,6 +19,4 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
 int nf_conntrack_ipv4_compat_init(void);
 void nf_conntrack_ipv4_compat_fini(void);
 
-void need_ipv4_conntrack(void);
-
 #endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/include/net/netfilter/ipv4/nf_reject.h b/include/net/netfilter/ipv4/nf_reject.h
new file mode 100644 (file)
index 0000000..931fbf8
--- /dev/null
@@ -0,0 +1,128 @@
+#ifndef _IPV4_NF_REJECT_H
+#define _IPV4_NF_REJECT_H
+
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/route.h>
+#include <net/dst.h>
+
+static inline void nf_send_unreach(struct sk_buff *skb_in, int code)
+{
+       icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
+}
+
+/* Send RST reply */
+static void nf_send_reset(struct sk_buff *oldskb, int hook)
+{
+       struct sk_buff *nskb;
+       const struct iphdr *oiph;
+       struct iphdr *niph;
+       const struct tcphdr *oth;
+       struct tcphdr _otcph, *tcph;
+
+       /* IP header checks: fragment. */
+       if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
+               return;
+
+       oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
+                                sizeof(_otcph), &_otcph);
+       if (oth == NULL)
+               return;
+
+       /* No RST for RST. */
+       if (oth->rst)
+               return;
+
+       if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
+               return;
+
+       /* Check checksum */
+       if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
+               return;
+       oiph = ip_hdr(oldskb);
+
+       nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
+                        LL_MAX_HEADER, GFP_ATOMIC);
+       if (!nskb)
+               return;
+
+       skb_reserve(nskb, LL_MAX_HEADER);
+
+       skb_reset_network_header(nskb);
+       niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
+       niph->version   = 4;
+       niph->ihl       = sizeof(struct iphdr) / 4;
+       niph->tos       = 0;
+       niph->id        = 0;
+       niph->frag_off  = htons(IP_DF);
+       niph->protocol  = IPPROTO_TCP;
+       niph->check     = 0;
+       niph->saddr     = oiph->daddr;
+       niph->daddr     = oiph->saddr;
+
+       skb_reset_transport_header(nskb);
+       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
+       memset(tcph, 0, sizeof(*tcph));
+       tcph->source    = oth->dest;
+       tcph->dest      = oth->source;
+       tcph->doff      = sizeof(struct tcphdr) / 4;
+
+       if (oth->ack)
+               tcph->seq = oth->ack_seq;
+       else {
+               tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
+                                     oldskb->len - ip_hdrlen(oldskb) -
+                                     (oth->doff << 2));
+               tcph->ack = 1;
+       }
+
+       tcph->rst       = 1;
+       tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
+                                   niph->daddr, 0);
+       nskb->ip_summed = CHECKSUM_PARTIAL;
+       nskb->csum_start = (unsigned char *)tcph - nskb->head;
+       nskb->csum_offset = offsetof(struct tcphdr, check);
+
+       /* ip_route_me_harder expects skb->dst to be set */
+       skb_dst_set_noref(nskb, skb_dst(oldskb));
+
+       nskb->protocol = htons(ETH_P_IP);
+       if (ip_route_me_harder(nskb, RTN_UNSPEC))
+               goto free_nskb;
+
+       niph->ttl       = ip4_dst_hoplimit(skb_dst(nskb));
+
+       /* "Never happens" */
+       if (nskb->len > dst_mtu(skb_dst(nskb)))
+               goto free_nskb;
+
+       nf_ct_attach(nskb, oldskb);
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+       /* If we use ip_local_out for bridged traffic, the MAC source on
+        * the RST will be ours, instead of the destination's.  This confuses
+        * some routers/firewalls, and they drop the packet.  So we need to
+        * build the eth header using the original destination's MAC as the
+        * source, and send the RST packet directly.
+        */
+       if (oldskb->nf_bridge) {
+               struct ethhdr *oeth = eth_hdr(oldskb);
+               nskb->dev = oldskb->nf_bridge->physindev;
+               niph->tot_len = htons(nskb->len);
+               ip_send_check(niph);
+               if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
+                                   oeth->h_source, oeth->h_dest, nskb->len) < 0)
+                       goto free_nskb;
+               dev_queue_xmit(nskb);
+       } else
+#endif
+               ip_local_out(nskb);
+
+       return;
+
+ free_nskb:
+       kfree_skb(nskb);
+}
+
+
+#endif /* _IPV4_NF_REJECT_H */
diff --git a/include/net/netfilter/ipv6/nf_reject.h b/include/net/netfilter/ipv6/nf_reject.h
new file mode 100644 (file)
index 0000000..710d17e
--- /dev/null
@@ -0,0 +1,171 @@
+#ifndef _IPV6_NF_REJECT_H
+#define _IPV6_NF_REJECT_H
+
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/ip6_fib.h>
+#include <net/ip6_checksum.h>
+#include <linux/netfilter_ipv6.h>
+
+static inline void
+nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code,
+            unsigned int hooknum)
+{
+       if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
+               skb_in->dev = net->loopback_dev;
+
+       icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
+}
+
+/* Send RST reply */
+static void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
+{
+       struct sk_buff *nskb;
+       struct tcphdr otcph, *tcph;
+       unsigned int otcplen, hh_len;
+       int tcphoff, needs_ack;
+       const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
+       struct ipv6hdr *ip6h;
+#define DEFAULT_TOS_VALUE      0x0U
+       const __u8 tclass = DEFAULT_TOS_VALUE;
+       struct dst_entry *dst = NULL;
+       u8 proto;
+       __be16 frag_off;
+       struct flowi6 fl6;
+
+       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
+           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
+               pr_debug("addr is not unicast.\n");
+               return;
+       }
+
+       proto = oip6h->nexthdr;
+       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off);
+
+       if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
+               pr_debug("Cannot get TCP header.\n");
+               return;
+       }
+
+       otcplen = oldskb->len - tcphoff;
+
+       /* IP header checks: fragment, too short. */
+       if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
+               pr_debug("proto(%d) != IPPROTO_TCP, "
+                        "or too short. otcplen = %d\n",
+                        proto, otcplen);
+               return;
+       }
+
+       if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr)))
+               BUG();
+
+       /* No RST for RST. */
+       if (otcph.rst) {
+               pr_debug("RST is set\n");
+               return;
+       }
+
+       /* Check checksum. */
+       if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) {
+               pr_debug("TCP checksum is invalid\n");
+               return;
+       }
+
+       memset(&fl6, 0, sizeof(fl6));
+       fl6.flowi6_proto = IPPROTO_TCP;
+       fl6.saddr = oip6h->daddr;
+       fl6.daddr = oip6h->saddr;
+       fl6.fl6_sport = otcph.dest;
+       fl6.fl6_dport = otcph.source;
+       security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
+       dst = ip6_route_output(net, NULL, &fl6);
+       if (dst == NULL || dst->error) {
+               dst_release(dst);
+               return;
+       }
+       dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+       if (IS_ERR(dst))
+               return;
+
+       hh_len = (dst->dev->hard_header_len + 15)&~15;
+       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
+                        + sizeof(struct tcphdr) + dst->trailer_len,
+                        GFP_ATOMIC);
+
+       if (!nskb) {
+               net_dbg_ratelimited("cannot alloc skb\n");
+               dst_release(dst);
+               return;
+       }
+
+       skb_dst_set(nskb, dst);
+
+       skb_reserve(nskb, hh_len + dst->header_len);
+
+       skb_put(nskb, sizeof(struct ipv6hdr));
+       skb_reset_network_header(nskb);
+       ip6h = ipv6_hdr(nskb);
+       ip6_flow_hdr(ip6h, tclass, 0);
+       ip6h->hop_limit = ip6_dst_hoplimit(dst);
+       ip6h->nexthdr = IPPROTO_TCP;
+       ip6h->saddr = oip6h->daddr;
+       ip6h->daddr = oip6h->saddr;
+
+       skb_reset_transport_header(nskb);
+       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
+       /* Truncate to length (no data) */
+       tcph->doff = sizeof(struct tcphdr)/4;
+       tcph->source = otcph.dest;
+       tcph->dest = otcph.source;
+
+       if (otcph.ack) {
+               needs_ack = 0;
+               tcph->seq = otcph.ack_seq;
+               tcph->ack_seq = 0;
+       } else {
+               needs_ack = 1;
+               tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
+                                     + otcplen - (otcph.doff<<2));
+               tcph->seq = 0;
+       }
+
+       /* Reset flags */
+       ((u_int8_t *)tcph)[13] = 0;
+       tcph->rst = 1;
+       tcph->ack = needs_ack;
+       tcph->window = 0;
+       tcph->urg_ptr = 0;
+       tcph->check = 0;
+
+       /* Adjust TCP checksum */
+       tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr,
+                                     &ipv6_hdr(nskb)->daddr,
+                                     sizeof(struct tcphdr), IPPROTO_TCP,
+                                     csum_partial(tcph,
+                                                  sizeof(struct tcphdr), 0));
+
+       nf_ct_attach(nskb, oldskb);
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+       /* If we use ip6_local_out for bridged traffic, the MAC source on
+        * the RST will be ours, instead of the destination's.  This confuses
+        * some routers/firewalls, and they drop the packet.  So we need to
+        * build the eth header using the original destination's MAC as the
+        * source, and send the RST packet directly.
+        */
+       if (oldskb->nf_bridge) {
+               struct ethhdr *oeth = eth_hdr(oldskb);
+               nskb->dev = oldskb->nf_bridge->physindev;
+               nskb->protocol = htons(ETH_P_IPV6);
+               ip6h->payload_len = htons(sizeof(struct tcphdr));
+               if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
+                                   oeth->h_source, oeth->h_dest, nskb->len) < 0)
+                       return;
+               dev_queue_xmit(nskb);
+       } else
+#endif
+               ip6_local_out(nskb);
+}
+
+#endif /* _IPV6_NF_REJECT_H */
index 3efab704b7eb9b303b433549bb342d923e43f67f..adc1fa3dd7ab8a7c69bc6b61bd19357d6332f120 100644 (file)
@@ -87,7 +87,6 @@ int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto);
 void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto);
 
 struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
-void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
 
 /* Existing built-in protocols */
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic;
index c1d5b3e34a211a8df6fd4eba749b4fcd9e62131f..84a53d7803069dd15bb5bb8575dffa1a900d8ea5 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef _NF_QUEUE_H
 #define _NF_QUEUE_H
 
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/jhash.h>
+
 /* Each queued (to userspace) skbuff has one of these. */
 struct nf_queue_entry {
        struct list_head        list;
@@ -33,4 +37,62 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
 bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
 void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
 
+static inline void init_hashrandom(u32 *jhash_initval)
+{
+       while (*jhash_initval == 0)
+               *jhash_initval = prandom_u32();
+}
+
+static inline u32 hash_v4(const struct sk_buff *skb, u32 jhash_initval)
+{
+       const struct iphdr *iph = ip_hdr(skb);
+
+       /* packets in either direction go into same queue */
+       if ((__force u32)iph->saddr < (__force u32)iph->daddr)
+               return jhash_3words((__force u32)iph->saddr,
+                       (__force u32)iph->daddr, iph->protocol, jhash_initval);
+
+       return jhash_3words((__force u32)iph->daddr,
+                       (__force u32)iph->saddr, iph->protocol, jhash_initval);
+}
+
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+static inline u32 hash_v6(const struct sk_buff *skb, u32 jhash_initval)
+{
+       const struct ipv6hdr *ip6h = ipv6_hdr(skb);
+       u32 a, b, c;
+
+       if ((__force u32)ip6h->saddr.s6_addr32[3] <
+           (__force u32)ip6h->daddr.s6_addr32[3]) {
+               a = (__force u32) ip6h->saddr.s6_addr32[3];
+               b = (__force u32) ip6h->daddr.s6_addr32[3];
+       } else {
+               b = (__force u32) ip6h->saddr.s6_addr32[3];
+               a = (__force u32) ip6h->daddr.s6_addr32[3];
+       }
+
+       if ((__force u32)ip6h->saddr.s6_addr32[1] <
+           (__force u32)ip6h->daddr.s6_addr32[1])
+               c = (__force u32) ip6h->saddr.s6_addr32[1];
+       else
+               c = (__force u32) ip6h->daddr.s6_addr32[1];
+
+       return jhash_3words(a, b, c, jhash_initval);
+}
+#endif
+
+static inline u32
+nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family,
+            u32 jhash_initval)
+{
+       if (family == NFPROTO_IPV4)
+               queue += ((u64) hash_v4(skb, jhash_initval) * queues_total) >> 32;
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+       else if (family == NFPROTO_IPV6)
+               queue += ((u64) hash_v6(skb, jhash_initval) * queues_total) >> 32;
+#endif
+
+       return queue;
+}
+
 #endif /* _NF_QUEUE_H */
index 5a91abfc0c30dec50c6f83c2d6568429a676c1c5..57c8ff7955dfbd109e8ac2c731d595539220b3d4 100644 (file)
@@ -13,9 +13,10 @@ struct nft_pktinfo {
        struct sk_buff                  *skb;
        const struct net_device         *in;
        const struct net_device         *out;
-       u8                              hooknum;
+       const struct nf_hook_ops        *ops;
        u8                              nhoff;
        u8                              thoff;
+       u8                              tprot;
        /* for x_tables compatibility */
        struct xt_action_param          xt;
 };
@@ -29,7 +30,8 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
        pkt->skb = skb;
        pkt->in = pkt->xt.in = in;
        pkt->out = pkt->xt.out = out;
-       pkt->hooknum = pkt->xt.hooknum = ops->hooknum;
+       pkt->ops = ops;
+       pkt->xt.hooknum = ops->hooknum;
        pkt->xt.family = ops->pf;
 }
 
@@ -421,6 +423,8 @@ struct nft_stats {
        u64 pkts;
 };
 
+#define NFT_HOOK_OPS_MAX               2
+
 /**
  *     struct nft_base_chain - nf_tables base chain
  *
@@ -431,8 +435,8 @@ struct nft_stats {
  *     @chain: the chain
  */
 struct nft_base_chain {
-       struct nf_hook_ops              ops;
-       enum nft_chain_type             type;
+       struct nf_hook_ops              ops[NFT_HOOK_OPS_MAX];
+       const struct nf_chain_type      *type;
        u8                              policy;
        struct nft_stats __percpu       *stats;
        struct nft_chain                chain;
@@ -443,8 +447,8 @@ static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chai
        return container_of(chain, struct nft_base_chain, chain);
 }
 
-unsigned int nft_do_chain_pktinfo(struct nft_pktinfo *pkt,
-                                 const struct nf_hook_ops *ops);
+unsigned int nft_do_chain(struct nft_pktinfo *pkt,
+                         const struct nf_hook_ops *ops);
 
 /**
  *     struct nft_table - nf_tables table
@@ -475,6 +479,8 @@ struct nft_table {
  *     @nhooks: number of hooks in this family
  *     @owner: module owner
  *     @tables: used internally
+ *     @nops: number of hook ops in this family
+ *     @hook_ops_init: initialization function for chain hook ops
  *     @hooks: hookfn overrides for packet validation
  */
 struct nft_af_info {
@@ -483,23 +489,36 @@ struct nft_af_info {
        unsigned int                    nhooks;
        struct module                   *owner;
        struct list_head                tables;
+       unsigned int                    nops;
+       void                            (*hook_ops_init)(struct nf_hook_ops *,
+                                                        unsigned int);
        nf_hookfn                       *hooks[NF_MAX_HOOKS];
 };
 
 int nft_register_afinfo(struct net *, struct nft_af_info *);
 void nft_unregister_afinfo(struct nft_af_info *);
 
+/**
+ *     struct nf_chain_type - nf_tables chain type info
+ *
+ *     @name: name of the type
+ *     @type: numeric identifier
+ *     @family: address family
+ *     @owner: module owner
+ *     @hook_mask: mask of valid hooks
+ *     @hooks: hookfn overrides
+ */
 struct nf_chain_type {
-       unsigned int            hook_mask;
-       const char              *name;
-       enum nft_chain_type     type;
-       nf_hookfn               *fn[NF_MAX_HOOKS];
-       struct module           *me;
-       int                     family;
+       const char                      *name;
+       enum nft_chain_type             type;
+       int                             family;
+       struct module                   *owner;
+       unsigned int                    hook_mask;
+       nf_hookfn                       *hooks[NF_MAX_HOOKS];
 };
 
-int nft_register_chain_type(struct nf_chain_type *);
-void nft_unregister_chain_type(struct nf_chain_type *);
+int nft_register_chain_type(const struct nf_chain_type *);
+void nft_unregister_chain_type(const struct nf_chain_type *);
 
 int nft_register_expr(struct nft_expr_type *);
 void nft_unregister_expr(struct nft_expr_type *);
index 1be1c2c197ee2b0d8540bdb3469f8d6c0db4538e..cba143fbd2e4fca9f5d0280dda035215ebd922fb 100644 (file)
@@ -15,9 +15,12 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
 
        nft_set_pktinfo(pkt, ops, skb, in, out);
 
-       pkt->xt.thoff = ip_hdrlen(pkt->skb);
        ip = ip_hdr(pkt->skb);
+       pkt->tprot = ip->protocol;
+       pkt->xt.thoff = ip_hdrlen(pkt->skb);
        pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
 }
 
+extern struct nft_af_info nft_af_ipv4;
+
 #endif
index 4a9b88a65963ee48d33589e2b544c95551c5f185..74d97613765801512e523bab6e40b6e2767d982d 100644 (file)
@@ -21,10 +21,13 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
        if (protohdr < 0)
                return -1;
 
+       pkt->tprot = protohdr;
        pkt->xt.thoff = thoff;
        pkt->xt.fragoff = frag_off;
 
        return 0;
 }
 
+extern struct nft_af_info nft_af_ipv6;
+
 #endif
index c9c0c538b68bb478c924e93d9b5408c933100459..fbcc7fa536dc4ab49440d4566e63fedf8b860d2a 100644 (file)
@@ -65,6 +65,23 @@ struct nf_ip_net {
 struct netns_ct {
        atomic_t                count;
        unsigned int            expect_count;
+#ifdef CONFIG_SYSCTL
+       struct ctl_table_header *sysctl_header;
+       struct ctl_table_header *acct_sysctl_header;
+       struct ctl_table_header *tstamp_sysctl_header;
+       struct ctl_table_header *event_sysctl_header;
+       struct ctl_table_header *helper_sysctl_header;
+#endif
+       char                    *slabname;
+       unsigned int            sysctl_log_invalid; /* Log invalid packets */
+       unsigned int            sysctl_events_retry_timeout;
+       int                     sysctl_events;
+       int                     sysctl_acct;
+       int                     sysctl_auto_assign_helper;
+       bool                    auto_assign_helper_warned;
+       int                     sysctl_tstamp;
+       int                     sysctl_checksum;
+
        unsigned int            htable_size;
        struct kmem_cache       *nf_conntrack_cachep;
        struct hlist_nulls_head *hash;
@@ -75,14 +92,6 @@ struct netns_ct {
        struct ip_conntrack_stat __percpu *stat;
        struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
        struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
-       int                     sysctl_events;
-       unsigned int            sysctl_events_retry_timeout;
-       int                     sysctl_acct;
-       int                     sysctl_tstamp;
-       int                     sysctl_checksum;
-       unsigned int            sysctl_log_invalid; /* Log invalid packets */
-       int                     sysctl_auto_assign_helper;
-       bool                    auto_assign_helper_warned;
        struct nf_ip_net        nf_ct_proto;
 #if defined(CONFIG_NF_CONNTRACK_LABELS)
        unsigned int            labels_used;
@@ -92,13 +101,5 @@ struct netns_ct {
        struct hlist_head       *nat_bysource;
        unsigned int            nat_htable_size;
 #endif
-#ifdef CONFIG_SYSCTL
-       struct ctl_table_header *sysctl_header;
-       struct ctl_table_header *acct_sysctl_header;
-       struct ctl_table_header *tstamp_sysctl_header;
-       struct ctl_table_header *event_sysctl_header;
-       struct ctl_table_header *helper_sysctl_header;
-#endif
-       char                    *slabname;
 };
 #endif
index 929a668e91a9a8b42acba7a1148cdf21c872f0e8..80f500a29498e1fc9b8892e5c66be6bd02362eaa 100644 (file)
@@ -70,6 +70,7 @@ struct netns_ipv4 {
 
        int sysctl_tcp_ecn;
        int sysctl_ip_no_pmtu_disc;
+       int sysctl_ip_fwd_use_pmtu;
 
        kgid_t sysctl_ping_group_range[2];
 
index 0fb2401197c51ecf9dd041066975cf5f0bb6a264..76fc7d1dbfd3a4f425a0afe0e88f40353b1468ea 100644 (file)
@@ -73,6 +73,7 @@ struct netns_ipv6 {
 #endif
        atomic_t                dev_addr_genid;
        atomic_t                rt_genid;
+       int                     anycast_src_echo_reply;
 };
 
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
index 15d056d534e3ba08a71cb4c796d3f98655161fce..26a394cb91a8fde2bb5a3f8716d25e073e4b1862 100644 (file)
@@ -10,6 +10,7 @@ struct netns_nftables {
        struct list_head        commit_list;
        struct nft_af_info      *ipv4;
        struct nft_af_info      *ipv6;
+       struct nft_af_info      *inet;
        struct nft_af_info      *arp;
        struct nft_af_info      *bridge;
        u8                      gencursor;
index 099d02782e22274fb9f7b52abe296cb17d14e45d..dafc09f0fdbc86f8b87180cbee2e733694b89085 100644 (file)
 
 #ifndef _NETPRIO_CGROUP_H
 #define _NETPRIO_CGROUP_H
+
 #include <linux/cgroup.h>
 #include <linux/hardirq.h>
 #include <linux/rcupdate.h>
 
-
-#if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
+#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
 struct netprio_map {
        struct rcu_head rcu;
        u32 priomap_len;
@@ -27,8 +27,7 @@ struct netprio_map {
 
 void sock_update_netprioidx(struct sock *sk);
 
-#if IS_BUILTIN(CONFIG_NETPRIO_CGROUP)
-
+#if IS_BUILTIN(CONFIG_CGROUP_NET_PRIO)
 static inline u32 task_netprioidx(struct task_struct *p)
 {
        struct cgroup_subsys_state *css;
@@ -40,9 +39,7 @@ static inline u32 task_netprioidx(struct task_struct *p)
        rcu_read_unlock();
        return idx;
 }
-
-#elif IS_MODULE(CONFIG_NETPRIO_CGROUP)
-
+#elif IS_MODULE(CONFIG_CGROUP_NET_PRIO)
 static inline u32 task_netprioidx(struct task_struct *p)
 {
        struct cgroup_subsys_state *css;
@@ -56,9 +53,7 @@ static inline u32 task_netprioidx(struct task_struct *p)
        return idx;
 }
 #endif
-
-#else /* !CONFIG_NETPRIO_CGROUP */
-
+#else /* !CONFIG_CGROUP_NET_PRIO */
 static inline u32 task_netprioidx(struct task_struct *p)
 {
        return 0;
@@ -66,6 +61,5 @@ static inline u32 task_netprioidx(struct task_struct *p)
 
 #define sock_update_netprioidx(sk)
 
-#endif /* CONFIG_NETPRIO_CGROUP */
-
+#endif /* CONFIG_CGROUP_NET_PRIO */
 #endif  /* _NET_CLS_CGROUP_H */
index 90f48417b03dac91259aefe18d79c63145a23849..76013653e08ce19f0ded51f64ab9ca3f71026582 100644 (file)
@@ -42,11 +42,6 @@ struct pingv6_ops {
                             const struct net_device *dev, int strict);
 };
 
-struct ping_table {
-       struct hlist_nulls_head hash[PING_HTABLE_SIZE];
-       rwlock_t                lock;
-};
-
 struct ping_iter_state {
        struct seq_net_private  p;
        int                     bucket;
@@ -54,7 +49,6 @@ struct ping_iter_state {
 };
 
 extern struct proto ping_prot;
-extern struct ping_table ping_table;
 #if IS_ENABLED(CONFIG_IPV6)
 extern struct pingv6_ops pingv6_ops;
 #endif
@@ -81,8 +75,6 @@ int  ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                  size_t len, int noblock, int flags, int *addr_len);
 int  ping_common_sendmsg(int family, struct msghdr *msg, size_t len,
                         void *user_icmph, size_t icmph_len);
-int  ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
-                    size_t len);
 int  ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                     size_t len);
 int  ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
index 50ea07969c0999b1307b6c4ef053958f13af4b34..a2441fb1428f3f2e181df63319ca2b3fdc15dc4e 100644 (file)
@@ -338,27 +338,27 @@ static inline int tcf_valid_offset(const struct sk_buff *skb,
 #include <net/net_namespace.h>
 
 static inline int
-tcf_change_indev(struct tcf_proto *tp, char *indev, struct nlattr *indev_tlv)
+tcf_change_indev(struct net *net, struct nlattr *indev_tlv)
 {
+       char indev[IFNAMSIZ];
+       struct net_device *dev;
+
        if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
                return -EINVAL;
-       return 0;
+       dev = __dev_get_by_name(net, indev);
+       if (!dev)
+               return -ENODEV;
+       return dev->ifindex;
 }
 
-static inline int
-tcf_match_indev(struct sk_buff *skb, char *indev)
+static inline bool
+tcf_match_indev(struct sk_buff *skb, int ifindex)
 {
-       struct net_device *dev;
-
-       if (indev[0]) {
-               if  (!skb->skb_iif)
-                       return 0;
-               dev = __dev_get_by_index(dev_net(skb->dev), skb->skb_iif);
-               if (!dev || strcmp(indev, dev->name))
-                       return 0;
-       }
-
-       return 1;
+       if (!ifindex)
+               return true;
+       if  (!skb->skb_iif)
+               return false;
+       return ifindex == skb->skb_iif;
 }
 #endif /* CONFIG_NET_CLS_IND */
 
index fbf7676c9a02e352890b66d0bc3caf1775dbb199..0e5f8665d7fbf651746ba46727eeda0365be6a47 100644 (file)
@@ -43,7 +43,12 @@ struct net_protocol {
        int                     (*handler)(struct sk_buff *skb);
        void                    (*err_handler)(struct sk_buff *skb, u32 info);
        unsigned int            no_policy:1,
-                               netns_ok:1;
+                               netns_ok:1,
+                               /* does the protocol do more stringent
+                                * icmp tag validation than simple
+                                * socket lookup?
+                                */
+                               icmp_strict_tag_validation:1;
 };
 
 #if IS_ENABLED(CONFIG_IPV6)
index 638e3ebf76f33443ac3c218912c7b7646a4f7846..9d1f423d5944bc3908bf68e64aae7f259ff7fdb0 100644 (file)
@@ -36,6 +36,9 @@
 #include <linux/cache.h>
 #include <linux/security.h>
 
+/* IPv4 datagram length is stored into 16bit field (tot_len) */
+#define IP_MAX_MTU     0xFFFFU
+
 #define RTO_ONLINK     0x01
 
 #define RT_CONN_FLAGS(sk)   (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE))
@@ -311,20 +314,4 @@ static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
        return hoplimit;
 }
 
-static inline bool ip_sk_accept_pmtu(const struct sock *sk)
-{
-       return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE;
-}
-
-static inline bool ip_sk_use_pmtu(const struct sock *sk)
-{
-       return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE;
-}
-
-static inline int ip_skb_dst_mtu(const struct sk_buff *skb)
-{
-       return (!skb->sk || ip_sk_use_pmtu(skb->sk)) ?
-              dst_mtu(skb_dst(skb)) : skb_dst(skb)->dev->mtu;
-}
-
 #endif /* _ROUTE_H */
index bb13a182fba6ed076851f58590ab662e429bf01a..8fb42070a2c1485f6def2bdbd8b8ff95ff2c97fe 100644 (file)
@@ -115,10 +115,9 @@ struct rtnl_af_ops {
                                               const struct nlattr *attr);
 };
 
-int __rtnl_af_register(struct rtnl_af_ops *ops);
 void __rtnl_af_unregister(struct rtnl_af_ops *ops);
 
-int rtnl_af_register(struct rtnl_af_ops *ops);
+void rtnl_af_register(struct rtnl_af_ops *ops);
 void rtnl_af_unregister(struct rtnl_af_ops *ops);
 
 struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
index 013d96dc69183c906adeeca604ecf8a7cea80082..d062f81c692f1ee3e61ba1a06bd27e3a9edb761a 100644 (file)
@@ -204,7 +204,7 @@ struct tcf_proto_ops {
        void                    (*walk)(struct tcf_proto*, struct tcf_walker *arg);
 
        /* rtnetlink specific */
-       int                     (*dump)(struct tcf_proto*, unsigned long,
+       int                     (*dump)(struct net*, struct tcf_proto*, unsigned long,
                                        struct sk_buff *skb, struct tcmsg*);
 
        struct module           *owner;
index 41c7013e26995d3271f8c07eb900e5897b0d78b1..d992ca3145fec9826c1df1cf0affc95272a6af25 100644 (file)
@@ -649,7 +649,6 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
                          struct iovec *data);
 void sctp_chunk_free(struct sctp_chunk *);
 void  *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
-void  *sctp_addto_chunk_fixed(struct sctp_chunk *, int len, const void *data);
 struct sctp_chunk *sctp_chunkify(struct sk_buff *,
                                 const struct sctp_association *,
                                 struct sock *);
@@ -1045,9 +1044,6 @@ struct sctp_outq {
 
        /* Corked? */
        char cork;
-
-       /* Is this structure empty?  */
-       char empty;
 };
 
 void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
index 2ef3c3eca47aacaa28ee25aecd236897d276845a..5c3f7c3624aa00214572c47cd3b6dbb3777d93ee 100644 (file)
@@ -395,7 +395,7 @@ struct sock {
        unsigned short          sk_ack_backlog;
        unsigned short          sk_max_ack_backlog;
        __u32                   sk_priority;
-#if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
+#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
        __u32                   sk_cgrp_prioidx;
 #endif
        struct pid              *sk_peer_pid;
@@ -820,30 +820,44 @@ static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
        return sk->sk_backlog_rcv(sk, skb);
 }
 
-static inline void sock_rps_record_flow(const struct sock *sk)
+static inline void sock_rps_record_flow_hash(__u32 hash)
 {
 #ifdef CONFIG_RPS
        struct rps_sock_flow_table *sock_flow_table;
 
        rcu_read_lock();
        sock_flow_table = rcu_dereference(rps_sock_flow_table);
-       rps_record_sock_flow(sock_flow_table, sk->sk_rxhash);
+       rps_record_sock_flow(sock_flow_table, hash);
        rcu_read_unlock();
 #endif
 }
 
-static inline void sock_rps_reset_flow(const struct sock *sk)
+static inline void sock_rps_reset_flow_hash(__u32 hash)
 {
 #ifdef CONFIG_RPS
        struct rps_sock_flow_table *sock_flow_table;
 
        rcu_read_lock();
        sock_flow_table = rcu_dereference(rps_sock_flow_table);
-       rps_reset_sock_flow(sock_flow_table, sk->sk_rxhash);
+       rps_reset_sock_flow(sock_flow_table, hash);
        rcu_read_unlock();
 #endif
 }
 
+static inline void sock_rps_record_flow(const struct sock *sk)
+{
+#ifdef CONFIG_RPS
+       sock_rps_record_flow_hash(sk->sk_rxhash);
+#endif
+}
+
+static inline void sock_rps_reset_flow(const struct sock *sk)
+{
+#ifdef CONFIG_RPS
+       sock_rps_reset_flow_hash(sk->sk_rxhash);
+#endif
+}
+
 static inline void sock_rps_save_rxhash(struct sock *sk,
                                        const struct sk_buff *skb)
 {
@@ -1535,8 +1549,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority);
 
 struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
                             gfp_t priority);
-struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force,
-                            gfp_t priority);
 void sock_wfree(struct sk_buff *skb);
 void skb_orphan_partial(struct sk_buff *skb);
 void sock_rfree(struct sk_buff *skb);
index 9cd62bc090553f529f0ff4f435d20ef5713deff5..56fc366da6d5183b536648e949769a118ba33677 100644 (file)
@@ -468,7 +468,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
                                struct tcp_fastopen_cookie *foc);
 int tcp_disconnect(struct sock *sk, int flags);
 
-void tcp_connect_init(struct sock *sk);
 void tcp_finish_connect(struct sock *sk, struct sk_buff *skb);
 int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size);
 void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb);
@@ -623,8 +622,6 @@ static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
        return (tp->srtt >> 3) + tp->rttvar;
 }
 
-void tcp_set_rto(struct sock *sk);
-
 static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
 {
        tp->pred_flags = htonl((tp->tcp_header_len << 26) |
index 979874c627ee7f450c7aabff5c948cb2c87f84c3..61e1935c91b121d0ba6a9e5d6f05221d15060432 100644 (file)
@@ -978,7 +978,7 @@ struct ib_uobject {
 };
 
 struct ib_udata {
-       void __user *inbuf;
+       const void __user *inbuf;
        void __user *outbuf;
        size_t       inlen;
        size_t       outlen;
index 45412a6afa69d95ea82c820fb197d350c9d0575e..321301c0a643bfb32303b3f48cecae720f3fad87 100644 (file)
@@ -517,10 +517,6 @@ struct se_node_acl {
        u32                     acl_index;
 #define MAX_ACL_TAG_SIZE 64
        char                    acl_tag[MAX_ACL_TAG_SIZE];
-       u64                     num_cmds;
-       u64                     read_bytes;
-       u64                     write_bytes;
-       spinlock_t              stats_lock;
        /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
        atomic_t                acl_pr_ref_count;
        struct se_dev_entry     **device_list;
@@ -624,6 +620,7 @@ struct se_dev_attrib {
        u32             unmap_granularity;
        u32             unmap_granularity_alignment;
        u32             max_write_same_len;
+       u32             max_bytes_per_io;
        struct se_device *da_dev;
        struct config_group da_group;
 };
index d7fea3496f323078739fc6c6148be125f79797c3..4d024d75d64ba8b7831cdb1d61384e47ac14ef33 100644 (file)
@@ -94,6 +94,7 @@
 #define ARPHRD_CAIF    822             /* CAIF media type              */
 #define ARPHRD_IP6GRE  823             /* GRE over IPv6                */
 #define ARPHRD_NETLINK 824             /* Netlink header               */
+#define ARPHRD_6LOWPAN 825             /* IPv6 over LoWPAN             */
 
 #define ARPHRD_VOID      0xFFFF        /* Void type, nothing is known */
 #define ARPHRD_NONE      0xFFFE        /* zero header length */
index 8fbc7ca878b47e6090176041f7e1d8afa3348580..3e6bd3c7445dd3b16b193a0ea67cc41ed4ef78c1 100644 (file)
@@ -349,11 +349,25 @@ enum {
        IFLA_BOND_MIN_LINKS,
        IFLA_BOND_LP_INTERVAL,
        IFLA_BOND_PACKETS_PER_SLAVE,
+       IFLA_BOND_AD_LACP_RATE,
+       IFLA_BOND_AD_SELECT,
+       IFLA_BOND_AD_INFO,
        __IFLA_BOND_MAX,
 };
 
 #define IFLA_BOND_MAX  (__IFLA_BOND_MAX - 1)
 
+enum {
+       IFLA_BOND_AD_INFO_AGGREGATOR,
+       IFLA_BOND_AD_INFO_NUM_PORTS,
+       IFLA_BOND_AD_INFO_ACTOR_KEY,
+       IFLA_BOND_AD_INFO_PARTNER_KEY,
+       IFLA_BOND_AD_INFO_PARTNER_MAC,
+       __IFLA_BOND_AD_INFO_MAX,
+};
+
+#define IFLA_BOND_AD_INFO_MAX  (__IFLA_BOND_AD_INFO_MAX - 1)
+
 /* SR-IOV virtual function management section */
 
 enum {
index e9d844c80c112f45a64935a3a6c963a91e579995..1988a02842cc539c20381c0fbe412e2ce4c7f30d 100644 (file)
@@ -26,8 +26,10 @@ struct sockaddr_ll {
 #define PACKET_MULTICAST       2               /* To group             */
 #define PACKET_OTHERHOST       3               /* To someone else      */
 #define PACKET_OUTGOING                4               /* Outgoing of any type */
-/* These ones are invisible by user level */
 #define PACKET_LOOPBACK                5               /* MC/BRD frame looped back */
+#define PACKET_USER            6               /* To user space        */
+#define PACKET_KERNEL          7               /* To kernel space      */
+/* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */
 #define PACKET_FASTROUTE       6               /* Fastrouted frame     */
 
 /* Packet socket options */
index bd969d77ce5203125b815b78eb6c7237d011f6c4..669a1f0b1d976d2f6045b539f18e1fccbadc6809 100644 (file)
@@ -14,7 +14,7 @@ enum {
        NETCONFA_FORWARDING,
        NETCONFA_RP_FILTER,
        NETCONFA_MC_FORWARDING,
-       NETCONFA_PROXY_ARP,
+       NETCONFA_PROXY_NEIGH,
        __NETCONFA_MAX
 };
 #define NETCONFA_MAX   (__NETCONFA_MAX - 1)
index f7dc0ebeeba552a147b1110fe383a4eb9d6e0b13..ef1b1f88ca18476f2166dd1007da3e373164f391 100644 (file)
@@ -53,6 +53,7 @@ enum nf_inet_hooks {
 
 enum {
        NFPROTO_UNSPEC =  0,
+       NFPROTO_INET   =  1,
        NFPROTO_IPV4   =  2,
        NFPROTO_ARP    =  3,
        NFPROTO_BRIDGE =  7,
index 17c3af2c4bb958b636ec8553056709769dd9d73b..1d973d2ba417247f4265d8dee6bf6566ae1f9047 100644 (file)
@@ -39,6 +39,7 @@ header-y += xt_TEE.h
 header-y += xt_TPROXY.h
 header-y += xt_addrtype.h
 header-y += xt_bpf.h
+header-y += xt_cgroup.h
 header-y += xt_cluster.h
 header-y += xt_comment.h
 header-y += xt_connbytes.h
@@ -54,8 +55,10 @@ header-y += xt_ecn.h
 header-y += xt_esp.h
 header-y += xt_hashlimit.h
 header-y += xt_helper.h
+header-y += xt_ipcomp.h
 header-y += xt_iprange.h
 header-y += xt_ipvs.h
+header-y += xt_l2tp.h
 header-y += xt_length.h
 header-y += xt_limit.h
 header-y += xt_mac.h
index bf0cc373ffb6ae02487e74ba478c024c3be3b477..1ad3659102b64d54a8ad814fd7be11132a136319 100644 (file)
@@ -4,10 +4,14 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter/nf_conntrack_tuple_common.h>
 
-#define NF_NAT_RANGE_MAP_IPS           1
-#define NF_NAT_RANGE_PROTO_SPECIFIED   2
-#define NF_NAT_RANGE_PROTO_RANDOM      4
-#define NF_NAT_RANGE_PERSISTENT                8
+#define NF_NAT_RANGE_MAP_IPS                   (1 << 0)
+#define NF_NAT_RANGE_PROTO_SPECIFIED           (1 << 1)
+#define NF_NAT_RANGE_PROTO_RANDOM              (1 << 2)
+#define NF_NAT_RANGE_PERSISTENT                        (1 << 3)
+#define NF_NAT_RANGE_PROTO_RANDOM_FULLY                (1 << 4)
+
+#define NF_NAT_RANGE_PROTO_RANDOM_ALL          \
+       (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
 
 struct nf_nat_ipv4_range {
        unsigned int                    flags;
index fbfd229a8e99e123108c6fc80dd962df683e5622..83c985a6170bd52938764732f45a70d09ae2a28e 100644 (file)
@@ -110,11 +110,13 @@ enum nft_table_flags {
  *
  * @NFTA_TABLE_NAME: name of the table (NLA_STRING)
  * @NFTA_TABLE_FLAGS: bitmask of enum nft_table_flags (NLA_U32)
+ * @NFTA_TABLE_USE: number of chains in this table (NLA_U32)
  */
 enum nft_table_attributes {
        NFTA_TABLE_UNSPEC,
        NFTA_TABLE_NAME,
        NFTA_TABLE_FLAGS,
+       NFTA_TABLE_USE,
        __NFTA_TABLE_MAX
 };
 #define NFTA_TABLE_MAX         (__NFTA_TABLE_MAX - 1)
@@ -529,6 +531,8 @@ enum nft_exthdr_attributes {
  * @NFT_META_NFTRACE: packet nftrace bit
  * @NFT_META_RTCLASSID: realm value of packet's route (skb->dst->tclassid)
  * @NFT_META_SECMARK: packet secmark (skb->secmark)
+ * @NFT_META_NFPROTO: netfilter protocol
+ * @NFT_META_L4PROTO: layer 4 protocol number
  */
 enum nft_meta_keys {
        NFT_META_LEN,
@@ -546,6 +550,8 @@ enum nft_meta_keys {
        NFT_META_NFTRACE,
        NFT_META_RTCLASSID,
        NFT_META_SECMARK,
+       NFT_META_NFPROTO,
+       NFT_META_L4PROTO,
 };
 
 /**
@@ -553,11 +559,13 @@ enum nft_meta_keys {
  *
  * @NFTA_META_DREG: destination register (NLA_U32)
  * @NFTA_META_KEY: meta data item to load (NLA_U32: nft_meta_keys)
+ * @NFTA_META_SREG: source register (NLA_U32)
  */
 enum nft_meta_attributes {
        NFTA_META_UNSPEC,
        NFTA_META_DREG,
        NFTA_META_KEY,
+       NFTA_META_SREG,
        __NFTA_META_MAX
 };
 #define NFTA_META_MAX          (__NFTA_META_MAX - 1)
@@ -601,12 +609,14 @@ enum nft_ct_keys {
  * @NFTA_CT_DREG: destination register (NLA_U32)
  * @NFTA_CT_KEY: conntrack data item to load (NLA_U32: nft_ct_keys)
  * @NFTA_CT_DIRECTION: direction in case of directional keys (NLA_U8)
+ * @NFTA_CT_SREG: source register (NLA_U32)
  */
 enum nft_ct_attributes {
        NFTA_CT_UNSPEC,
        NFTA_CT_DREG,
        NFTA_CT_KEY,
        NFTA_CT_DIRECTION,
+       NFTA_CT_SREG,
        __NFTA_CT_MAX
 };
 #define NFTA_CT_MAX            (__NFTA_CT_MAX - 1)
@@ -657,6 +667,26 @@ enum nft_log_attributes {
 };
 #define NFTA_LOG_MAX           (__NFTA_LOG_MAX - 1)
 
+/**
+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+ *
+ * @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
+ * @NFTA_QUEUE_TOTAL: number of queues to load balance packets on (NLA_U16)
+ * @NFTA_QUEUE_FLAGS: various flags (NLA_U16)
+ */
+enum nft_queue_attributes {
+       NFTA_QUEUE_UNSPEC,
+       NFTA_QUEUE_NUM,
+       NFTA_QUEUE_TOTAL,
+       NFTA_QUEUE_FLAGS,
+       __NFTA_QUEUE_MAX
+};
+#define NFTA_QUEUE_MAX         (__NFTA_QUEUE_MAX - 1)
+
+#define NFT_QUEUE_FLAG_BYPASS          0x01 /* for compatibility with v2 */
+#define NFT_QUEUE_FLAG_CPU_FANOUT      0x02 /* use current CPU (no hashing) */
+#define NFT_QUEUE_FLAG_MASK            0x03
+
 /**
  * enum nft_reject_types - nf_tables reject expression reject types
  *
index 0132bad79de7f6860120d13c6df2d508ad2d5d14..8dd819e2b5feddf4afa4ba0389b9e324973a9b9c 100644 (file)
@@ -47,6 +47,8 @@ enum nfqnl_attr_type {
        NFQA_CAP_LEN,                   /* __u32 length of captured packet */
        NFQA_SKB_INFO,                  /* __u32 skb meta information */
        NFQA_EXP,                       /* nf_conntrack_netlink.h */
+       NFQA_UID,                       /* __u32 sk uid */
+       NFQA_GID,                       /* __u32 sk gid */
 
        __NFQA_MAX
 };
@@ -99,7 +101,8 @@ enum nfqnl_attr_config {
 #define NFQA_CFG_F_FAIL_OPEN                   (1 << 0)
 #define NFQA_CFG_F_CONNTRACK                   (1 << 1)
 #define NFQA_CFG_F_GSO                         (1 << 2)
-#define NFQA_CFG_F_MAX                         (1 << 3)
+#define NFQA_CFG_F_UID_GID                     (1 << 3)
+#define NFQA_CFG_F_MAX                         (1 << 4)
 
 /* flags for NFQA_SKB_INFO */
 /* packet appears to have wrong checksums, but they are ok */
diff --git a/include/uapi/linux/netfilter/xt_cgroup.h b/include/uapi/linux/netfilter/xt_cgroup.h
new file mode 100644 (file)
index 0000000..43acb7e
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _UAPI_XT_CGROUP_H
+#define _UAPI_XT_CGROUP_H
+
+#include <linux/types.h>
+
+struct xt_cgroup_info {
+       __u32 id;
+       __u32 invert;
+};
+
+#endif /* _UAPI_XT_CGROUP_H */
diff --git a/include/uapi/linux/netfilter/xt_ipcomp.h b/include/uapi/linux/netfilter/xt_ipcomp.h
new file mode 100644 (file)
index 0000000..45c7e40
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _XT_IPCOMP_H
+#define _XT_IPCOMP_H
+
+#include <linux/types.h>
+
+struct xt_ipcomp {
+       __u32 spis[2];  /* Security Parameter Index */
+       __u8 invflags;  /* Inverse flags */
+       __u8 hdrres;    /* Test of the Reserved Filed */
+};
+
+/* Values for "invflags" field in struct xt_ipcomp. */
+#define XT_IPCOMP_INV_SPI      0x01    /* Invert the sense of spi. */
+#define XT_IPCOMP_INV_MASK     0x01    /* All possible flags. */
+
+#endif /*_XT_IPCOMP_H*/
diff --git a/include/uapi/linux/netfilter/xt_l2tp.h b/include/uapi/linux/netfilter/xt_l2tp.h
new file mode 100644 (file)
index 0000000..7dccfa0
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _LINUX_NETFILTER_XT_L2TP_H
+#define _LINUX_NETFILTER_XT_L2TP_H
+
+#include <linux/types.h>
+
+enum xt_l2tp_type {
+       XT_L2TP_TYPE_CONTROL,
+       XT_L2TP_TYPE_DATA,
+};
+
+/* L2TP matching stuff */
+struct xt_l2tp_info {
+       __u32 tid;                      /* tunnel id */
+       __u32 sid;                      /* session id */
+       __u8 version;                   /* L2TP protocol version */
+       __u8 type;                      /* L2TP packet type */
+       __u8 flags;                     /* which fields to match */
+};
+
+enum {
+       XT_L2TP_TID     = (1 << 0),     /* match L2TP tunnel id */
+       XT_L2TP_SID     = (1 << 1),     /* match L2TP session id */
+       XT_L2TP_VERSION = (1 << 2),     /* match L2TP protocol version */
+       XT_L2TP_TYPE    = (1 << 3),     /* match L2TP packet type */
+};
+
+#endif /* _LINUX_NETFILTER_XT_L2TP_H */
index 129b7b08714848279f3638019892a4dc0e9e6d65..91054fd660e083156f02b826f0a5b812d7faac26 100644 (file)
  *     other station that transmission must be blocked until the channel
  *     switch is complete.
  *
+ * @NL80211_CMD_VENDOR: Vendor-specified command/event. The command is specified
+ *     by the %NL80211_ATTR_VENDOR_ID attribute and a sub-command in
+ *     %NL80211_ATTR_VENDOR_SUBCMD. Parameter(s) can be transported in
+ *     %NL80211_ATTR_VENDOR_DATA.
+ *     For feature advertisement, the %NL80211_ATTR_VENDOR_DATA attribute is
+ *     used in the wiphy data as a nested attribute containing descriptions
+ *     (&struct nl80211_vendor_cmd_info) of the supported vendor commands.
+ *     This may also be sent as an event with the same attributes.
+ *
+ * @NL80211_CMD_SET_QOS_MAP: Set Interworking QoS mapping for IP DSCP values.
+ *     The QoS mapping information is included in %NL80211_ATTR_QOS_MAP. If
+ *     that attribute is not included, QoS mapping is disabled. Since this
+ *     QoS mapping is relevant for IP packets, it is only valid during an
+ *     association. This is cleared on disassociation and AP restart.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -860,6 +875,10 @@ enum nl80211_commands {
 
        NL80211_CMD_CHANNEL_SWITCH,
 
+       NL80211_CMD_VENDOR,
+
+       NL80211_CMD_SET_QOS_MAP,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
@@ -1520,6 +1539,22 @@ enum nl80211_commands {
  * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports
  *     10 MHz channel bandwidth.
  *
+ * @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode
+ *     Notification Element based on association request when used with
+ *     %NL80211_CMD_NEW_STATION; u8 attribute.
+ *
+ * @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if
+ *     %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet)
+ * @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command
+ * @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this
+ *     attribute is also used for vendor command feature advertisement
+ * @NL80211_ATTR_VENDOR_EVENTS: used for event list advertising in the wiphy
+ *     info, containing a nested array of possible events
+ *
+ * @NL80211_ATTR_QOS_MAP: IP DSCP mapping for Interworking QoS mapping. This
+ *     data is in the format defined for the payload of the QoS Map Set element
+ *     in IEEE Std 802.11-2012, 8.4.2.97.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1839,6 +1874,15 @@ enum nl80211_attrs {
        NL80211_ATTR_SUPPORT_5_MHZ,
        NL80211_ATTR_SUPPORT_10_MHZ,
 
+       NL80211_ATTR_OPMODE_NOTIF,
+
+       NL80211_ATTR_VENDOR_ID,
+       NL80211_ATTR_VENDOR_SUBCMD,
+       NL80211_ATTR_VENDOR_DATA,
+       NL80211_ATTR_VENDOR_EVENTS,
+
+       NL80211_ATTR_QOS_MAP,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -3083,21 +3127,35 @@ enum nl80211_key_attributes {
  *     in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with
  *     1 = 500 kbps) but without the IE length restriction (at most
  *     %NL80211_MAX_SUPP_RATES in a single array).
- * @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection
+ * @NL80211_TXRATE_HT: HT (MCS) rates allowed for TX rate selection
  *     in an array of MCS numbers.
+ * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection,
+ *     see &struct nl80211_txrate_vht
  * @__NL80211_TXRATE_AFTER_LAST: internal
  * @NL80211_TXRATE_MAX: highest TX rate attribute
  */
 enum nl80211_tx_rate_attributes {
        __NL80211_TXRATE_INVALID,
        NL80211_TXRATE_LEGACY,
-       NL80211_TXRATE_MCS,
+       NL80211_TXRATE_HT,
+       NL80211_TXRATE_VHT,
 
        /* keep last */
        __NL80211_TXRATE_AFTER_LAST,
        NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1
 };
 
+#define NL80211_TXRATE_MCS NL80211_TXRATE_HT
+#define NL80211_VHT_NSS_MAX            8
+
+/**
+ * struct nl80211_txrate_vht - VHT MCS/NSS txrate bitmap
+ * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.)
+ */
+struct nl80211_txrate_vht {
+       __u16 mcs[NL80211_VHT_NSS_MAX];
+};
+
 /**
  * enum nl80211_band - Frequency band
  * @NL80211_BAND_2GHZ: 2.4 GHz ISM band
@@ -3959,4 +4017,24 @@ enum nl80211_rxmgmt_flags {
        NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0,
 };
 
+/*
+ * If this flag is unset, the lower 24 bits are an OUI, if set
+ * a Linux nl80211 vendor ID is used (no such IDs are allocated
+ * yet, so that's not valid so far)
+ */
+#define NL80211_VENDOR_ID_IS_LINUX     0x80000000
+
+/**
+ * struct nl80211_vendor_cmd_info - vendor command data
+ * @vendor_id: If the %NL80211_VENDOR_ID_IS_LINUX flag is clear, then the
+ *     value is a 24-bit OUI; if it is set then a separately allocated ID
+ *     may be used, but no such IDs are allocated yet. New IDs should be
+ *     added to this file when needed.
+ * @subcmd: sub-command ID for the command
+ */
+struct nl80211_vendor_cmd_info {
+       __u32 vendor_id;
+       __u32 subcmd;
+};
+
 #endif /* __LINUX_NL80211_H */
index d120f9fe001783754bf27bcce1f4f4ebcf7e694e..970553cbbc8e9d69dca1167aedfbfee20947e257 100644 (file)
@@ -40,7 +40,15 @@ struct ovs_header {
 
 #define OVS_DATAPATH_FAMILY  "ovs_datapath"
 #define OVS_DATAPATH_MCGROUP "ovs_datapath"
-#define OVS_DATAPATH_VERSION 0x1
+
+/* V2:
+ *   - API users are expected to provide OVS_DP_ATTR_USER_FEATURES
+ *     when creating the datapath.
+ */
+#define OVS_DATAPATH_VERSION 2
+
+/* First OVS datapath version to support features */
+#define OVS_DP_VER_FEATURES 2
 
 enum ovs_datapath_cmd {
        OVS_DP_CMD_UNSPEC,
@@ -75,6 +83,7 @@ enum ovs_datapath_attr {
        OVS_DP_ATTR_UPCALL_PID,         /* Netlink PID to receive upcalls */
        OVS_DP_ATTR_STATS,              /* struct ovs_dp_stats */
        OVS_DP_ATTR_MEGAFLOW_STATS,     /* struct ovs_dp_megaflow_stats */
+       OVS_DP_ATTR_USER_FEATURES,      /* OVS_DP_F_*  */
        __OVS_DP_ATTR_MAX
 };
 
@@ -106,6 +115,9 @@ struct ovs_vport_stats {
        __u64   tx_dropped;             /* no space available in linux  */
 };
 
+/* Allow last Netlink attribute to be unaligned */
+#define OVS_DP_F_UNALIGNED     (1 << 0)
+
 /* Fixed logical ports. */
 #define OVSP_LOCAL      ((__u32)0)
 
index 4a98e85438a7706c5288deda0626d17ed312aa17..c870c2a71d65e9355c068b4148a8e4851cc11baf 100644 (file)
 #define  PCI_EXP_LNKSTA_CLS    0x000f  /* Current Link Speed */
 #define  PCI_EXP_LNKSTA_CLS_2_5GB 0x0001 /* Current Link Speed 2.5GT/s */
 #define  PCI_EXP_LNKSTA_CLS_5_0GB 0x0002 /* Current Link Speed 5.0GT/s */
+#define  PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */
 #define  PCI_EXP_LNKSTA_NLW    0x03f0  /* Negotiated Link Width */
+#define  PCI_EXP_LNKSTA_NLW_X1 0x0010  /* Current Link Width x1 */
+#define  PCI_EXP_LNKSTA_NLW_X2 0x0020  /* Current Link Width x2 */
+#define  PCI_EXP_LNKSTA_NLW_X4 0x0040  /* Current Link Width x4 */
+#define  PCI_EXP_LNKSTA_NLW_X8 0x0080  /* Current Link Width x8 */
 #define  PCI_EXP_LNKSTA_NLW_SHIFT 4    /* start of NLW mask in link status */
 #define  PCI_EXP_LNKSTA_LT     0x0800  /* Link Training */
 #define  PCI_EXP_LNKSTA_SLC    0x1000  /* Slot Clock Configuration */
index e1802d6153aec4d0c5fd81300dcde057d9bf8a59..959d454f76a185c87ce7fc223a229d37db2564f8 100644 (file)
@@ -679,6 +679,7 @@ enum perf_event_type {
         *
         *      { u64                   weight;   } && PERF_SAMPLE_WEIGHT
         *      { u64                   data_src; } && PERF_SAMPLE_DATA_SRC
+        *      { u64                   transaction; } && PERF_SAMPLE_TRANSACTION
         * };
         */
        PERF_RECORD_SAMPLE                      = 9,
index 4566993b8385a5baa0d41c31bc054594e565d614..d62316baae942c43b2558ed2768c88950516126c 100644 (file)
@@ -173,6 +173,8 @@ enum {
        TCA_TBF_PTAB,
        TCA_TBF_RATE64,
        TCA_TBF_PRATE64,
+       TCA_TBF_BURST,
+       TCA_TBF_PBURST,
        __TCA_TBF_MAX,
 };
 
@@ -523,6 +525,7 @@ enum {
        TCA_NETEM_LOSS,
        TCA_NETEM_RATE,
        TCA_NETEM_ECN,
+       TCA_NETEM_RATE64,
        __TCA_NETEM_MAX,
 };
 
@@ -815,4 +818,29 @@ struct tc_hhf_xstats {
        __u32   hh_tot_count;   /* number of captured heavy-hitters so far */
        __u32   hh_cur_count;   /* number of current heavy-hitters */
 };
+
+/* PIE */
+enum {
+       TCA_PIE_UNSPEC,
+       TCA_PIE_TARGET,
+       TCA_PIE_LIMIT,
+       TCA_PIE_TUPDATE,
+       TCA_PIE_ALPHA,
+       TCA_PIE_BETA,
+       TCA_PIE_ECN,
+       TCA_PIE_BYTEMODE,
+       __TCA_PIE_MAX
+};
+#define TCA_PIE_MAX   (__TCA_PIE_MAX - 1)
+
+struct tc_pie_xstats {
+       __u32 prob;             /* current probability */
+       __u32 delay;            /* current delay in ms */
+       __u32 avg_dq_rate;      /* current average dq_rate in bits/pie_time */
+       __u32 packets_in;       /* total number of packets enqueued */
+       __u32 dropped;          /* packets dropped due to pie_action */
+       __u32 overlimit;        /* dropped due to lack of space in queue */
+       __u32 maxq;             /* maximum queue size */
+       __u32 ecn_mark;         /* packets marked with ecn*/
+};
 #endif
index cb5157b55f324bfbca68417f0a266b10cafa5e13..54a37b13f2c4d77202d35d42e852689ddc9fcdd0 100644 (file)
@@ -35,6 +35,8 @@ enum {
        TCP_METRICS_ATTR_FOPEN_SYN_DROPS,       /* u16, count of drops */
        TCP_METRICS_ATTR_FOPEN_SYN_DROP_TS,     /* msecs age */
        TCP_METRICS_ATTR_FOPEN_COOKIE,          /* binary */
+       TCP_METRICS_ATTR_SADDR_IPV4,            /* u32 */
+       TCP_METRICS_ATTR_SADDR_IPV6,            /* binary */
 
        __TCP_METRICS_ATTR_MAX,
 };
index 65e12099ef89d9f3b5706858d956d8aabe427348..ae665ac59c36b6812a0470d5a7e0124c3e13a69f 100644 (file)
@@ -146,7 +146,7 @@ struct blkif_request_segment_aligned {
 struct blkif_request_rw {
        uint8_t        nr_segments;  /* number of segments                   */
        blkif_vdev_t   handle;       /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad1;        /* offsetof(blkif_request,u.rw.id) == 8 */
 #endif
        uint64_t       id;           /* private guest value, echoed in resp  */
@@ -163,7 +163,7 @@ struct blkif_request_discard {
        uint8_t        flag;         /* BLKIF_DISCARD_SECURE or zero.        */
 #define BLKIF_DISCARD_SECURE (1<<0)  /* ignored if discard-secure=0          */
        blkif_vdev_t   _pad1;        /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad2;        /* offsetof(blkif_req..,u.discard.id)==8*/
 #endif
        uint64_t       id;           /* private guest value, echoed in resp  */
@@ -175,7 +175,7 @@ struct blkif_request_discard {
 struct blkif_request_other {
        uint8_t      _pad1;
        blkif_vdev_t _pad2;        /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t     _pad3;        /* offsetof(blkif_req..,u.other.id)==8*/
 #endif
        uint64_t     id;           /* private guest value, echoed in resp  */
@@ -184,7 +184,7 @@ struct blkif_request_other {
 struct blkif_request_indirect {
        uint8_t        indirect_op;
        uint16_t       nr_segments;
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad1;        /* offsetof(blkif_...,u.indirect.id) == 8 */
 #endif
        uint64_t       id;
@@ -192,7 +192,7 @@ struct blkif_request_indirect {
        blkif_vdev_t   handle;
        uint16_t       _pad2;
        grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t      _pad3;         /* make it 64 byte aligned */
 #else
        uint64_t      _pad3;         /* make it 64 byte aligned */
index bbaf7d59c1bb14f166441e6532b55585790e4b52..bc010ee272b6cfec39892e6cb04b98cc06995e1a 100644 (file)
@@ -137,9 +137,10 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
 ###############################################################################
 ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
 X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509)
-X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509
-X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
+X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += $(objtree)/signing_key.x509
+X509_CERTIFICATES-raw := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
                                $(or $(realpath $(CERT)),$(CERT))))
+X509_CERTIFICATES := $(subst $(realpath $(objtree))/,,$(X509_CERTIFICATES-raw))
 
 ifeq ($(X509_CERTIFICATES),)
 $(warning *** No X.509 certificates found ***)
@@ -164,9 +165,9 @@ $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
 targets += $(obj)/.x509.list
 $(obj)/.x509.list:
        @echo $(X509_CERTIFICATES) >$@
+endif
 
 clean-files := x509_certificate_list .x509.list
-endif
 
 ifeq ($(CONFIG_MODULE_SIG),y)
 ###############################################################################
index 5253204afdcace55e89cda669aaf2896eba23aaa..9fd4246b04b8298ec608dbba4d9ee9997e105fbc 100644 (file)
@@ -22,6 +22,6 @@ void foo(void)
 #ifdef CONFIG_SMP
        DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS));
 #endif
-       DEFINE(BLOATED_SPINLOCKS, sizeof(spinlock_t) > sizeof(int));
+       DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t));
        /* End of constants */
 }
index 8b729c278b649c7c016786f6dac9886290ce794f..bc1dcabe92176636baf79c7ef52e597422aeaf75 100644 (file)
@@ -890,6 +890,16 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
                struct cgroup *cgrp = dentry->d_fsdata;
 
                BUG_ON(!(cgroup_is_dead(cgrp)));
+
+               /*
+                * XXX: cgrp->id is only used to look up css's.  As cgroup
+                * and css's lifetimes will be decoupled, it should be made
+                * per-subsystem and moved to css->id so that lookups are
+                * successful until the target css is released.
+                */
+               idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
+               cgrp->id = -1;
+
                call_rcu(&cgrp->rcu_head, cgroup_free_rcu);
        } else {
                struct cfent *cfe = __d_cfe(dentry);
@@ -4268,6 +4278,7 @@ static void css_release(struct percpu_ref *ref)
        struct cgroup_subsys_state *css =
                container_of(ref, struct cgroup_subsys_state, refcnt);
 
+       rcu_assign_pointer(css->cgroup->subsys[css->ss->subsys_id], NULL);
        call_rcu(&css->rcu_head, css_free_rcu_fn);
 }
 
@@ -4426,14 +4437,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
        root->number_of_cgroups++;
 
-       /* each css holds a ref to the cgroup's dentry and the parent css */
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
-
-               dget(dentry);
-               css_get(css->parent);
-       }
-
        /* hold a ref to the parent's dentry */
        dget(parent->dentry);
 
@@ -4445,6 +4448,13 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
                if (err)
                        goto err_destroy;
 
+               /* each css holds a ref to the cgroup's dentry and parent css */
+               dget(dentry);
+               css_get(css->parent);
+
+               /* mark it consumed for error path */
+               css_ar[ss->subsys_id] = NULL;
+
                if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
                    parent->parent) {
                        pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n",
@@ -4491,6 +4501,14 @@ err_free_cgrp:
        return err;
 
 err_destroy:
+       for_each_root_subsys(root, ss) {
+               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
+
+               if (css) {
+                       percpu_ref_cancel_init(&css->refcnt);
+                       ss->css_free(css);
+               }
+       }
        cgroup_destroy_locked(cgrp);
        mutex_unlock(&cgroup_mutex);
        mutex_unlock(&dentry->d_inode->i_mutex);
@@ -4652,8 +4670,12 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
         * will be invoked to perform the rest of destruction once the
         * percpu refs of all css's are confirmed to be killed.
         */
-       for_each_root_subsys(cgrp->root, ss)
-               kill_css(cgroup_css(cgrp, ss));
+       for_each_root_subsys(cgrp->root, ss) {
+               struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
+
+               if (css)
+                       kill_css(css);
+       }
 
        /*
         * Mark @cgrp dead.  This prevents further task migration and child
@@ -4722,14 +4744,6 @@ static void cgroup_destroy_css_killed(struct cgroup *cgrp)
        /* delete this cgroup from parent->children */
        list_del_rcu(&cgrp->sibling);
 
-       /*
-        * We should remove the cgroup object from idr before its grace
-        * period starts, so we won't be looking up a cgroup while the
-        * cgroup is being freed.
-        */
-       idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
-       cgrp->id = -1;
-
        dput(d);
 
        set_bit(CGRP_RELEASABLE, &parent->flags);
index 72348dc192c11e7a85560b67bc792415d969e22f..f5744010a8d2f980f1902279de41a866ceb00a37 100644 (file)
@@ -1396,6 +1396,8 @@ event_sched_out(struct perf_event *event,
        if (event->state != PERF_EVENT_STATE_ACTIVE)
                return;
 
+       perf_pmu_disable(event->pmu);
+
        event->state = PERF_EVENT_STATE_INACTIVE;
        if (event->pending_disable) {
                event->pending_disable = 0;
@@ -1412,6 +1414,8 @@ event_sched_out(struct perf_event *event,
                ctx->nr_freq--;
        if (event->attr.exclusive || !cpuctx->active_oncpu)
                cpuctx->exclusive = 0;
+
+       perf_pmu_enable(event->pmu);
 }
 
 static void
@@ -1652,6 +1656,7 @@ event_sched_in(struct perf_event *event,
                 struct perf_event_context *ctx)
 {
        u64 tstamp = perf_event_time(event);
+       int ret = 0;
 
        if (event->state <= PERF_EVENT_STATE_OFF)
                return 0;
@@ -1674,10 +1679,13 @@ event_sched_in(struct perf_event *event,
         */
        smp_wmb();
 
+       perf_pmu_disable(event->pmu);
+
        if (event->pmu->add(event, PERF_EF_START)) {
                event->state = PERF_EVENT_STATE_INACTIVE;
                event->oncpu = -1;
-               return -EAGAIN;
+               ret = -EAGAIN;
+               goto out;
        }
 
        event->tstamp_running += tstamp - event->tstamp_stopped;
@@ -1693,7 +1701,10 @@ event_sched_in(struct perf_event *event,
        if (event->attr.exclusive)
                cpuctx->exclusive = 1;
 
-       return 0;
+out:
+       perf_pmu_enable(event->pmu);
+
+       return ret;
 }
 
 static int
@@ -2743,6 +2754,8 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                if (!event_filter_match(event))
                        continue;
 
+               perf_pmu_disable(event->pmu);
+
                hwc = &event->hw;
 
                if (hwc->interrupts == MAX_INTERRUPTS) {
@@ -2752,7 +2765,7 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                }
 
                if (!event->attr.freq || !event->attr.sample_freq)
-                       continue;
+                       goto next;
 
                /*
                 * stop the event and update event->count
@@ -2774,6 +2787,8 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                        perf_adjust_period(event, period, delta, false);
 
                event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);
+       next:
+               perf_pmu_enable(event->pmu);
        }
 
        perf_pmu_enable(ctx->pmu);
index 728d5be9548ce61913c85e14303248363eae0a31..5721f0e3f2da4d1d4bcbc788b4016c944bbfea03 100644 (file)
@@ -537,6 +537,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
        spin_lock_init(&mm->page_table_lock);
        mm_init_aio(mm);
        mm_init_owner(mm, p);
+       clear_tlb_flush_pending(mm);
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
index b462fa197517b6176701fa860cdb966bc44a69ba..aa6a8aadb911fb323b4662a4652c95ff4319f0c5 100644 (file)
@@ -19,6 +19,12 @@ EXPORT_SYMBOL(system_freezing_cnt);
 bool pm_freezing;
 bool pm_nosig_freezing;
 
+/*
+ * Temporary export for the deadlock workaround in ata_scsi_hotplug().
+ * Remove once the hack becomes unnecessary.
+ */
+EXPORT_SYMBOL_GPL(pm_freezing);
+
 /* protects freezing and frozen transitions */
 static DEFINE_SPINLOCK(freezer_lock);
 
index d0d8fca54065d72a248b0f8b76346bb72c6e2441..9c970167e4025f01be6bd696499eec2504c72ef7 100644 (file)
@@ -1680,6 +1680,7 @@ int kernel_kexec(void)
        {
                kexec_in_progress = true;
                kernel_restart_prepare(NULL);
+               migrate_to_reboot_cpu();
                printk(KERN_EMERG "Starting new kernel\n");
                machine_shutdown();
        }
index 463aa6736751a0a12d949ddeb93330b6067f053b..eacb8bd8cab4e1205230ecfdde12483be9846cf7 100644 (file)
@@ -81,6 +81,7 @@ void pm_vt_switch_unregister(struct device *dev)
        list_for_each_entry(tmp, &pm_vt_switch_list, head) {
                if (tmp->dev == dev) {
                        list_del(&tmp->head);
+                       kfree(tmp);
                        break;
                }
        }
index f813b3474646c5b320a19d9a8997349bdd14d68e..662c83fc16b77ed79b9474c681848858666055e0 100644 (file)
@@ -104,7 +104,7 @@ int unregister_reboot_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_reboot_notifier);
 
-static void migrate_to_reboot_cpu(void)
+void migrate_to_reboot_cpu(void)
 {
        /* The boot cpu is always logical cpu 0 */
        int cpu = reboot_cpu;
index 19af58f3a261c02b14f0fda441658099f3a1eed1..a88f4a485c5e5f92190dd5bf784600d79d5f8f18 100644 (file)
@@ -4902,6 +4902,7 @@ DEFINE_PER_CPU(struct sched_domain *, sd_asym);
 static void update_top_cache_domain(int cpu)
 {
        struct sched_domain *sd;
+       struct sched_domain *busy_sd = NULL;
        int id = cpu;
        int size = 1;
 
@@ -4909,9 +4910,9 @@ static void update_top_cache_domain(int cpu)
        if (sd) {
                id = cpumask_first(sched_domain_span(sd));
                size = cpumask_weight(sched_domain_span(sd));
-               sd = sd->parent; /* sd_busy */
+               busy_sd = sd->parent; /* sd_busy */
        }
-       rcu_assign_pointer(per_cpu(sd_busy, cpu), sd);
+       rcu_assign_pointer(per_cpu(sd_busy, cpu), busy_sd);
 
        rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
        per_cpu(sd_llc_size, cpu) = size;
index 9030da7bcb15f62f5d4873857c81e920e61fe052..c7395d97e4cb7c33f26925569adff8f7e3007d4e 100644 (file)
@@ -1738,6 +1738,13 @@ void task_numa_work(struct callback_head *work)
                    (vma->vm_file && (vma->vm_flags & (VM_READ|VM_WRITE)) == (VM_READ)))
                        continue;
 
+               /*
+                * Skip inaccessible VMAs to avoid any confusion between
+                * PROT_NONE and NUMA hinting ptes
+                */
+               if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+                       continue;
+
                do {
                        start = max(start, vma->vm_start);
                        end = ALIGN(start + (pages << PAGE_SHIFT), HPAGE_SIZE);
index 7d57275fc396d1c56475c707888f1f95fd84142b..1c4065575fa2c44d91250455db38638d728788e8 100644 (file)
@@ -901,6 +901,13 @@ inc_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio)
 {
        struct rq *rq = rq_of_rt_rq(rt_rq);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * Change rq's cpupri only if rt_rq is the top queue.
+        */
+       if (&rq->rt != rt_rq)
+               return;
+#endif
        if (rq->online && prio < prev_prio)
                cpupri_set(&rq->rd->cpupri, rq->cpu, prio);
 }
@@ -910,6 +917,13 @@ dec_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio)
 {
        struct rq *rq = rq_of_rt_rq(rt_rq);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * Change rq's cpupri only if rt_rq is the top queue.
+        */
+       if (&rq->rt != rt_rq)
+               return;
+#endif
        if (rq->online && rt_rq->highest_prio.curr != prev_prio)
                cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio.curr);
 }
index 0e9f9eaade2f6a2dd0e729cd2d3bb38b4f6f8ec0..72a0f81dc5a801e62ef5bb400c068705851b32f6 100644 (file)
@@ -775,7 +775,7 @@ static int ftrace_profile_init(void)
        int cpu;
        int ret = 0;
 
-       for_each_online_cpu(cpu) {
+       for_each_possible_cpu(cpu) {
                ret = ftrace_profile_init_cpu(cpu);
                if (ret)
                        break;
index a3a0dbfda32957616f143ae2722541a5846c0a62..c006131beb77c5151f92cacb9e11e6a3b1defe1b 100644 (file)
@@ -51,9 +51,9 @@ struct user_namespace init_user_ns = {
        .owner = GLOBAL_ROOT_UID,
        .group = GLOBAL_ROOT_GID,
        .proc_inum = PROC_USER_INIT_INO,
-#ifdef CONFIG_KEYS_KERBEROS_CACHE
-       .krb_cache_register_sem =
-       __RWSEM_INITIALIZER(init_user_ns.krb_cache_register_sem),
+#ifdef CONFIG_PERSISTENT_KEYRINGS
+       .persistent_keyring_register_sem =
+       __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
 #endif
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
index eb69f352401de910552fb7f28959b38f4746a878..723bbe04a0b0511976d3778a4df94cb2974eb9c8 100644 (file)
@@ -543,7 +543,7 @@ config ZSWAP
 
 config MEM_SOFT_DIRTY
        bool "Track memory changes"
-       depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY
+       depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY && PROC_FS
        select PROC_PAGE_MONITOR
        help
          This option enables memory changes tracking by introducing a
index 805165bcd3dd0ab8f27bbff2c9105927ed803c15..f58bcd016f432dd094d6f6378aa53f9799d30811 100644 (file)
@@ -134,6 +134,10 @@ static void update_pageblock_skip(struct compact_control *cc,
                        bool migrate_scanner)
 {
        struct zone *zone = cc->zone;
+
+       if (cc->ignore_skip_hint)
+               return;
+
        if (!page)
                return;
 
index 33a5dc492810d59eae0c7069e60dd3bdd9c8a374..7de1bf85f6833422e16161445b71e328fad2e1f6 100644 (file)
@@ -882,6 +882,10 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                ret = 0;
                goto out_unlock;
        }
+
+       /* mmap_sem prevents this happening but warn if that changes */
+       WARN_ON(pmd_trans_migrating(pmd));
+
        if (unlikely(pmd_trans_splitting(pmd))) {
                /* split huge page running from under us */
                spin_unlock(src_ptl);
@@ -1243,6 +1247,10 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
        if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd))
                return ERR_PTR(-EFAULT);
 
+       /* Full NUMA hinting faults to serialise migration in fault paths */
+       if ((flags & FOLL_NUMA) && pmd_numa(*pmd))
+               goto out;
+
        page = pmd_page(*pmd);
        VM_BUG_ON(!PageHead(page));
        if (flags & FOLL_TOUCH) {
@@ -1295,6 +1303,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(!pmd_same(pmd, *pmdp)))
                goto out_unlock;
 
+       /*
+        * If there are potential migrations, wait for completion and retry
+        * without disrupting NUMA hinting information. Do not relock and
+        * check_same as the page may no longer be mapped.
+        */
+       if (unlikely(pmd_trans_migrating(*pmdp))) {
+               spin_unlock(ptl);
+               wait_migrate_huge_page(vma->anon_vma, pmdp);
+               goto out;
+       }
+
        page = pmd_page(pmd);
        BUG_ON(is_huge_zero_page(page));
        page_nid = page_to_nid(page);
@@ -1323,23 +1342,22 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                /* If the page was locked, there are no parallel migrations */
                if (page_locked)
                        goto clear_pmdnuma;
+       }
 
-               /*
-                * Otherwise wait for potential migrations and retry. We do
-                * relock and check_same as the page may no longer be mapped.
-                * As the fault is being retried, do not account for it.
-                */
+       /* Migration could have started since the pmd_trans_migrating check */
+       if (!page_locked) {
                spin_unlock(ptl);
                wait_on_page_locked(page);
                page_nid = -1;
                goto out;
        }
 
-       /* Page is misplaced, serialise migrations and parallel THP splits */
+       /*
+        * Page is misplaced. Page lock serialises migrations. Acquire anon_vma
+        * to serialises splits
+        */
        get_page(page);
        spin_unlock(ptl);
-       if (!page_locked)
-               lock_page(page);
        anon_vma = page_lock_anon_vma_read(page);
 
        /* Confirm the PMD did not change while page_table_lock was released */
@@ -1351,6 +1369,13 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                goto out_unlock;
        }
 
+       /* Bail if we fail to protect against THP splits for any reason */
+       if (unlikely(!anon_vma)) {
+               put_page(page);
+               page_nid = -1;
+               goto clear_pmdnuma;
+       }
+
        /*
         * Migrate the THP to the requested node, returns with page unlocked
         * and pmd_numa cleared.
@@ -1517,6 +1542,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                ret = 1;
                if (!prot_numa) {
                        entry = pmdp_get_and_clear(mm, addr, pmd);
+                       if (pmd_numa(entry))
+                               entry = pmd_mknonnuma(entry);
                        entry = pmd_modify(entry, newprot);
                        ret = HPAGE_PMD_NR;
                        BUG_ON(pmd_write(entry));
@@ -1531,7 +1558,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                         */
                        if (!is_huge_zero_page(page) &&
                            !pmd_numa(*pmd)) {
-                               entry = pmdp_get_and_clear(mm, addr, pmd);
+                               entry = *pmd;
                                entry = pmd_mknuma(entry);
                                ret = HPAGE_PMD_NR;
                        }
index b7c171602ba1ebb8697f0c523f1a62f51c3a2fa4..db08af92c6fce92d9e0d61ca5752aa003c52c3f2 100644 (file)
@@ -1505,10 +1505,16 @@ static int soft_offline_huge_page(struct page *page, int flags)
                if (ret > 0)
                        ret = -EIO;
        } else {
-               set_page_hwpoison_huge_page(hpage);
-               dequeue_hwpoisoned_huge_page(hpage);
-               atomic_long_add(1 << compound_order(hpage),
-                               &num_poisoned_pages);
+               /* overcommit hugetlb page will be freed to buddy */
+               if (PageHuge(page)) {
+                       set_page_hwpoison_huge_page(hpage);
+                       dequeue_hwpoisoned_huge_page(hpage);
+                       atomic_long_add(1 << compound_order(hpage),
+                                       &num_poisoned_pages);
+               } else {
+                       SetPageHWPoison(page);
+                       atomic_long_inc(&num_poisoned_pages);
+               }
        }
        return ret;
 }
index 5d9025f3b3e1cd65bd97655ee95d6cd2f390ce5b..6768ce9e57d29b6d8076b11c62c2097662f334d5 100644 (file)
@@ -4271,7 +4271,7 @@ void copy_user_huge_page(struct page *dst, struct page *src,
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */
 
-#if USE_SPLIT_PTE_PTLOCKS && BLOATED_SPINLOCKS
+#if USE_SPLIT_PTE_PTLOCKS && ALLOC_SPLIT_PTLOCKS
 bool ptlock_alloc(struct page *page)
 {
        spinlock_t *ptl;
index eca4a3129129751208b41cfe808e9e31e5dc7b5f..0cd2c4d4e2703f88f56b957b6f442a531fbd2e1f 100644 (file)
@@ -1197,14 +1197,16 @@ static struct page *new_vma_page(struct page *page, unsigned long private, int *
                        break;
                vma = vma->vm_next;
        }
+
+       if (PageHuge(page)) {
+               if (vma)
+                       return alloc_huge_page_noerr(vma, address, 1);
+               else
+                       return NULL;
+       }
        /*
-        * queue_pages_range() confirms that @page belongs to some vma,
-        * so vma shouldn't be NULL.
+        * if !vma, alloc_page_vma() will use task or system default policy
         */
-       BUG_ON(!vma);
-
-       if (PageHuge(page))
-               return alloc_huge_page_noerr(vma, address, 1);
        return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
 }
 #else
@@ -1318,7 +1320,7 @@ static long do_mbind(unsigned long start, unsigned long len,
                if (nr_failed && (flags & MPOL_MF_STRICT))
                        err = -EIO;
        } else
-               putback_lru_pages(&pagelist);
+               putback_movable_pages(&pagelist);
 
        up_write(&mm->mmap_sem);
  mpol_out:
index bb940045fe8595842ed58f2e32f87b83d40485e1..9194375b230729fead356e8dd3c8f6bb951415ab 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/hugetlb_cgroup.h>
 #include <linux/gfp.h>
 #include <linux/balloon_compaction.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/tlbflush.h>
 
@@ -316,14 +317,15 @@ static inline bool buffer_migrate_lock_buffers(struct buffer_head *head,
  */
 int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode)
+               struct buffer_head *head, enum migrate_mode mode,
+               int extra_count)
 {
-       int expected_count = 0;
+       int expected_count = 1 + extra_count;
        void **pslot;
 
        if (!mapping) {
                /* Anonymous page without mapping */
-               if (page_count(page) != 1)
+               if (page_count(page) != expected_count)
                        return -EAGAIN;
                return MIGRATEPAGE_SUCCESS;
        }
@@ -333,7 +335,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
        pslot = radix_tree_lookup_slot(&mapping->page_tree,
                                        page_index(page));
 
-       expected_count = 2 + page_has_private(page);
+       expected_count += 1 + page_has_private(page);
        if (page_count(page) != expected_count ||
                radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) {
                spin_unlock_irq(&mapping->tree_lock);
@@ -583,7 +585,7 @@ int migrate_page(struct address_space *mapping,
 
        BUG_ON(PageWriteback(page));    /* Writeback must be complete */
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode);
+       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -610,7 +612,7 @@ int buffer_migrate_page(struct address_space *mapping,
 
        head = page_buffers(page);
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, head, mode);
+       rc = migrate_page_move_mapping(mapping, newpage, page, head, mode, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -1654,6 +1656,18 @@ int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
        return 1;
 }
 
+bool pmd_trans_migrating(pmd_t pmd)
+{
+       struct page *page = pmd_page(pmd);
+       return PageLocked(page);
+}
+
+void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd)
+{
+       struct page *page = pmd_page(*pmd);
+       wait_on_page_locked(page);
+}
+
 /*
  * Attempt to migrate a misplaced page to the specified destination
  * node. Caller is expected to have an elevated reference count on
@@ -1716,12 +1730,14 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                                struct page *page, int node)
 {
        spinlock_t *ptl;
-       unsigned long haddr = address & HPAGE_PMD_MASK;
        pg_data_t *pgdat = NODE_DATA(node);
        int isolated = 0;
        struct page *new_page = NULL;
        struct mem_cgroup *memcg = NULL;
        int page_lru = page_is_file_cache(page);
+       unsigned long mmun_start = address & HPAGE_PMD_MASK;
+       unsigned long mmun_end = mmun_start + HPAGE_PMD_SIZE;
+       pmd_t orig_entry;
 
        /*
         * Rate-limit the amount of data that is being migrated to a node.
@@ -1744,6 +1760,9 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                goto out_fail;
        }
 
+       if (mm_tlb_flush_pending(mm))
+               flush_tlb_range(vma, mmun_start, mmun_end);
+
        /* Prepare a page as a migration target */
        __set_page_locked(new_page);
        SetPageSwapBacked(new_page);
@@ -1755,9 +1774,12 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
        WARN_ON(PageLRU(new_page));
 
        /* Recheck the target PMD */
+       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
        ptl = pmd_lock(mm, pmd);
-       if (unlikely(!pmd_same(*pmd, entry))) {
+       if (unlikely(!pmd_same(*pmd, entry) || page_count(page) != 2)) {
+fail_putback:
                spin_unlock(ptl);
+               mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
                /* Reverse changes made by migrate_page_copy() */
                if (TestClearPageActive(new_page))
@@ -1774,7 +1796,8 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                putback_lru_page(page);
                mod_zone_page_state(page_zone(page),
                         NR_ISOLATED_ANON + page_lru, -HPAGE_PMD_NR);
-               goto out_fail;
+
+               goto out_unlock;
        }
 
        /*
@@ -1786,16 +1809,35 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
         */
        mem_cgroup_prepare_migration(page, new_page, &memcg);
 
+       orig_entry = *pmd;
        entry = mk_pmd(new_page, vma->vm_page_prot);
-       entry = pmd_mknonnuma(entry);
-       entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
        entry = pmd_mkhuge(entry);
+       entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
 
-       pmdp_clear_flush(vma, haddr, pmd);
-       set_pmd_at(mm, haddr, pmd, entry);
-       page_add_new_anon_rmap(new_page, vma, haddr);
+       /*
+        * Clear the old entry under pagetable lock and establish the new PTE.
+        * Any parallel GUP will either observe the old page blocking on the
+        * page lock, block on the page table lock or observe the new page.
+        * The SetPageUptodate on the new page and page_add_new_anon_rmap
+        * guarantee the copy is visible before the pagetable update.
+        */
+       flush_cache_range(vma, mmun_start, mmun_end);
+       page_add_new_anon_rmap(new_page, vma, mmun_start);
+       pmdp_clear_flush(vma, mmun_start, pmd);
+       set_pmd_at(mm, mmun_start, pmd, entry);
+       flush_tlb_range(vma, mmun_start, mmun_end);
        update_mmu_cache_pmd(vma, address, &entry);
+
+       if (page_count(page) != 2) {
+               set_pmd_at(mm, mmun_start, pmd, orig_entry);
+               flush_tlb_range(vma, mmun_start, mmun_end);
+               update_mmu_cache_pmd(vma, address, &entry);
+               page_remove_rmap(new_page);
+               goto fail_putback;
+       }
+
        page_remove_rmap(page);
+
        /*
         * Finish the charge transaction under the page table lock to
         * prevent split_huge_page() from dividing up the charge
@@ -1803,6 +1845,7 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
         */
        mem_cgroup_end_migration(memcg, page, new_page, true);
        spin_unlock(ptl);
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
        unlock_page(new_page);
        unlock_page(page);
@@ -1820,10 +1863,15 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
 out_fail:
        count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
 out_dropref:
-       entry = pmd_mknonnuma(entry);
-       set_pmd_at(mm, haddr, pmd, entry);
-       update_mmu_cache_pmd(vma, address, &entry);
+       ptl = pmd_lock(mm, pmd);
+       if (pmd_same(*pmd, entry)) {
+               entry = pmd_mknonnuma(entry);
+               set_pmd_at(mm, mmun_start, pmd, entry);
+               update_mmu_cache_pmd(vma, address, &entry);
+       }
+       spin_unlock(ptl);
 
+out_unlock:
        unlock_page(page);
        put_page(page);
        return 0;
index 26667971c824b08ca3dae7188a965e1e4efe0b79..bb53a6591aea1373d6bc74d5bb3e847650af8d24 100644 (file)
@@ -52,17 +52,21 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                        pte_t ptent;
                        bool updated = false;
 
-                       ptent = ptep_modify_prot_start(mm, addr, pte);
                        if (!prot_numa) {
+                               ptent = ptep_modify_prot_start(mm, addr, pte);
+                               if (pte_numa(ptent))
+                                       ptent = pte_mknonnuma(ptent);
                                ptent = pte_modify(ptent, newprot);
                                updated = true;
                        } else {
                                struct page *page;
 
+                               ptent = *pte;
                                page = vm_normal_page(vma, addr, oldpte);
                                if (page) {
                                        if (!pte_numa(oldpte)) {
                                                ptent = pte_mknuma(ptent);
+                                               set_pte_at(mm, addr, pte, ptent);
                                                updated = true;
                                        }
                                }
@@ -79,7 +83,10 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 
                        if (updated)
                                pages++;
-                       ptep_modify_prot_commit(mm, addr, pte, ptent);
+
+                       /* Only !prot_numa always clears the pte */
+                       if (!prot_numa)
+                               ptep_modify_prot_commit(mm, addr, pte, ptent);
                } else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) {
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
 
@@ -181,6 +188,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
        BUG_ON(addr >= end);
        pgd = pgd_offset(mm, addr);
        flush_cache_range(vma, addr, end);
+       set_tlb_flush_pending(mm);
        do {
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
@@ -192,6 +200,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
        /* Only flush the TLB if we actually modified any entries: */
        if (pages)
                flush_tlb_range(vma, start, end);
+       clear_tlb_flush_pending(mm);
 
        return pages;
 }
index 580a5f075ed0ab6e3047351a8271b1f053e35774..5248fe070aa4e9f94b4be087aa8957e16cf16c1f 100644 (file)
@@ -1816,7 +1816,7 @@ static void zlc_clear_zones_full(struct zonelist *zonelist)
 
 static bool zone_local(struct zone *local_zone, struct zone *zone)
 {
-       return node_distance(local_zone->node, zone->node) == LOCAL_DISTANCE;
+       return local_zone->node == zone->node;
 }
 
 static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
@@ -1913,18 +1913,17 @@ zonelist_scan:
                 * page was allocated in should have no effect on the
                 * time the page has in memory before being reclaimed.
                 *
-                * When zone_reclaim_mode is enabled, try to stay in
-                * local zones in the fastpath.  If that fails, the
-                * slowpath is entered, which will do another pass
-                * starting with the local zones, but ultimately fall
-                * back to remote zones that do not partake in the
-                * fairness round-robin cycle of this zonelist.
+                * Try to stay in local zones in the fastpath.  If
+                * that fails, the slowpath is entered, which will do
+                * another pass starting with the local zones, but
+                * ultimately fall back to remote zones that do not
+                * partake in the fairness round-robin cycle of this
+                * zonelist.
                 */
                if (alloc_flags & ALLOC_WMARK_LOW) {
                        if (zone_page_state(zone, NR_ALLOC_BATCH) <= 0)
                                continue;
-                       if (zone_reclaim_mode &&
-                           !zone_local(preferred_zone, zone))
+                       if (!zone_local(preferred_zone, zone))
                                continue;
                }
                /*
@@ -2390,7 +2389,7 @@ static void prepare_slowpath(gfp_t gfp_mask, unsigned int order,
                 * thrash fairness information for zones that are not
                 * actually part of this zonelist's round-robin cycle.
                 */
-               if (zone_reclaim_mode && !zone_local(preferred_zone, zone))
+               if (!zone_local(preferred_zone, zone))
                        continue;
                mod_zone_page_state(zone, NR_ALLOC_BATCH,
                                    high_wmark_pages(zone) -
index cbb38545d9d6ab8d96ebcdb001ed9e19db772f59..a8b9199259342df9cafb84be53010eb2206ebece 100644 (file)
@@ -110,9 +110,10 @@ int pmdp_clear_flush_young(struct vm_area_struct *vma,
 pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address,
                       pte_t *ptep)
 {
+       struct mm_struct *mm = (vma)->vm_mm;
        pte_t pte;
-       pte = ptep_get_and_clear((vma)->vm_mm, address, ptep);
-       if (pte_accessible(pte))
+       pte = ptep_get_and_clear(mm, address, ptep);
+       if (pte_accessible(mm, pte))
                flush_tlb_page(vma, address);
        return pte;
 }
@@ -191,6 +192,9 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
 void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                     pmd_t *pmdp)
 {
+       pmd_t entry = *pmdp;
+       if (pmd_numa(entry))
+               entry = pmd_mknonnuma(entry);
        set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(*pmdp));
        flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
 }
index 55c8b8dc9ffb0c349eb63ad20a8d7bbcc2e9b25d..068522d8502a58e9465a963e68c37ce4ccf635d7 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -600,7 +600,11 @@ pte_t *__page_check_address(struct page *page, struct mm_struct *mm,
        spinlock_t *ptl;
 
        if (unlikely(PageHuge(page))) {
+               /* when pud is not present, pte will be NULL */
                pte = huge_pte_offset(mm, address);
+               if (!pte)
+                       return NULL;
+
                ptl = huge_pte_lockptr(page_hstate(page), mm, pte);
                goto check;
        }
index 762896ebfcf505348a659c83d8720b48e8b58c86..47c908f1f626a4d4a2de96b9f4a648ad386d4357 100644 (file)
@@ -530,6 +530,23 @@ static const struct header_ops vlan_header_ops = {
        .parse   = eth_header_parse,
 };
 
+static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev,
+                                    unsigned short type,
+                                    const void *daddr, const void *saddr,
+                                    unsigned int len)
+{
+       struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+       struct net_device *real_dev = vlan->real_dev;
+
+       return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
+}
+
+static const struct header_ops vlan_passthru_header_ops = {
+       .create  = vlan_passthru_hard_header,
+       .rebuild = dev_rebuild_header,
+       .parse   = eth_header_parse,
+};
+
 static struct device_type vlan_type = {
        .name   = "vlan",
 };
@@ -573,7 +590,7 @@ static int vlan_dev_init(struct net_device *dev)
 
        dev->needed_headroom = real_dev->needed_headroom;
        if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
-               dev->header_ops      = real_dev->header_ops;
+               dev->header_ops      = &vlan_passthru_header_ops;
                dev->hard_header_len = real_dev->hard_header_len;
        } else {
                dev->header_ops      = &vlan_header_ops;
index d334678c0bd8706d7c3efb6c0f35d0d62102c360..e411046a62e3f0fe82281bc6b97dd8a1183558d1 100644 (file)
@@ -238,12 +238,19 @@ config XPS
        depends on SMP
        default y
 
-config NETPRIO_CGROUP
+config CGROUP_NET_PRIO
        tristate "Network priority cgroup"
        depends on CGROUPS
        ---help---
          Cgroup subsystem for use in assigning processes to network priorities on
-         a per-interface basis
+         a per-interface basis.
+
+config CGROUP_NET_CLASSID
+       boolean "Network classid cgroup"
+       depends on CGROUPS
+       ---help---
+         Cgroup subsystem for use as general purpose socket classid marker that is
+         being used in cls_cgroup and for netfilter matching.
 
 config NET_RX_BUSY_POLL
        boolean
index fa780b76630e4def219fc5f464554a4361721229..2b2dc473e1f781591796d06fe4711eacb8fa88aa 100644 (file)
@@ -5,7 +5,6 @@
 config BATMAN_ADV
        tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
        depends on NET
-       select CRC16
        select LIBCRC32C
         default n
        help
index 4f4aabbd8eab24c4d12983ccf656966f4f7084b0..42df18f877e9304a515a30f2122ae0c324984356 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+# Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
 #
 # Marek Lindner, Simon Wunderlich
 #
@@ -13,9 +13,7 @@
 # General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 
 obj-$(CONFIG_BATMAN_ADV) += batman-adv.o
index a4808c29ea3d3cdb95021c2c7130735cf21c3955..4e49666f8c653d8751e20692587f028b99001677 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_BAT_ALGO_H_
index a2b480a908723a37d47d14bd76e63628518e6561..921ac20cf6900cc308a3973d3ff400af556fd61a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -274,7 +272,14 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
        if (!neigh_node)
                goto out;
 
-       spin_lock_init(&neigh_node->bat_iv.lq_update_lock);
+       if (!atomic_inc_not_zero(&hard_iface->refcount)) {
+               kfree(neigh_node);
+               neigh_node = NULL;
+               goto out;
+       }
+
+       neigh_node->orig_node = orig_neigh;
+       neigh_node->if_incoming = hard_iface;
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                   "Creating new neighbor %pM for orig_node %pM on interface %s\n",
@@ -307,9 +312,9 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
        hard_iface->bat_iv.ogm_buff = ogm_buff;
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
-       batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
-       batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
-       batadv_ogm_packet->header.ttl = 2;
+       batadv_ogm_packet->packet_type = BATADV_IV_OGM;
+       batadv_ogm_packet->version = BATADV_COMPAT_VERSION;
+       batadv_ogm_packet->ttl = 2;
        batadv_ogm_packet->flags = BATADV_NO_FLAGS;
        batadv_ogm_packet->reserved = 0;
        batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
@@ -346,7 +351,7 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
        batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
-       batadv_ogm_packet->header.ttl = BATADV_TTL;
+       batadv_ogm_packet->ttl = BATADV_TTL;
 }
 
 /* when do we schedule our own ogm to be sent */
@@ -435,7 +440,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
                           fwd_str, (packet_num > 0 ? "aggregated " : ""),
                           batadv_ogm_packet->orig,
                           ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl,
+                          batadv_ogm_packet->tq, batadv_ogm_packet->ttl,
                           (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
                            "on" : "off"),
                           hard_iface->net_dev->name,
@@ -461,17 +466,9 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
 /* send a batman ogm packet */
 static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
 {
-       struct batadv_hard_iface *hard_iface;
        struct net_device *soft_iface;
        struct batadv_priv *bat_priv;
        struct batadv_hard_iface *primary_if = NULL;
-       struct batadv_ogm_packet *batadv_ogm_packet;
-       unsigned char directlink;
-       uint8_t *packet_pos;
-
-       packet_pos = forw_packet->skb->data;
-       batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
-       directlink = (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 1 : 0);
 
        if (!forw_packet->if_incoming) {
                pr_err("Error - can't forward packet: incoming iface not specified\n");
@@ -481,59 +478,48 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
        soft_iface = forw_packet->if_incoming->soft_iface;
        bat_priv = netdev_priv(soft_iface);
 
-       if (forw_packet->if_incoming->if_status != BATADV_IF_ACTIVE)
+       if (WARN_ON(!forw_packet->if_outgoing))
                goto out;
 
-       primary_if = batadv_primary_if_get_selected(bat_priv);
-       if (!primary_if)
+       if (WARN_ON(forw_packet->if_outgoing->soft_iface != soft_iface))
                goto out;
 
-       /* multihomed peer assumed
-        * non-primary OGMs are only broadcasted on their interface
-        */
-       if ((directlink && (batadv_ogm_packet->header.ttl == 1)) ||
-           (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
-               /* FIXME: what about aggregated packets ? */
-               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "%s packet (originator %pM, seqno %u, TTL %d) on interface %s [%pM]\n",
-                          (forw_packet->own ? "Sending own" : "Forwarding"),
-                          batadv_ogm_packet->orig,
-                          ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->header.ttl,
-                          forw_packet->if_incoming->net_dev->name,
-                          forw_packet->if_incoming->net_dev->dev_addr);
-
-               /* skb is only used once and than forw_packet is free'd */
-               batadv_send_skb_packet(forw_packet->skb,
-                                      forw_packet->if_incoming,
-                                      batadv_broadcast_addr);
-               forw_packet->skb = NULL;
-
+       if (forw_packet->if_incoming->if_status != BATADV_IF_ACTIVE)
                goto out;
-       }
 
-       /* broadcast on every interface */
-       rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
-               if (hard_iface->soft_iface != soft_iface)
-                       continue;
+       primary_if = batadv_primary_if_get_selected(bat_priv);
+       if (!primary_if)
+               goto out;
 
-               batadv_iv_ogm_send_to_if(forw_packet, hard_iface);
-       }
-       rcu_read_unlock();
+       /* only for one specific outgoing interface */
+       batadv_iv_ogm_send_to_if(forw_packet, forw_packet->if_outgoing);
 
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
 }
 
-/* return true if new_packet can be aggregated with forw_packet */
+/**
+ * batadv_iv_ogm_can_aggregate - find out if an OGM can be aggregated on an
+ *  existing forward packet
+ * @new_bat_ogm_packet: OGM packet to be aggregated
+ * @bat_priv: the bat priv with all the soft interface information
+ * @packet_len: (total) length of the OGM
+ * @send_time: timestamp (jiffies) when the packet is to be sent
+ * @direktlink: true if this is a direct link packet
+ * @if_incoming: interface where the packet was received
+ * @if_outgoing: interface for which the retransmission should be considered
+ * @forw_packet: the forwarded packet which should be checked
+ *
+ * Returns true if new_packet can be aggregated with forw_packet
+ */
 static bool
 batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                            struct batadv_priv *bat_priv,
                            int packet_len, unsigned long send_time,
                            bool directlink,
                            const struct batadv_hard_iface *if_incoming,
+                           const struct batadv_hard_iface *if_outgoing,
                            const struct batadv_forw_packet *forw_packet)
 {
        struct batadv_ogm_packet *batadv_ogm_packet;
@@ -567,12 +553,16 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                if (!primary_if)
                        goto out;
 
+               /* packet is not leaving on the same interface. */
+               if (forw_packet->if_outgoing != if_outgoing)
+                       goto out;
+
                /* packets without direct link flag and high TTL
                 * are flooded through the net
                 */
                if ((!directlink) &&
                    (!(batadv_ogm_packet->flags & BATADV_DIRECTLINK)) &&
-                   (batadv_ogm_packet->header.ttl != 1) &&
+                   (batadv_ogm_packet->ttl != 1) &&
 
                    /* own packets originating non-primary
                     * interfaces leave only that interface
@@ -587,7 +577,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                 * interface only - we still can aggregate
                 */
                if ((directlink) &&
-                   (new_bat_ogm_packet->header.ttl == 1) &&
+                   (new_bat_ogm_packet->ttl == 1) &&
                    (forw_packet->if_incoming == if_incoming) &&
 
                    /* packets from direct neighbors or
@@ -608,11 +598,21 @@ out:
        return res;
 }
 
-/* create a new aggregated packet and add this packet to it */
+/* batadv_iv_ogm_aggregate_new - create a new aggregated packet and add this
+ *  packet to it.
+ * @packet_buff: pointer to the OGM
+ * @packet_len: (total) length of the OGM
+ * @send_time: timestamp (jiffies) when the packet is to be sent
+ * @direct_link: whether this OGM has direct link status
+ * @if_incoming: interface where the packet was received
+ * @if_outgoing: interface for which the retransmission should be considered
+ * @own_packet: true if it is a self-generated ogm
+ */
 static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
                                        int packet_len, unsigned long send_time,
                                        bool direct_link,
                                        struct batadv_hard_iface *if_incoming,
+                                       struct batadv_hard_iface *if_outgoing,
                                        int own_packet)
 {
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
@@ -623,6 +623,9 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
        if (!atomic_inc_not_zero(&if_incoming->refcount))
                return;
 
+       if (!atomic_inc_not_zero(&if_outgoing->refcount))
+               goto out_free_incoming;
+
        /* own packet should always be scheduled */
        if (!own_packet) {
                if (!batadv_atomic_dec_not_zero(&bat_priv->batman_queue_left)) {
@@ -663,6 +666,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
 
        forw_packet_aggr->own = own_packet;
        forw_packet_aggr->if_incoming = if_incoming;
+       forw_packet_aggr->if_outgoing = if_outgoing;
        forw_packet_aggr->num_packets = 0;
        forw_packet_aggr->direct_link_flags = BATADV_NO_FLAGS;
        forw_packet_aggr->send_time = send_time;
@@ -685,6 +689,8 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
 
        return;
 out:
+       batadv_hardif_free_ref(if_outgoing);
+out_free_incoming:
        batadv_hardif_free_ref(if_incoming);
 }
 
@@ -708,10 +714,21 @@ static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr,
        }
 }
 
+/**
+ * batadv_iv_ogm_queue_add - queue up an OGM for transmission
+ * @bat_priv: the bat priv with all the soft interface information
+ * @packet_buff: pointer to the OGM
+ * @packet_len: (total) length of the OGM
+ * @if_incoming: interface where the packet was received
+ * @if_outgoing: interface for which the retransmission should be considered
+ * @own_packet: true if it is a self-generated ogm
+ * @send_time: timestamp (jiffies) when the packet is to be sent
+ */
 static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
                                    unsigned char *packet_buff,
                                    int packet_len,
                                    struct batadv_hard_iface *if_incoming,
+                                   struct batadv_hard_iface *if_outgoing,
                                    int own_packet, unsigned long send_time)
 {
        /* _aggr -> pointer to the packet we want to aggregate with
@@ -737,6 +754,7 @@ static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
                                                        bat_priv, packet_len,
                                                        send_time, direct_link,
                                                        if_incoming,
+                                                       if_outgoing,
                                                        forw_packet_pos)) {
                                forw_packet_aggr = forw_packet_pos;
                                break;
@@ -760,7 +778,8 @@ static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
 
                batadv_iv_ogm_aggregate_new(packet_buff, packet_len,
                                            send_time, direct_link,
-                                           if_incoming, own_packet);
+                                           if_incoming, if_outgoing,
+                                           own_packet);
        } else {
                batadv_iv_ogm_aggregate(forw_packet_aggr, packet_buff,
                                        packet_len, direct_link);
@@ -773,12 +792,13 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
                                  struct batadv_ogm_packet *batadv_ogm_packet,
                                  bool is_single_hop_neigh,
                                  bool is_from_best_next_hop,
-                                 struct batadv_hard_iface *if_incoming)
+                                 struct batadv_hard_iface *if_incoming,
+                                 struct batadv_hard_iface *if_outgoing)
 {
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
        uint16_t tvlv_len;
 
-       if (batadv_ogm_packet->header.ttl <= 1) {
+       if (batadv_ogm_packet->ttl <= 1) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
                return;
        }
@@ -798,7 +818,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);
 
-       batadv_ogm_packet->header.ttl--;
+       batadv_ogm_packet->ttl--;
        memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
 
        /* apply hop penalty */
@@ -807,7 +827,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                   "Forwarding packet: tq: %i, ttl: %i\n",
-                  batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl);
+                  batadv_ogm_packet->tq, batadv_ogm_packet->ttl);
 
        /* switch of primaries first hop flag when forwarding */
        batadv_ogm_packet->flags &= ~BATADV_PRIMARIES_FIRST_HOP;
@@ -818,7 +838,8 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet,
                                BATADV_OGM_HLEN + tvlv_len,
-                               if_incoming, 0, batadv_iv_ogm_fwd_send_time());
+                               if_incoming, if_outgoing, 0,
+                               batadv_iv_ogm_fwd_send_time());
 }
 
 /**
@@ -863,10 +884,11 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
        unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
        struct batadv_ogm_packet *batadv_ogm_packet;
-       struct batadv_hard_iface *primary_if;
+       struct batadv_hard_iface *primary_if, *tmp_hard_iface;
        int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
        uint32_t seqno;
        uint16_t tvlv_len = 0;
+       unsigned long send_time;
 
        primary_if = batadv_primary_if_get_selected(bat_priv);
 
@@ -889,23 +911,60 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
        atomic_inc(&hard_iface->bat_iv.ogm_seqno);
 
        batadv_iv_ogm_slide_own_bcast_window(hard_iface);
-       batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
-                               hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
-                               batadv_iv_ogm_emit_send_time(bat_priv));
 
+       send_time = batadv_iv_ogm_emit_send_time(bat_priv);
+
+       if (hard_iface != primary_if) {
+               /* OGMs from secondary interfaces are only scheduled on their
+                * respective interfaces.
+                */
+               batadv_iv_ogm_queue_add(bat_priv, *ogm_buff, *ogm_buff_len,
+                                       hard_iface, hard_iface, 1, send_time);
+               goto out;
+       }
+
+       /* OGMs from primary interfaces are scheduled on all
+        * interfaces.
+        */
+       rcu_read_lock();
+       list_for_each_entry_rcu(tmp_hard_iface, &batadv_hardif_list, list) {
+               if (tmp_hard_iface->soft_iface != hard_iface->soft_iface)
+                               continue;
+               batadv_iv_ogm_queue_add(bat_priv, *ogm_buff,
+                                       *ogm_buff_len, hard_iface,
+                                       tmp_hard_iface, 1, send_time);
+       }
+       rcu_read_unlock();
+
+out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
 }
 
+/**
+ * batadv_iv_ogm_orig_update - use OGM to update corresponding data in an
+ *  originator
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: the orig node who originally emitted the ogm packet
+ * @orig_ifinfo: ifinfo for the outgoing interface of the orig_node
+ * @ethhdr: Ethernet header of the OGM
+ * @batadv_ogm_packet: the ogm packet
+ * @if_incoming: interface where the packet was received
+ * @if_outgoing: interface for which the retransmission should be considered
+ * @dup_status: the duplicate status of this ogm packet.
+ */
 static void
 batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
                          struct batadv_orig_node *orig_node,
+                         struct batadv_orig_ifinfo *orig_ifinfo,
                          const struct ethhdr *ethhdr,
                          const struct batadv_ogm_packet *batadv_ogm_packet,
                          struct batadv_hard_iface *if_incoming,
-                         const unsigned char *tt_buff,
+                         struct batadv_hard_iface *if_outgoing,
                          enum batadv_dup_status dup_status)
 {
+       struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
+       struct batadv_neigh_ifinfo *router_ifinfo = NULL;
        struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
        struct batadv_neigh_node *router = NULL;
        struct batadv_orig_node *orig_node_tmp;
@@ -933,12 +992,21 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
                if (dup_status != BATADV_NO_DUP)
                        continue;
 
-               spin_lock_bh(&tmp_neigh_node->bat_iv.lq_update_lock);
-               batadv_ring_buffer_set(tmp_neigh_node->bat_iv.tq_recv,
-                                      &tmp_neigh_node->bat_iv.tq_index, 0);
-               tq_avg = batadv_ring_buffer_avg(tmp_neigh_node->bat_iv.tq_recv);
-               tmp_neigh_node->bat_iv.tq_avg = tq_avg;
-               spin_unlock_bh(&tmp_neigh_node->bat_iv.lq_update_lock);
+               /* only update the entry for this outgoing interface */
+               neigh_ifinfo = batadv_neigh_ifinfo_get(tmp_neigh_node,
+                                                      if_outgoing);
+               if (!neigh_ifinfo)
+                       continue;
+
+               spin_lock_bh(&tmp_neigh_node->ifinfo_lock);
+               batadv_ring_buffer_set(neigh_ifinfo->bat_iv.tq_recv,
+                                      &neigh_ifinfo->bat_iv.tq_index, 0);
+               tq_avg = batadv_ring_buffer_avg(neigh_ifinfo->bat_iv.tq_recv);
+               neigh_ifinfo->bat_iv.tq_avg = tq_avg;
+               spin_unlock_bh(&tmp_neigh_node->ifinfo_lock);
+
+               batadv_neigh_ifinfo_free_ref(neigh_ifinfo);
+               neigh_ifinfo = NULL;
        }
 
        if (!neigh_node) {
@@ -960,39 +1028,49 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
                           "Updating existing last-hop neighbor of originator\n");
 
        rcu_read_unlock();
+       neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing);
+       if (!neigh_ifinfo)
+               goto out;
 
        neigh_node->last_seen = jiffies;
 
-       spin_lock_bh(&neigh_node->bat_iv.lq_update_lock);
-       batadv_ring_buffer_set(neigh_node->bat_iv.tq_recv,
-                              &neigh_node->bat_iv.tq_index,
+       spin_lock_bh(&neigh_node->ifinfo_lock);
+       batadv_ring_buffer_set(neigh_ifinfo->bat_iv.tq_recv,
+                              &neigh_ifinfo->bat_iv.tq_index,
                               batadv_ogm_packet->tq);
-       tq_avg = batadv_ring_buffer_avg(neigh_node->bat_iv.tq_recv);
-       neigh_node->bat_iv.tq_avg = tq_avg;
-       spin_unlock_bh(&neigh_node->bat_iv.lq_update_lock);
+       tq_avg = batadv_ring_buffer_avg(neigh_ifinfo->bat_iv.tq_recv);
+       neigh_ifinfo->bat_iv.tq_avg = tq_avg;
+       spin_unlock_bh(&neigh_node->ifinfo_lock);
 
        if (dup_status == BATADV_NO_DUP) {
-               orig_node->last_ttl = batadv_ogm_packet->header.ttl;
-               neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
+               orig_ifinfo->last_ttl = batadv_ogm_packet->ttl;
+               neigh_ifinfo->last_ttl = batadv_ogm_packet->ttl;
        }
 
-       batadv_bonding_candidate_add(bat_priv, orig_node, neigh_node);
-
        /* if this neighbor already is our next hop there is nothing
         * to change
         */
-       router = batadv_orig_node_get_router(orig_node);
+       router = batadv_orig_router_get(orig_node, if_outgoing);
        if (router == neigh_node)
                goto out;
 
-       /* if this neighbor does not offer a better TQ we won't consider it */
-       if (router && (router->bat_iv.tq_avg > neigh_node->bat_iv.tq_avg))
-               goto out;
+       if (router) {
+               router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
+               if (!router_ifinfo)
+                       goto out;
+
+               /* if this neighbor does not offer a better TQ we won't
+                * consider it
+                */
+               if (router_ifinfo->bat_iv.tq_avg > neigh_ifinfo->bat_iv.tq_avg)
+                       goto out;
+       }
 
        /* if the TQ is the same and the link not more symmetric we
         * won't consider it either
         */
-       if (router && (neigh_node->bat_iv.tq_avg == router->bat_iv.tq_avg)) {
+       if (router_ifinfo &&
+           (neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg)) {
                orig_node_tmp = router->orig_node;
                spin_lock_bh(&orig_node_tmp->bat_iv.ogm_cnt_lock);
                if_num = router->if_incoming->if_num;
@@ -1009,7 +1087,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
                        goto out;
        }
 
-       batadv_update_route(bat_priv, orig_node, neigh_node);
+       batadv_update_route(bat_priv, orig_node, if_outgoing, neigh_node);
        goto out;
 
 unlock:
@@ -1019,20 +1097,37 @@ out:
                batadv_neigh_node_free_ref(neigh_node);
        if (router)
                batadv_neigh_node_free_ref(router);
+       if (neigh_ifinfo)
+               batadv_neigh_ifinfo_free_ref(neigh_ifinfo);
+       if (router_ifinfo)
+               batadv_neigh_ifinfo_free_ref(router_ifinfo);
 }
 
+/**
+ * batadv_iv_ogm_calc_tq - calculate tq for current received ogm packet
+ * @orig_node: the orig node who originally emitted the ogm packet
+ * @orig_neigh_node: the orig node struct of the neighbor who sent the packet
+ * @batadv_ogm_packet: the ogm packet
+ * @if_incoming: interface where the packet was received
+ * @if_outgoing: interface for which the retransmission should be considered
+ *
+ * Returns 1 if the link can be considered bidirectional, 0 otherwise
+ */
 static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
                                 struct batadv_orig_node *orig_neigh_node,
                                 struct batadv_ogm_packet *batadv_ogm_packet,
-                                struct batadv_hard_iface *if_incoming)
+                                struct batadv_hard_iface *if_incoming,
+                                struct batadv_hard_iface *if_outgoing)
 {
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
        struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node;
+       struct batadv_neigh_ifinfo *neigh_ifinfo;
        uint8_t total_count;
        uint8_t orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own;
        unsigned int neigh_rq_inv_cube, neigh_rq_max_cube;
        int tq_asym_penalty, inv_asym_penalty, if_num, ret = 0;
        unsigned int combined_tq;
+       int tq_iface_penalty;
 
        /* find corresponding one hop neighbor */
        rcu_read_lock();
@@ -1072,7 +1167,13 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
        spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
        if_num = if_incoming->if_num;
        orig_eq_count = orig_neigh_node->bat_iv.bcast_own_sum[if_num];
-       neigh_rq_count = neigh_node->bat_iv.real_packet_count;
+       neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing);
+       if (neigh_ifinfo) {
+               neigh_rq_count = neigh_ifinfo->bat_iv.real_packet_count;
+               batadv_neigh_ifinfo_free_ref(neigh_ifinfo);
+       } else {
+               neigh_rq_count = 0;
+       }
        spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
 
        /* pay attention to not get a value bigger than 100 % */
@@ -1108,15 +1209,31 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
        inv_asym_penalty /= neigh_rq_max_cube;
        tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty;
 
-       combined_tq = batadv_ogm_packet->tq * tq_own * tq_asym_penalty;
-       combined_tq /= BATADV_TQ_MAX_VALUE * BATADV_TQ_MAX_VALUE;
+       /* penalize if the OGM is forwarded on the same interface. WiFi
+        * interfaces and other half duplex devices suffer from throughput
+        * drops as they can't send and receive at the same time.
+        */
+       tq_iface_penalty = BATADV_TQ_MAX_VALUE;
+       if (if_outgoing && (if_incoming == if_outgoing) &&
+           batadv_is_wifi_netdev(if_outgoing->net_dev))
+               tq_iface_penalty = batadv_hop_penalty(BATADV_TQ_MAX_VALUE,
+                                                     bat_priv);
+
+       combined_tq = batadv_ogm_packet->tq *
+                     tq_own *
+                     tq_asym_penalty *
+                     tq_iface_penalty;
+       combined_tq /= BATADV_TQ_MAX_VALUE *
+                      BATADV_TQ_MAX_VALUE *
+                      BATADV_TQ_MAX_VALUE;
        batadv_ogm_packet->tq = combined_tq;
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                  "bidirectional: orig = %-15pM neigh = %-15pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i\n",
+                  "bidirectional: orig = %-15pM neigh = %-15pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, iface_penalty: %3i, total tq: %3i, if_incoming = %s, if_outgoing = %s\n",
                   orig_node->orig, orig_neigh_node->orig, total_count,
-                  neigh_rq_count, tq_own,
-                  tq_asym_penalty, batadv_ogm_packet->tq);
+                  neigh_rq_count, tq_own, tq_asym_penalty, tq_iface_penalty,
+                  batadv_ogm_packet->tq, if_incoming->net_dev->name,
+                  if_outgoing ? if_outgoing->net_dev->name : "DEFAULT");
 
        /* if link has the minimum required transmission quality
         * consider it bidirectional
@@ -1136,17 +1253,21 @@ out:
  * @ethhdr: ethernet header of the packet
  * @batadv_ogm_packet: OGM packet to be considered
  * @if_incoming: interface on which the OGM packet was received
+ * @if_outgoing: interface for which the retransmission should be considered
  *
  * Returns duplicate status as enum batadv_dup_status
  */
 static enum batadv_dup_status
 batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
                            const struct batadv_ogm_packet *batadv_ogm_packet,
-                           const struct batadv_hard_iface *if_incoming)
+                           const struct batadv_hard_iface *if_incoming,
+                           struct batadv_hard_iface *if_outgoing)
 {
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
        struct batadv_orig_node *orig_node;
-       struct batadv_neigh_node *tmp_neigh_node;
+       struct batadv_orig_ifinfo *orig_ifinfo = NULL;
+       struct batadv_neigh_node *neigh_node;
+       struct batadv_neigh_ifinfo *neigh_ifinfo;
        int is_dup;
        int32_t seq_diff;
        int need_update = 0;
@@ -1161,27 +1282,37 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
        if (!orig_node)
                return BATADV_NO_DUP;
 
+       orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
+       if (WARN_ON(!orig_ifinfo)) {
+               batadv_orig_node_free_ref(orig_node);
+               return 0;
+       }
+
        spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
-       seq_diff = seqno - orig_node->last_real_seqno;
+       seq_diff = seqno - orig_ifinfo->last_real_seqno;
 
        /* signalize caller that the packet is to be dropped. */
        if (!hlist_empty(&orig_node->neigh_list) &&
            batadv_window_protected(bat_priv, seq_diff,
-                                   &orig_node->batman_seqno_reset)) {
+                                   &orig_ifinfo->batman_seqno_reset)) {
                ret = BATADV_PROTECTED;
                goto out;
        }
 
        rcu_read_lock();
-       hlist_for_each_entry_rcu(tmp_neigh_node,
-                                &orig_node->neigh_list, list) {
-               neigh_addr = tmp_neigh_node->addr;
-               is_dup = batadv_test_bit(tmp_neigh_node->bat_iv.real_bits,
-                                        orig_node->last_real_seqno,
+       hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
+               neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node,
+                                                      if_outgoing);
+               if (!neigh_ifinfo)
+                       continue;
+
+               neigh_addr = neigh_node->addr;
+               is_dup = batadv_test_bit(neigh_ifinfo->bat_iv.real_bits,
+                                        orig_ifinfo->last_real_seqno,
                                         seqno);
 
                if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
-                   tmp_neigh_node->if_incoming == if_incoming) {
+                   neigh_node->if_incoming == if_incoming) {
                        set_mark = 1;
                        if (is_dup)
                                ret = BATADV_NEIGH_DUP;
@@ -1192,173 +1323,78 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
                }
 
                /* if the window moved, set the update flag. */
-               bitmap = tmp_neigh_node->bat_iv.real_bits;
+               bitmap = neigh_ifinfo->bat_iv.real_bits;
                need_update |= batadv_bit_get_packet(bat_priv, bitmap,
                                                     seq_diff, set_mark);
 
-               packet_count = bitmap_weight(tmp_neigh_node->bat_iv.real_bits,
+               packet_count = bitmap_weight(bitmap,
                                             BATADV_TQ_LOCAL_WINDOW_SIZE);
-               tmp_neigh_node->bat_iv.real_packet_count = packet_count;
+               neigh_ifinfo->bat_iv.real_packet_count = packet_count;
+               batadv_neigh_ifinfo_free_ref(neigh_ifinfo);
        }
        rcu_read_unlock();
 
        if (need_update) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "updating last_seqno: old %u, new %u\n",
-                          orig_node->last_real_seqno, seqno);
-               orig_node->last_real_seqno = seqno;
+                          "%s updating last_seqno: old %u, new %u\n",
+                          if_outgoing ? if_outgoing->net_dev->name : "DEFAULT",
+                          orig_ifinfo->last_real_seqno, seqno);
+               orig_ifinfo->last_real_seqno = seqno;
        }
 
 out:
        spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
        batadv_orig_node_free_ref(orig_node);
+       if (orig_ifinfo)
+               batadv_orig_ifinfo_free_ref(orig_ifinfo);
        return ret;
 }
 
-static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
-                                 struct batadv_ogm_packet *batadv_ogm_packet,
-                                 const unsigned char *tt_buff,
-                                 struct batadv_hard_iface *if_incoming)
+
+/**
+ * batadv_iv_ogm_process_per_outif - process a batman iv OGM for an outgoing if
+ * @skb: the skb containing the OGM
+ * @orig_node: the (cached) orig node for the originator of this OGM
+ * @if_incoming: the interface where this packet was received
+ * @if_outgoing: the interface for which the packet should be considered
+ */
+static void
+batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
+                               struct batadv_orig_node *orig_node,
+                               struct batadv_hard_iface *if_incoming,
+                               struct batadv_hard_iface *if_outgoing)
 {
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
-       struct batadv_hard_iface *hard_iface;
-       struct batadv_orig_node *orig_neigh_node, *orig_node, *orig_node_tmp;
        struct batadv_neigh_node *router = NULL, *router_router = NULL;
+       struct batadv_orig_node *orig_neigh_node;
+       struct batadv_orig_ifinfo *orig_ifinfo;
        struct batadv_neigh_node *orig_neigh_router = NULL;
-       int has_directlink_flag;
-       int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
-       int is_bidirect;
-       bool is_single_hop_neigh = false;
-       bool is_from_best_next_hop = false;
-       int sameseq, similar_ttl;
+       struct batadv_neigh_ifinfo *router_ifinfo = NULL;
+       struct batadv_ogm_packet *ogm_packet;
        enum batadv_dup_status dup_status;
-       uint32_t if_incoming_seqno;
+       bool is_from_best_next_hop = false;
+       bool is_single_hop_neigh = false;
+       bool sameseq, similar_ttl;
+       struct sk_buff *skb_priv;
+       struct ethhdr *ethhdr;
        uint8_t *prev_sender;
+       int is_bidirect;
 
-       /* Silently drop when the batman packet is actually not a
-        * correct packet.
-        *
-        * This might happen if a packet is padded (e.g. Ethernet has a
-        * minimum frame length of 64 byte) and the aggregation interprets
-        * it as an additional length.
-        *
-        * TODO: A more sane solution would be to have a bit in the
-        * batadv_ogm_packet to detect whether the packet is the last
-        * packet in an aggregation.  Here we expect that the padding
-        * is always zero (or not 0x01)
+       /* create a private copy of the skb, as some functions change tq value
+        * and/or flags.
         */
-       if (batadv_ogm_packet->header.packet_type != BATADV_IV_OGM)
+       skb_priv = skb_copy(skb, GFP_ATOMIC);
+       if (!skb_priv)
                return;
 
-       /* could be changed by schedule_own_packet() */
-       if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno);
-
-       if (batadv_ogm_packet->flags & BATADV_DIRECTLINK)
-               has_directlink_flag = 1;
-       else
-               has_directlink_flag = 0;
+       ethhdr = eth_hdr(skb_priv);
+       ogm_packet = (struct batadv_ogm_packet *)(skb_priv->data + ogm_offset);
 
-       if (batadv_compare_eth(ethhdr->h_source, batadv_ogm_packet->orig))
+       dup_status = batadv_iv_ogm_update_seqnos(ethhdr, ogm_packet,
+                                                if_incoming, if_outgoing);
+       if (batadv_compare_eth(ethhdr->h_source, ogm_packet->orig))
                is_single_hop_neigh = true;
 
-       batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                  "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, tq %d, TTL %d, V %d, IDF %d)\n",
-                  ethhdr->h_source, if_incoming->net_dev->name,
-                  if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig,
-                  batadv_ogm_packet->prev_sender,
-                  ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
-                  batadv_ogm_packet->header.ttl,
-                  batadv_ogm_packet->header.version, has_directlink_flag);
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
-               if (hard_iface->if_status != BATADV_IF_ACTIVE)
-                       continue;
-
-               if (hard_iface->soft_iface != if_incoming->soft_iface)
-                       continue;
-
-               if (batadv_compare_eth(ethhdr->h_source,
-                                      hard_iface->net_dev->dev_addr))
-                       is_my_addr = 1;
-
-               if (batadv_compare_eth(batadv_ogm_packet->orig,
-                                      hard_iface->net_dev->dev_addr))
-                       is_my_orig = 1;
-
-               if (batadv_compare_eth(batadv_ogm_packet->prev_sender,
-                                      hard_iface->net_dev->dev_addr))
-                       is_my_oldorig = 1;
-       }
-       rcu_read_unlock();
-
-       if (is_my_addr) {
-               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "Drop packet: received my own broadcast (sender: %pM)\n",
-                          ethhdr->h_source);
-               return;
-       }
-
-       if (is_my_orig) {
-               unsigned long *word;
-               int offset;
-               int32_t bit_pos;
-               int16_t if_num;
-               uint8_t *weight;
-
-               orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv,
-                                                        ethhdr->h_source);
-               if (!orig_neigh_node)
-                       return;
-
-               /* neighbor has to indicate direct link and it has to
-                * come via the corresponding interface
-                * save packet seqno for bidirectional check
-                */
-               if (has_directlink_flag &&
-                   batadv_compare_eth(if_incoming->net_dev->dev_addr,
-                                      batadv_ogm_packet->orig)) {
-                       if_num = if_incoming->if_num;
-                       offset = if_num * BATADV_NUM_WORDS;
-
-                       spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
-                       word = &(orig_neigh_node->bat_iv.bcast_own[offset]);
-                       bit_pos = if_incoming_seqno - 2;
-                       bit_pos -= ntohl(batadv_ogm_packet->seqno);
-                       batadv_set_bit(word, bit_pos);
-                       weight = &orig_neigh_node->bat_iv.bcast_own_sum[if_num];
-                       *weight = bitmap_weight(word,
-                                               BATADV_TQ_LOCAL_WINDOW_SIZE);
-                       spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
-               }
-
-               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "Drop packet: originator packet from myself (via neighbor)\n");
-               batadv_orig_node_free_ref(orig_neigh_node);
-               return;
-       }
-
-       if (is_my_oldorig) {
-               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "Drop packet: ignoring all rebroadcast echos (sender: %pM)\n",
-                          ethhdr->h_source);
-               return;
-       }
-
-       if (batadv_ogm_packet->flags & BATADV_NOT_BEST_NEXT_HOP) {
-               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "Drop packet: ignoring all packets not forwarded from the best next hop (sender: %pM)\n",
-                          ethhdr->h_source);
-               return;
-       }
-
-       orig_node = batadv_iv_ogm_orig_get(bat_priv, batadv_ogm_packet->orig);
-       if (!orig_node)
-               return;
-
-       dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
-                                                if_incoming);
-
        if (dup_status == BATADV_PROTECTED) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Drop packet: packet within seqno protection time (sender: %pM)\n",
@@ -1366,27 +1402,28 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
                goto out;
        }
 
-       if (batadv_ogm_packet->tq == 0) {
+       if (ogm_packet->tq == 0) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Drop packet: originator packet with tq equal 0\n");
                goto out;
        }
 
-       router = batadv_orig_node_get_router(orig_node);
+       router = batadv_orig_router_get(orig_node, if_outgoing);
        if (router) {
-               orig_node_tmp = router->orig_node;
-               router_router = batadv_orig_node_get_router(orig_node_tmp);
+               router_router = batadv_orig_router_get(router->orig_node,
+                                                      if_outgoing);
+               router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
        }
 
-       if ((router && router->bat_iv.tq_avg != 0) &&
+       if ((router_ifinfo && router_ifinfo->bat_iv.tq_avg != 0) &&
            (batadv_compare_eth(router->addr, ethhdr->h_source)))
                is_from_best_next_hop = true;
 
-       prev_sender = batadv_ogm_packet->prev_sender;
+       prev_sender = ogm_packet->prev_sender;
        /* avoid temporary routing loops */
        if (router && router_router &&
            (batadv_compare_eth(router->addr, prev_sender)) &&
-           !(batadv_compare_eth(batadv_ogm_packet->orig, prev_sender)) &&
+           !(batadv_compare_eth(ogm_packet->orig, prev_sender)) &&
            (batadv_compare_eth(router->addr, router_router->addr))) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %pM)\n",
@@ -1394,7 +1431,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
                goto out;
        }
 
-       batadv_tvlv_ogm_receive(bat_priv, batadv_ogm_packet, orig_node);
+       if (if_outgoing == BATADV_IF_DEFAULT)
+               batadv_tvlv_ogm_receive(bat_priv, ogm_packet, orig_node);
 
        /* if sender is a direct neighbor the sender mac equals
         * originator mac
@@ -1410,9 +1448,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
 
        /* Update nc_nodes of the originator */
        batadv_nc_update_nc_node(bat_priv, orig_node, orig_neigh_node,
-                                batadv_ogm_packet, is_single_hop_neigh);
+                                ogm_packet, is_single_hop_neigh);
 
-       orig_neigh_router = batadv_orig_node_get_router(orig_neigh_node);
+       orig_neigh_router = batadv_orig_router_get(orig_neigh_node,
+                                                  if_outgoing);
 
        /* drop packet if sender is not a direct neighbor and if we
         * don't route towards it
@@ -1424,28 +1463,48 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
        }
 
        is_bidirect = batadv_iv_ogm_calc_tq(orig_node, orig_neigh_node,
-                                           batadv_ogm_packet, if_incoming);
-
-       batadv_bonding_save_primary(orig_node, orig_neigh_node,
-                                   batadv_ogm_packet);
+                                           ogm_packet, if_incoming,
+                                           if_outgoing);
 
        /* update ranking if it is not a duplicate or has the same
         * seqno and similar ttl as the non-duplicate
         */
-       sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
-       similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
+       orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
+       if (!orig_ifinfo)
+               goto out_neigh;
+
+       sameseq = orig_ifinfo->last_real_seqno == ntohl(ogm_packet->seqno);
+       similar_ttl = (orig_ifinfo->last_ttl - 3) <= ogm_packet->ttl;
+
        if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
-                           (sameseq && similar_ttl)))
-               batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
-                                         batadv_ogm_packet, if_incoming,
-                                         tt_buff, dup_status);
+                           (sameseq && similar_ttl))) {
+               batadv_iv_ogm_orig_update(bat_priv, orig_node,
+                                         orig_ifinfo, ethhdr,
+                                         ogm_packet, if_incoming,
+                                         if_outgoing, dup_status);
+       }
+       batadv_orig_ifinfo_free_ref(orig_ifinfo);
+
+       /* only forward for specific interface, not for the default one. */
+       if (if_outgoing == BATADV_IF_DEFAULT)
+               goto out_neigh;
 
        /* is single hop (direct) neighbor */
        if (is_single_hop_neigh) {
+               /* OGMs from secondary interfaces should only scheduled once
+                * per interface where it has been received, not multiple times
+                */
+               if ((ogm_packet->ttl <= 2) &&
+                   (if_incoming != if_outgoing)) {
+                       batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                                  "Drop packet: OGM from secondary interface and wrong outgoing interface\n");
+                       goto out_neigh;
+               }
                /* mark direct link on incoming interface */
-               batadv_iv_ogm_forward(orig_node, ethhdr, batadv_ogm_packet,
+               batadv_iv_ogm_forward(orig_node, ethhdr, ogm_packet,
                                      is_single_hop_neigh,
-                                     is_from_best_next_hop, if_incoming);
+                                     is_from_best_next_hop, if_incoming,
+                                     if_outgoing);
 
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Forwarding packet: rebroadcast neighbor packet with direct link flag\n");
@@ -1467,9 +1526,9 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                   "Forwarding packet: rebroadcast originator packet\n");
-       batadv_iv_ogm_forward(orig_node, ethhdr, batadv_ogm_packet,
+       batadv_iv_ogm_forward(orig_node, ethhdr, ogm_packet,
                              is_single_hop_neigh, is_from_best_next_hop,
-                             if_incoming);
+                             if_incoming, if_outgoing);
 
 out_neigh:
        if ((orig_neigh_node) && (!is_single_hop_neigh))
@@ -1482,6 +1541,165 @@ out:
        if (orig_neigh_router)
                batadv_neigh_node_free_ref(orig_neigh_router);
 
+       kfree_skb(skb_priv);
+}
+
+/**
+ * batadv_iv_ogm_process - process an incoming batman iv OGM
+ * @skb: the skb containing the OGM
+ * @ogm_offset: offset to the OGM which should be processed (for aggregates)
+ * @if_incoming: the interface where this packet was receved
+ */
+static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
+                                 struct batadv_hard_iface *if_incoming)
+{
+       struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
+       struct batadv_orig_node *orig_neigh_node, *orig_node;
+       struct batadv_hard_iface *hard_iface;
+       struct batadv_ogm_packet *ogm_packet;
+       uint32_t if_incoming_seqno;
+       bool has_directlink_flag;
+       struct ethhdr *ethhdr;
+       bool is_my_oldorig = false;
+       bool is_my_addr = false;
+       bool is_my_orig = false;
+
+       ogm_packet = (struct batadv_ogm_packet *)(skb->data + ogm_offset);
+       ethhdr = eth_hdr(skb);
+
+       /* Silently drop when the batman packet is actually not a
+        * correct packet.
+        *
+        * This might happen if a packet is padded (e.g. Ethernet has a
+        * minimum frame length of 64 byte) and the aggregation interprets
+        * it as an additional length.
+        *
+        * TODO: A more sane solution would be to have a bit in the
+        * batadv_ogm_packet to detect whether the packet is the last
+        * packet in an aggregation.  Here we expect that the padding
+        * is always zero (or not 0x01)
+        */
+       if (ogm_packet->packet_type != BATADV_IV_OGM)
+               return;
+
+       /* could be changed by schedule_own_packet() */
+       if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno);
+
+       if (ogm_packet->flags & BATADV_DIRECTLINK)
+               has_directlink_flag = true;
+       else
+               has_directlink_flag = false;
+
+       batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                  "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, tq %d, TTL %d, V %d, IDF %d)\n",
+                  ethhdr->h_source, if_incoming->net_dev->name,
+                  if_incoming->net_dev->dev_addr, ogm_packet->orig,
+                  ogm_packet->prev_sender, ntohl(ogm_packet->seqno),
+                  ogm_packet->tq, ogm_packet->ttl,
+                  ogm_packet->version, has_directlink_flag);
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+               if (hard_iface->if_status != BATADV_IF_ACTIVE)
+                       continue;
+
+               if (hard_iface->soft_iface != if_incoming->soft_iface)
+                       continue;
+
+               if (batadv_compare_eth(ethhdr->h_source,
+                                      hard_iface->net_dev->dev_addr))
+                       is_my_addr = true;
+
+               if (batadv_compare_eth(ogm_packet->orig,
+                                      hard_iface->net_dev->dev_addr))
+                       is_my_orig = true;
+
+               if (batadv_compare_eth(ogm_packet->prev_sender,
+                                      hard_iface->net_dev->dev_addr))
+                       is_my_oldorig = true;
+       }
+       rcu_read_unlock();
+
+       if (is_my_addr) {
+               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                          "Drop packet: received my own broadcast (sender: %pM)\n",
+                          ethhdr->h_source);
+               return;
+       }
+
+       if (is_my_orig) {
+               unsigned long *word;
+               int offset;
+               int32_t bit_pos;
+               int16_t if_num;
+               uint8_t *weight;
+
+               orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv,
+                                                        ethhdr->h_source);
+               if (!orig_neigh_node)
+                       return;
+
+               /* neighbor has to indicate direct link and it has to
+                * come via the corresponding interface
+                * save packet seqno for bidirectional check
+                */
+               if (has_directlink_flag &&
+                   batadv_compare_eth(if_incoming->net_dev->dev_addr,
+                                      ogm_packet->orig)) {
+                       if_num = if_incoming->if_num;
+                       offset = if_num * BATADV_NUM_WORDS;
+
+                       spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
+                       word = &(orig_neigh_node->bat_iv.bcast_own[offset]);
+                       bit_pos = if_incoming_seqno - 2;
+                       bit_pos -= ntohl(ogm_packet->seqno);
+                       batadv_set_bit(word, bit_pos);
+                       weight = &orig_neigh_node->bat_iv.bcast_own_sum[if_num];
+                       *weight = bitmap_weight(word,
+                                               BATADV_TQ_LOCAL_WINDOW_SIZE);
+                       spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
+               }
+
+               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                          "Drop packet: originator packet from myself (via neighbor)\n");
+               batadv_orig_node_free_ref(orig_neigh_node);
+               return;
+       }
+
+       if (is_my_oldorig) {
+               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                          "Drop packet: ignoring all rebroadcast echos (sender: %pM)\n",
+                          ethhdr->h_source);
+               return;
+       }
+
+       if (ogm_packet->flags & BATADV_NOT_BEST_NEXT_HOP) {
+               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                          "Drop packet: ignoring all packets not forwarded from the best next hop (sender: %pM)\n",
+                          ethhdr->h_source);
+               return;
+       }
+
+       orig_node = batadv_iv_ogm_orig_get(bat_priv, ogm_packet->orig);
+       if (!orig_node)
+               return;
+
+       batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node,
+                                       if_incoming, BATADV_IF_DEFAULT);
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+               if (hard_iface->if_status != BATADV_IF_ACTIVE)
+                       continue;
+
+               if (hard_iface->soft_iface != bat_priv->soft_iface)
+                       continue;
+
+               batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node,
+                                               if_incoming, hard_iface);
+       }
+       rcu_read_unlock();
+
        batadv_orig_node_free_ref(orig_node);
 }
 
@@ -1489,11 +1707,9 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
                                 struct batadv_hard_iface *if_incoming)
 {
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
-       struct batadv_ogm_packet *batadv_ogm_packet;
-       struct ethhdr *ethhdr;
-       int buff_pos = 0, packet_len;
-       unsigned char *tvlv_buff, *packet_buff;
+       struct batadv_ogm_packet *ogm_packet;
        uint8_t *packet_pos;
+       int ogm_offset;
        bool ret;
 
        ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
@@ -1510,42 +1726,68 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
        batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES,
                           skb->len + ETH_HLEN);
 
-       packet_len = skb_headlen(skb);
-       ethhdr = eth_hdr(skb);
-       packet_buff = skb->data;
-       batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
+       ogm_offset = 0;
+       ogm_packet = (struct batadv_ogm_packet *)skb->data;
 
        /* unpack the aggregated packets and process them one by one */
-       while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
-                                        batadv_ogm_packet->tvlv_len)) {
-               tvlv_buff = packet_buff + buff_pos + BATADV_OGM_HLEN;
+       while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
+                                        ogm_packet->tvlv_len)) {
+               batadv_iv_ogm_process(skb, ogm_offset, if_incoming);
 
-               batadv_iv_ogm_process(ethhdr, batadv_ogm_packet,
-                                     tvlv_buff, if_incoming);
+               ogm_offset += BATADV_OGM_HLEN;
+               ogm_offset += ntohs(ogm_packet->tvlv_len);
 
-               buff_pos += BATADV_OGM_HLEN;
-               buff_pos += ntohs(batadv_ogm_packet->tvlv_len);
-
-               packet_pos = packet_buff + buff_pos;
-               batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
+               packet_pos = skb->data + ogm_offset;
+               ogm_packet = (struct batadv_ogm_packet *)packet_pos;
        }
 
        kfree_skb(skb);
        return NET_RX_SUCCESS;
 }
 
+/* batadv_iv_ogm_orig_print_neigh - print neighbors for the originator table
+ * @orig_node: the orig_node for which the neighbors are printed
+ * @if_outgoing: outgoing interface for these entries
+ * @seq: debugfs table seq_file struct
+ *
+ * Must be called while holding an rcu lock.
+ */
+static void
+batadv_iv_ogm_orig_print_neigh(struct batadv_orig_node *orig_node,
+                              struct batadv_hard_iface *if_outgoing,
+                              struct seq_file *seq)
+{
+       struct batadv_neigh_node *neigh_node;
+       struct batadv_neigh_ifinfo *n_ifinfo;
+
+       hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
+               n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
+               if (!n_ifinfo)
+                       continue;
+
+               seq_printf(seq, " %pM (%3i)",
+                          neigh_node->addr,
+                          n_ifinfo->bat_iv.tq_avg);
+
+               batadv_neigh_ifinfo_free_ref(n_ifinfo);
+       }
+}
+
 /**
  * batadv_iv_ogm_orig_print - print the originator table
  * @bat_priv: the bat priv with all the soft interface information
  * @seq: debugfs table seq_file struct
+ * @if_outgoing: the outgoing interface for which this should be printed
  */
 static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv,
-                                    struct seq_file *seq)
+                                    struct seq_file *seq,
+                                    struct batadv_hard_iface *if_outgoing)
 {
-       struct batadv_neigh_node *neigh_node, *neigh_node_tmp;
+       struct batadv_neigh_node *neigh_node;
        struct batadv_hashtable *hash = bat_priv->orig_hash;
        int last_seen_msecs, last_seen_secs;
        struct batadv_orig_node *orig_node;
+       struct batadv_neigh_ifinfo *n_ifinfo;
        unsigned long last_seen_jiffies;
        struct hlist_head *head;
        int batman_count = 0;
@@ -1560,11 +1802,17 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv,
 
                rcu_read_lock();
                hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
-                       neigh_node = batadv_orig_node_get_router(orig_node);
+                       neigh_node = batadv_orig_router_get(orig_node,
+                                                           if_outgoing);
                        if (!neigh_node)
                                continue;
 
-                       if (neigh_node->bat_iv.tq_avg == 0)
+                       n_ifinfo = batadv_neigh_ifinfo_get(neigh_node,
+                                                          if_outgoing);
+                       if (!n_ifinfo)
+                               goto next;
+
+                       if (n_ifinfo->bat_iv.tq_avg == 0)
                                goto next;
 
                        last_seen_jiffies = jiffies - orig_node->last_seen;
@@ -1574,22 +1822,19 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv,
 
                        seq_printf(seq, "%pM %4i.%03is   (%3i) %pM [%10s]:",
                                   orig_node->orig, last_seen_secs,
-                                  last_seen_msecs, neigh_node->bat_iv.tq_avg,
+                                  last_seen_msecs, n_ifinfo->bat_iv.tq_avg,
                                   neigh_node->addr,
                                   neigh_node->if_incoming->net_dev->name);
 
-                       hlist_for_each_entry_rcu(neigh_node_tmp,
-                                                &orig_node->neigh_list, list) {
-                               seq_printf(seq, " %pM (%3i)",
-                                          neigh_node_tmp->addr,
-                                          neigh_node_tmp->bat_iv.tq_avg);
-                       }
-
+                       batadv_iv_ogm_orig_print_neigh(orig_node, if_outgoing,
+                                                      seq);
                        seq_puts(seq, "\n");
                        batman_count++;
 
 next:
                        batadv_neigh_node_free_ref(neigh_node);
+                       if (n_ifinfo)
+                               batadv_neigh_ifinfo_free_ref(n_ifinfo);
                }
                rcu_read_unlock();
        }
@@ -1601,37 +1846,84 @@ next:
 /**
  * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors
  * @neigh1: the first neighbor object of the comparison
+ * @if_outgoing1: outgoing interface for the first neighbor
  * @neigh2: the second neighbor object of the comparison
+ * @if_outgoing2: outgoing interface for the second neighbor
  *
  * Returns a value less, equal to or greater than 0 if the metric via neigh1 is
  * lower, the same as or higher than the metric via neigh2
  */
 static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1,
-                                  struct batadv_neigh_node *neigh2)
+                                  struct batadv_hard_iface *if_outgoing1,
+                                  struct batadv_neigh_node *neigh2,
+                                  struct batadv_hard_iface *if_outgoing2)
 {
+       struct batadv_neigh_ifinfo *neigh1_ifinfo, *neigh2_ifinfo;
        uint8_t tq1, tq2;
+       int diff;
+
+       neigh1_ifinfo = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
+       neigh2_ifinfo = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
+
+       if (!neigh1_ifinfo || !neigh2_ifinfo) {
+               diff = 0;
+               goto out;
+       }
+
+       tq1 = neigh1_ifinfo->bat_iv.tq_avg;
+       tq2 = neigh2_ifinfo->bat_iv.tq_avg;
+       diff = tq1 - tq2;
 
-       tq1 = neigh1->bat_iv.tq_avg;
-       tq2 = neigh2->bat_iv.tq_avg;
+out:
+       if (neigh1_ifinfo)
+               batadv_neigh_ifinfo_free_ref(neigh1_ifinfo);
+       if (neigh2_ifinfo)
+               batadv_neigh_ifinfo_free_ref(neigh2_ifinfo);
 
-       return tq1 - tq2;
+       return diff;
 }
 
 /**
  * batadv_iv_ogm_neigh_is_eob - check if neigh1 is equally good or better than
  *  neigh2 from the metric prospective
  * @neigh1: the first neighbor object of the comparison
+ * @if_outgoing: outgoing interface for the first neighbor
  * @neigh2: the second neighbor object of the comparison
- *
- * Returns true if the metric via neigh1 is equally good or better than the
- * metric via neigh2, false otherwise.
+ * @if_outgoing2: outgoing interface for the second neighbor
+
+ * Returns true if the metric via neigh1 is equally good or better than
+ * the metric via neigh2, false otherwise.
  */
-static bool batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1,
-                                      struct batadv_neigh_node *neigh2)
+static bool
+batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1,
+                          struct batadv_hard_iface *if_outgoing1,
+                          struct batadv_neigh_node *neigh2,
+                          struct batadv_hard_iface *if_outgoing2)
 {
-       int diff = batadv_iv_ogm_neigh_cmp(neigh1, neigh2);
+       struct batadv_neigh_ifinfo *neigh1_ifinfo, *neigh2_ifinfo;
+       uint8_t tq1, tq2;
+       bool ret;
 
-       return diff > -BATADV_TQ_SIMILARITY_THRESHOLD;
+       neigh1_ifinfo = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
+       neigh2_ifinfo = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
+
+       /* we can't say that the metric is better */
+       if (!neigh1_ifinfo || !neigh2_ifinfo) {
+               ret = false;
+               goto out;
+       }
+
+       tq1 = neigh1_ifinfo->bat_iv.tq_avg;
+       tq2 = neigh2_ifinfo->bat_iv.tq_avg;
+       ret = (tq1 - tq2) > -BATADV_TQ_SIMILARITY_THRESHOLD;
+
+out:
+       if (neigh1_ifinfo)
+               batadv_neigh_ifinfo_free_ref(neigh1_ifinfo);
+       if (neigh2_ifinfo)
+               batadv_neigh_ifinfo_free_ref(neigh2_ifinfo);
+
+       return ret;
 }
 
 static struct batadv_algo_ops batadv_batman_iv __read_mostly = {
index 973982414d58559c3ac009f2fb9b2db60a4221ea..9586750022f506d2dd6656d8b38f709dc9ea11a3 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2006-2014 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich, Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
index a81b9322e382b42635d8689085f20d02e602c296..cc2407351d367f74fe9f288fdff79fe8db95f7c3 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2006-2014 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich, Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_BITARRAY_H_
index 28eb5e6d0a02510a0a7b4e268f7dc34a26bc182a..5c0eda48d7a25a3fb7d4b7ea66dbd4262d8e347a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
index da173e760e775caab684d63d2a1749cb55e0b930..43c985d92c3ed66b14959f17c95903e27fd84483 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_BLA_H_
index 049a7a2ac5b69b83422a3292ee7ebb2183e36114..b758881be108c84bfa059cf61f15d44a9008c1c8 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2010-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -250,6 +248,19 @@ static int batadv_originators_open(struct inode *inode, struct file *file)
        return single_open(file, batadv_orig_seq_print_text, net_dev);
 }
 
+/**
+ * batadv_originators_hardif_open - handles debugfs output for the
+ *  originator table of an hard interface
+ * @inode: inode pointer to debugfs file
+ * @file: pointer to the seq_file
+ */
+static int batadv_originators_hardif_open(struct inode *inode,
+                                         struct file *file)
+{
+       struct net_device *net_dev = (struct net_device *)inode->i_private;
+       return single_open(file, batadv_orig_hardif_seq_print_text, net_dev);
+}
+
 static int batadv_gateways_open(struct inode *inode, struct file *file)
 {
        struct net_device *net_dev = (struct net_device *)inode->i_private;
@@ -371,6 +382,28 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
        NULL,
 };
 
+#define BATADV_HARDIF_DEBUGINFO(_name, _mode, _open)           \
+struct batadv_debuginfo batadv_hardif_debuginfo_##_name = {    \
+       .attr = {                                               \
+               .name = __stringify(_name),                     \
+               .mode = _mode,                                  \
+       },                                                      \
+       .fops = {                                               \
+               .owner = THIS_MODULE,                           \
+               .open = _open,                                  \
+               .read   = seq_read,                             \
+               .llseek = seq_lseek,                            \
+               .release = single_release,                      \
+       },                                                      \
+};
+static BATADV_HARDIF_DEBUGINFO(originators, S_IRUGO,
+                              batadv_originators_hardif_open);
+
+static struct batadv_debuginfo *batadv_hardif_debuginfos[] = {
+       &batadv_hardif_debuginfo_originators,
+       NULL,
+};
+
 void batadv_debugfs_init(void)
 {
        struct batadv_debuginfo **bat_debug;
@@ -398,6 +431,7 @@ void batadv_debugfs_init(void)
        return;
 err:
        debugfs_remove_recursive(batadv_debugfs);
+       batadv_debugfs = NULL;
 }
 
 void batadv_debugfs_destroy(void)
@@ -406,6 +440,59 @@ void batadv_debugfs_destroy(void)
        batadv_debugfs = NULL;
 }
 
+/**
+ * batadv_debugfs_add_hardif - creates the base directory for a hard interface
+ *  in debugfs.
+ * @hard_iface: hard interface which should be added.
+ */
+int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface)
+{
+       struct batadv_debuginfo **bat_debug;
+       struct dentry *file;
+
+       if (!batadv_debugfs)
+               goto out;
+
+       hard_iface->debug_dir = debugfs_create_dir(hard_iface->net_dev->name,
+                                                  batadv_debugfs);
+       if (!hard_iface->debug_dir)
+               goto out;
+
+       for (bat_debug = batadv_hardif_debuginfos; *bat_debug; ++bat_debug) {
+               file = debugfs_create_file(((*bat_debug)->attr).name,
+                                          S_IFREG | ((*bat_debug)->attr).mode,
+                                          hard_iface->debug_dir,
+                                          hard_iface->net_dev,
+                                          &(*bat_debug)->fops);
+               if (!file)
+                       goto rem_attr;
+       }
+
+       return 0;
+rem_attr:
+       debugfs_remove_recursive(hard_iface->debug_dir);
+       hard_iface->debug_dir = NULL;
+out:
+#ifdef CONFIG_DEBUG_FS
+       return -ENOMEM;
+#else
+       return 0;
+#endif /* CONFIG_DEBUG_FS */
+}
+
+/**
+ * batadv_debugfs_del_hardif - delete the base directory for a hard interface
+ *  in debugfs.
+ * @hard_iface: hard interface which is deleted.
+ */
+void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface)
+{
+       if (batadv_debugfs) {
+               debugfs_remove_recursive(hard_iface->debug_dir);
+               hard_iface->debug_dir = NULL;
+       }
+}
+
 int batadv_debugfs_add_meshif(struct net_device *dev)
 {
        struct batadv_priv *bat_priv = netdev_priv(dev);
index f8c3849edff428e3d98fbd7f74edfece03235400..37c4d6ddd04d44e4c19eaee97d6b4a877baa0df9 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2010-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_DEBUGFS_H_
@@ -26,5 +24,7 @@ void batadv_debugfs_init(void);
 void batadv_debugfs_destroy(void);
 int batadv_debugfs_add_meshif(struct net_device *dev);
 void batadv_debugfs_del_meshif(struct net_device *dev);
+int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface);
+void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface);
 
 #endif /* _NET_BATMAN_ADV_DEBUGFS_H_ */
index 6c8c3934bd7b44bac8643683683c494e003f1ed2..edee50411892f9ddaafd44a63163e24e79a3ae75 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors:
  *
  * Antonio Quartulli
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/if_ether.h>
@@ -141,7 +139,7 @@ static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
        const void *data1 = container_of(node, struct batadv_dat_entry,
                                         hash_entry);
 
-       return (memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0);
+       return memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0;
 }
 
 /**
@@ -349,7 +347,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       switch (unicast_4addr_packet->u.header.packet_type) {
+       switch (unicast_4addr_packet->u.packet_type) {
        case BATADV_UNICAST:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within a UNICAST packet\n");
@@ -374,7 +372,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
                        break;
                default:
                        batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
-                                  unicast_4addr_packet->u.header.packet_type);
+                                  unicast_4addr_packet->u.packet_type);
                }
                break;
        case BATADV_BCAST:
@@ -387,7 +385,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
        default:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within an unknown packet type (0x%x)\n",
-                          unicast_4addr_packet->u.header.packet_type);
+                          unicast_4addr_packet->u.packet_type);
        }
 }
 
@@ -591,7 +589,8 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
                if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND)
                        continue;
 
-               neigh_node = batadv_orig_node_get_router(cand[i].orig_node);
+               neigh_node = batadv_orig_router_get(cand[i].orig_node,
+                                                   BATADV_IF_DEFAULT);
                if (!neigh_node)
                        goto free_orig;
 
@@ -1039,9 +1038,9 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
        if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
                err = batadv_send_skb_via_tt_4addr(bat_priv, skb_new,
                                                   BATADV_P_DAT_CACHE_REPLY,
-                                                  vid);
+                                                  NULL, vid);
        else
-               err = batadv_send_skb_via_tt(bat_priv, skb_new, vid);
+               err = batadv_send_skb_via_tt(bat_priv, skb_new, NULL, vid);
 
        if (err != NET_XMIT_DROP) {
                batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX);
index 60d853beb8d8214c78d25f191aff77eafaabaefd..ac9be9b67a252a0a8b23088e08bdbbd49b9981b0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors:
  *
  * Antonio Quartulli
  *
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef _NET_BATMAN_ADV_ARP_H_
-#define _NET_BATMAN_ADV_ARP_H_
+#ifndef _NET_BATMAN_ADV_DISTRIBUTED_ARP_TABLE_H_
+#define _NET_BATMAN_ADV_DISTRIBUTED_ARP_TABLE_H_
 
 #ifdef CONFIG_BATMAN_ADV_DAT
 
@@ -169,4 +167,4 @@ static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
 
 #endif /* CONFIG_BATMAN_ADV_DAT */
 
-#endif /* _NET_BATMAN_ADV_ARP_H_ */
+#endif /* _NET_BATMAN_ADV_DISTRIBUTED_ARP_TABLE_H_ */
index 271d321b3a04063b4f9dfe476c7c07d9e2e50048..88df9b1d552de529b20cb699c303ec76034dee12 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2013-2014 B.A.T.M.A.N. contributors:
  *
  * Martin Hundebøll <martin@hundeboll.net>
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -355,7 +353,7 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
                batadv_add_counter(bat_priv, BATADV_CNT_FRAG_FWD_BYTES,
                                   skb->len + ETH_HLEN);
 
-               packet->header.ttl--;
+               packet->ttl--;
                batadv_send_skb_packet(skb, neigh_node->if_incoming,
                                       neigh_node->addr);
                ret = true;
@@ -444,9 +442,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
                goto out_err;
 
        /* Create one header to be copied to all fragments */
-       frag_header.header.packet_type = BATADV_UNICAST_FRAG;
-       frag_header.header.version = BATADV_COMPAT_VERSION;
-       frag_header.header.ttl = BATADV_TTL;
+       frag_header.packet_type = BATADV_UNICAST_FRAG;
+       frag_header.version = BATADV_COMPAT_VERSION;
+       frag_header.ttl = BATADV_TTL;
        frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno));
        frag_header.reserved = 0;
        frag_header.no = 0;
index ca029e2676e704fae6c8f3e30f1cbfdbf38b7938..5d7a0e66a22b35d54baf5910f8b923981d11c0b5 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2013-2014 B.A.T.M.A.N. contributors:
  *
  * Martin Hundebøll <martin@hundeboll.net>
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_FRAGMENTATION_H_
index 2449afaa7638358500c350af3bc39fb5ccc2d72e..55cf2260d295b6f4002d438ed34b52382ed7eeea 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
 #include <linux/udp.h>
 #include <linux/if_vlan.h>
 
-/* This is the offset of the options field in a dhcp packet starting at
- * the beginning of the dhcp header
+/* These are the offsets of the "hw type" and "hw address length" in the dhcp
+ * packet starting at the beginning of the dhcp header
  */
-#define BATADV_DHCP_OPTIONS_OFFSET 240
-#define BATADV_DHCP_REQUEST 3
+#define BATADV_DHCP_HTYPE_OFFSET       1
+#define BATADV_DHCP_HLEN_OFFSET                2
+/* Value of htype representing Ethernet */
+#define BATADV_DHCP_HTYPE_ETHERNET     0x01
+/* This is the offset of the "chaddr" field in the dhcp packet starting at the
+ * beginning of the dhcp header
+ */
+#define BATADV_DHCP_CHADDR_OFFSET      28
 
 static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node)
 {
@@ -105,7 +109,18 @@ static void batadv_gw_select(struct batadv_priv *bat_priv,
        spin_unlock_bh(&bat_priv->gw.list_lock);
 }
 
-void batadv_gw_deselect(struct batadv_priv *bat_priv)
+/**
+ * batadv_gw_reselect - force a gateway reselection
+ * @bat_priv: the bat priv with all the soft interface information
+ *
+ * Set a flag to remind the GW component to perform a new gateway reselection.
+ * However this function does not ensure that the current gateway is going to be
+ * deselected. The reselection mechanism may elect the same gateway once again.
+ *
+ * This means that invoking batadv_gw_reselect() does not guarantee a gateway
+ * change and therefore a uevent is not necessarily expected.
+ */
+void batadv_gw_reselect(struct batadv_priv *bat_priv)
 {
        atomic_set(&bat_priv->gw.reselect, 1);
 }
@@ -114,6 +129,7 @@ static struct batadv_gw_node *
 batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 {
        struct batadv_neigh_node *router;
+       struct batadv_neigh_ifinfo *router_ifinfo;
        struct batadv_gw_node *gw_node, *curr_gw = NULL;
        uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
        uint32_t gw_divisor;
@@ -130,14 +146,19 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
                        continue;
 
                orig_node = gw_node->orig_node;
-               router = batadv_orig_node_get_router(orig_node);
+               router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
                if (!router)
                        continue;
 
+               router_ifinfo = batadv_neigh_ifinfo_get(router,
+                                                       BATADV_IF_DEFAULT);
+               if (!router_ifinfo)
+                       goto next;
+
                if (!atomic_inc_not_zero(&gw_node->refcount))
                        goto next;
 
-               tq_avg = router->bat_iv.tq_avg;
+               tq_avg = router_ifinfo->bat_iv.tq_avg;
 
                switch (atomic_read(&bat_priv->gw_sel_class)) {
                case 1: /* fast connection */
@@ -182,6 +203,8 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 
 next:
                batadv_neigh_node_free_ref(router);
+               if (router_ifinfo)
+                       batadv_neigh_ifinfo_free_ref(router_ifinfo);
        }
        rcu_read_unlock();
 
@@ -207,6 +230,11 @@ void batadv_gw_check_client_stop(struct batadv_priv *bat_priv)
        if (!curr_gw)
                return;
 
+       /* deselect the current gateway so that next time that client mode is
+        * enabled a proper GW_ADD event can be sent
+        */
+       batadv_gw_select(bat_priv, NULL);
+
        /* if batman-adv is switching the gw client mode off and a gateway was
         * already selected, send a DEL uevent
         */
@@ -219,6 +247,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
 {
        struct batadv_gw_node *curr_gw = NULL, *next_gw = NULL;
        struct batadv_neigh_node *router = NULL;
+       struct batadv_neigh_ifinfo *router_ifinfo = NULL;
        char gw_addr[18] = { '\0' };
 
        if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT)
@@ -237,9 +266,17 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
        if (next_gw) {
                sprintf(gw_addr, "%pM", next_gw->orig_node->orig);
 
-               router = batadv_orig_node_get_router(next_gw->orig_node);
+               router = batadv_orig_router_get(next_gw->orig_node,
+                                               BATADV_IF_DEFAULT);
                if (!router) {
-                       batadv_gw_deselect(bat_priv);
+                       batadv_gw_reselect(bat_priv);
+                       goto out;
+               }
+
+               router_ifinfo = batadv_neigh_ifinfo_get(router,
+                                                       BATADV_IF_DEFAULT);
+               if (!router_ifinfo) {
+                       batadv_gw_reselect(bat_priv);
                        goto out;
                }
        }
@@ -256,7 +293,8 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
                           next_gw->bandwidth_down / 10,
                           next_gw->bandwidth_down % 10,
                           next_gw->bandwidth_up / 10,
-                          next_gw->bandwidth_up % 10, router->bat_iv.tq_avg);
+                          next_gw->bandwidth_up % 10,
+                          router_ifinfo->bat_iv.tq_avg);
                batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD,
                                    gw_addr);
        } else {
@@ -266,7 +304,8 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
                           next_gw->bandwidth_down / 10,
                           next_gw->bandwidth_down % 10,
                           next_gw->bandwidth_up / 10,
-                          next_gw->bandwidth_up % 10, router->bat_iv.tq_avg);
+                          next_gw->bandwidth_up % 10,
+                          router_ifinfo->bat_iv.tq_avg);
                batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE,
                                    gw_addr);
        }
@@ -280,33 +319,47 @@ out:
                batadv_gw_node_free_ref(next_gw);
        if (router)
                batadv_neigh_node_free_ref(router);
+       if (router_ifinfo)
+               batadv_neigh_ifinfo_free_ref(router_ifinfo);
 }
 
 void batadv_gw_check_election(struct batadv_priv *bat_priv,
                              struct batadv_orig_node *orig_node)
 {
+       struct batadv_neigh_ifinfo *router_orig_tq = NULL;
+       struct batadv_neigh_ifinfo *router_gw_tq = NULL;
        struct batadv_orig_node *curr_gw_orig;
        struct batadv_neigh_node *router_gw = NULL, *router_orig = NULL;
        uint8_t gw_tq_avg, orig_tq_avg;
 
        curr_gw_orig = batadv_gw_get_selected_orig(bat_priv);
        if (!curr_gw_orig)
-               goto deselect;
+               goto reselect;
 
-       router_gw = batadv_orig_node_get_router(curr_gw_orig);
+       router_gw = batadv_orig_router_get(curr_gw_orig, BATADV_IF_DEFAULT);
        if (!router_gw)
-               goto deselect;
+               goto reselect;
+
+       router_gw_tq = batadv_neigh_ifinfo_get(router_gw,
+                                              BATADV_IF_DEFAULT);
+       if (!router_gw_tq)
+               goto reselect;
 
        /* this node already is the gateway */
        if (curr_gw_orig == orig_node)
                goto out;
 
-       router_orig = batadv_orig_node_get_router(orig_node);
+       router_orig = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
        if (!router_orig)
                goto out;
 
-       gw_tq_avg = router_gw->bat_iv.tq_avg;
-       orig_tq_avg = router_orig->bat_iv.tq_avg;
+       router_orig_tq = batadv_neigh_ifinfo_get(router_orig,
+                                                BATADV_IF_DEFAULT);
+       if (!router_orig_tq)
+               goto out;
+
+       gw_tq_avg = router_gw_tq->bat_iv.tq_avg;
+       orig_tq_avg = router_orig_tq->bat_iv.tq_avg;
 
        /* the TQ value has to be better */
        if (orig_tq_avg < gw_tq_avg)
@@ -323,8 +376,8 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
                   "Restarting gateway selection: better gateway found (tq curr: %i, tq new: %i)\n",
                   gw_tq_avg, orig_tq_avg);
 
-deselect:
-       batadv_gw_deselect(bat_priv);
+reselect:
+       batadv_gw_reselect(bat_priv);
 out:
        if (curr_gw_orig)
                batadv_orig_node_free_ref(curr_gw_orig);
@@ -332,6 +385,10 @@ out:
                batadv_neigh_node_free_ref(router_gw);
        if (router_orig)
                batadv_neigh_node_free_ref(router_orig);
+       if (router_gw_tq)
+               batadv_neigh_ifinfo_free_ref(router_gw_tq);
+       if (router_orig_tq)
+               batadv_neigh_ifinfo_free_ref(router_orig_tq);
 
        return;
 }
@@ -454,7 +511,7 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
                 */
                curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
                if (gw_node == curr_gw)
-                       batadv_gw_deselect(bat_priv);
+                       batadv_gw_reselect(bat_priv);
        }
 
 out:
@@ -480,7 +537,7 @@ void batadv_gw_node_purge(struct batadv_priv *bat_priv)
        struct batadv_gw_node *gw_node, *curr_gw;
        struct hlist_node *node_tmp;
        unsigned long timeout = msecs_to_jiffies(2 * BATADV_PURGE_TIMEOUT);
-       int do_deselect = 0;
+       int do_reselect = 0;
 
        curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 
@@ -494,7 +551,7 @@ void batadv_gw_node_purge(struct batadv_priv *bat_priv)
                        continue;
 
                if (curr_gw == gw_node)
-                       do_deselect = 1;
+                       do_reselect = 1;
 
                hlist_del_rcu(&gw_node->list);
                batadv_gw_node_free_ref(gw_node);
@@ -502,9 +559,9 @@ void batadv_gw_node_purge(struct batadv_priv *bat_priv)
 
        spin_unlock_bh(&bat_priv->gw.list_lock);
 
-       /* gw_deselect() needs to acquire the gw_list_lock */
-       if (do_deselect)
-               batadv_gw_deselect(bat_priv);
+       /* gw_reselect() needs to acquire the gw_list_lock */
+       if (do_reselect)
+               batadv_gw_reselect(bat_priv);
 
        if (curr_gw)
                batadv_gw_node_free_ref(curr_gw);
@@ -517,28 +574,36 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv,
 {
        struct batadv_gw_node *curr_gw;
        struct batadv_neigh_node *router;
+       struct batadv_neigh_ifinfo *router_ifinfo = NULL;
        int ret = -1;
 
-       router = batadv_orig_node_get_router(gw_node->orig_node);
+       router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT);
        if (!router)
                goto out;
 
+       router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
+       if (!router_ifinfo)
+               goto out;
+
        curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 
        ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n",
                         (curr_gw == gw_node ? "=>" : "  "),
                         gw_node->orig_node->orig,
-                        router->bat_iv.tq_avg, router->addr,
+                        router_ifinfo->bat_iv.tq_avg, router->addr,
                         router->if_incoming->net_dev->name,
                         gw_node->bandwidth_down / 10,
                         gw_node->bandwidth_down % 10,
                         gw_node->bandwidth_up / 10,
                         gw_node->bandwidth_up % 10);
 
-       batadv_neigh_node_free_ref(router);
        if (curr_gw)
                batadv_gw_node_free_ref(curr_gw);
 out:
+       if (router_ifinfo)
+               batadv_neigh_ifinfo_free_ref(router_ifinfo);
+       if (router)
+               batadv_neigh_node_free_ref(router);
        return ret;
 }
 
@@ -582,80 +647,39 @@ out:
        return 0;
 }
 
-/* this call might reallocate skb data */
-static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
-{
-       int ret = false;
-       unsigned char *p;
-       int pkt_len;
-
-       if (skb_linearize(skb) < 0)
-               goto out;
-
-       pkt_len = skb_headlen(skb);
-
-       if (pkt_len < header_len + BATADV_DHCP_OPTIONS_OFFSET + 1)
-               goto out;
-
-       p = skb->data + header_len + BATADV_DHCP_OPTIONS_OFFSET;
-       pkt_len -= header_len + BATADV_DHCP_OPTIONS_OFFSET + 1;
-
-       /* Access the dhcp option lists. Each entry is made up by:
-        * - octet 1: option type
-        * - octet 2: option data len (only if type != 255 and 0)
-        * - octet 3: option data
-        */
-       while (*p != 255 && !ret) {
-               /* p now points to the first octet: option type */
-               if (*p == 53) {
-                       /* type 53 is the message type option.
-                        * Jump the len octet and go to the data octet
-                        */
-                       if (pkt_len < 2)
-                               goto out;
-                       p += 2;
-
-                       /* check if the message type is what we need */
-                       if (*p == BATADV_DHCP_REQUEST)
-                               ret = true;
-                       break;
-               } else if (*p == 0) {
-                       /* option type 0 (padding), just go forward */
-                       if (pkt_len < 1)
-                               goto out;
-                       pkt_len--;
-                       p++;
-               } else {
-                       /* This is any other option. So we get the length... */
-                       if (pkt_len < 1)
-                               goto out;
-                       pkt_len--;
-                       p++;
-
-                       /* ...and then we jump over the data */
-                       if (pkt_len < 1 + (*p))
-                               goto out;
-                       pkt_len -= 1 + (*p);
-                       p += 1 + (*p);
-               }
-       }
-out:
-       return ret;
-}
-
-/* this call might reallocate skb data */
-bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
+/**
+ * batadv_gw_dhcp_recipient_get - check if a packet is a DHCP message
+ * @skb: the packet to check
+ * @header_len: a pointer to the batman-adv header size
+ * @chaddr: buffer where the client address will be stored. Valid
+ *  only if the function returns BATADV_DHCP_TO_CLIENT
+ *
+ * Returns:
+ * - BATADV_DHCP_NO if the packet is not a dhcp message or if there was an error
+ *   while parsing it
+ * - BATADV_DHCP_TO_SERVER if this is a message going to the DHCP server
+ * - BATADV_DHCP_TO_CLIENT if this is a message going to a DHCP client
+ *
+ * This function may re-allocate the data buffer of the skb passed as argument.
+ */
+enum batadv_dhcp_recipient
+batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len,
+                            uint8_t *chaddr)
 {
+       enum batadv_dhcp_recipient ret = BATADV_DHCP_NO;
        struct ethhdr *ethhdr;
        struct iphdr *iphdr;
        struct ipv6hdr *ipv6hdr;
        struct udphdr *udphdr;
        struct vlan_ethhdr *vhdr;
+       int chaddr_offset;
        __be16 proto;
+       uint8_t *p;
 
        /* check for ethernet header */
        if (!pskb_may_pull(skb, *header_len + ETH_HLEN))
-               return false;
+               return BATADV_DHCP_NO;
+
        ethhdr = (struct ethhdr *)skb->data;
        proto = ethhdr->h_proto;
        *header_len += ETH_HLEN;
@@ -663,7 +687,7 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
        /* check for initial vlan header */
        if (proto == htons(ETH_P_8021Q)) {
                if (!pskb_may_pull(skb, *header_len + VLAN_HLEN))
-                       return false;
+                       return BATADV_DHCP_NO;
 
                vhdr = (struct vlan_ethhdr *)skb->data;
                proto = vhdr->h_vlan_encapsulated_proto;
@@ -674,32 +698,34 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
        switch (proto) {
        case htons(ETH_P_IP):
                if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr)))
-                       return false;
+                       return BATADV_DHCP_NO;
+
                iphdr = (struct iphdr *)(skb->data + *header_len);
                *header_len += iphdr->ihl * 4;
 
                /* check for udp header */
                if (iphdr->protocol != IPPROTO_UDP)
-                       return false;
+                       return BATADV_DHCP_NO;
 
                break;
        case htons(ETH_P_IPV6):
                if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr)))
-                       return false;
+                       return BATADV_DHCP_NO;
+
                ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len);
                *header_len += sizeof(*ipv6hdr);
 
                /* check for udp header */
                if (ipv6hdr->nexthdr != IPPROTO_UDP)
-                       return false;
+                       return BATADV_DHCP_NO;
 
                break;
        default:
-               return false;
+               return BATADV_DHCP_NO;
        }
 
        if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
-               return false;
+               return BATADV_DHCP_NO;
 
        /* skb->data might have been reallocated by pskb_may_pull() */
        ethhdr = (struct ethhdr *)skb->data;
@@ -710,17 +736,40 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
        *header_len += sizeof(*udphdr);
 
        /* check for bootp port */
-       if ((proto == htons(ETH_P_IP)) &&
-           (udphdr->dest != htons(67)))
-               return false;
+       switch (proto) {
+       case htons(ETH_P_IP):
+               if (udphdr->dest == htons(67))
+                       ret = BATADV_DHCP_TO_SERVER;
+               else if (udphdr->source == htons(67))
+                       ret = BATADV_DHCP_TO_CLIENT;
+               break;
+       case htons(ETH_P_IPV6):
+               if (udphdr->dest == htons(547))
+                       ret = BATADV_DHCP_TO_SERVER;
+               else if (udphdr->source == htons(547))
+                       ret = BATADV_DHCP_TO_CLIENT;
+               break;
+       }
 
-       if ((proto == htons(ETH_P_IPV6)) &&
-           (udphdr->dest != htons(547)))
-               return false;
+       chaddr_offset = *header_len + BATADV_DHCP_CHADDR_OFFSET;
+       /* store the client address if the message is going to a client */
+       if (ret == BATADV_DHCP_TO_CLIENT &&
+           pskb_may_pull(skb, chaddr_offset + ETH_ALEN)) {
+               /* check if the DHCP packet carries an Ethernet DHCP */
+               p = skb->data + *header_len + BATADV_DHCP_HTYPE_OFFSET;
+               if (*p != BATADV_DHCP_HTYPE_ETHERNET)
+                       return BATADV_DHCP_NO;
+
+               /* check if the DHCP packet carries a valid Ethernet address */
+               p = skb->data + *header_len + BATADV_DHCP_HLEN_OFFSET;
+               if (*p != ETH_ALEN)
+                       return BATADV_DHCP_NO;
+
+               memcpy(chaddr, skb->data + chaddr_offset, ETH_ALEN);
+       }
 
-       return true;
+       return ret;
 }
-
 /**
  * batadv_gw_out_of_range - check if the dhcp request destination is the best gw
  * @bat_priv: the bat priv with all the soft interface information
@@ -734,6 +783,7 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
  * false otherwise.
  *
  * This call might reallocate skb data.
+ * Must be invoked only when the DHCP packet is going TO a DHCP SERVER.
  */
 bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
                            struct sk_buff *skb)
@@ -741,19 +791,14 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
        struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL;
        struct batadv_orig_node *orig_dst_node = NULL;
        struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL;
-       struct ethhdr *ethhdr;
-       bool ret, out_of_range = false;
-       unsigned int header_len = 0;
+       struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo;
+       struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
+       bool out_of_range = false;
        uint8_t curr_tq_avg;
        unsigned short vid;
 
        vid = batadv_get_vid(skb, 0);
 
-       ret = batadv_gw_is_dhcp_target(skb, &header_len);
-       if (!ret)
-               goto out;
-
-       ethhdr = (struct ethhdr *)skb->data;
        orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
                                                 ethhdr->h_dest, vid);
        if (!orig_dst_node)
@@ -763,10 +808,6 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
        if (!gw_node->bandwidth_down == 0)
                goto out;
 
-       ret = batadv_is_type_dhcprequest(skb, header_len);
-       if (!ret)
-               goto out;
-
        switch (atomic_read(&bat_priv->gw_mode)) {
        case BATADV_GW_MODE_SERVER:
                /* If we are a GW then we are our best GW. We can artificially
@@ -792,7 +833,14 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
                if (!neigh_curr)
                        goto out;
 
-               curr_tq_avg = neigh_curr->bat_iv.tq_avg;
+               curr_ifinfo = batadv_neigh_ifinfo_get(neigh_curr,
+                                                     BATADV_IF_DEFAULT);
+               if (!curr_ifinfo)
+                       goto out;
+
+               curr_tq_avg = curr_ifinfo->bat_iv.tq_avg;
+               batadv_neigh_ifinfo_free_ref(curr_ifinfo);
+
                break;
        case BATADV_GW_MODE_OFF:
        default:
@@ -803,8 +851,13 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
        if (!neigh_old)
                goto out;
 
-       if (curr_tq_avg - neigh_old->bat_iv.tq_avg > BATADV_GW_THRESHOLD)
+       old_ifinfo = batadv_neigh_ifinfo_get(neigh_old, BATADV_IF_DEFAULT);
+       if (!old_ifinfo)
+               goto out;
+
+       if ((curr_tq_avg - old_ifinfo->bat_iv.tq_avg) > BATADV_GW_THRESHOLD)
                out_of_range = true;
+       batadv_neigh_ifinfo_free_ref(old_ifinfo);
 
 out:
        if (orig_dst_node)
index d95c2d23195ee962496667d449a25d7b58b2741c..7ee53bb7d50f20926083132069b370d4d893dc25 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_GATEWAY_CLIENT_H_
 #define _NET_BATMAN_ADV_GATEWAY_CLIENT_H_
 
 void batadv_gw_check_client_stop(struct batadv_priv *bat_priv);
-void batadv_gw_deselect(struct batadv_priv *bat_priv);
+void batadv_gw_reselect(struct batadv_priv *bat_priv);
 void batadv_gw_election(struct batadv_priv *bat_priv);
 struct batadv_orig_node *
 batadv_gw_get_selected_orig(struct batadv_priv *bat_priv);
@@ -34,7 +32,9 @@ void batadv_gw_node_delete(struct batadv_priv *bat_priv,
                           struct batadv_orig_node *orig_node);
 void batadv_gw_node_purge(struct batadv_priv *bat_priv);
 int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset);
-bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len);
 bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb);
+enum batadv_dhcp_recipient
+batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len,
+                            uint8_t *chaddr);
 
 #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
index b211b0f9cb788efa2b476616dd534675fb746b66..6f5e621f220ae0d6c419cff55aa87094c12f59d0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -164,7 +162,7 @@ ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
        if ((down_curr == down_new) && (up_curr == up_new))
                return count;
 
-       batadv_gw_deselect(bat_priv);
+       batadv_gw_reselect(bat_priv);
        batadv_info(net_dev,
                    "Changing gateway bandwidth from: '%u.%u/%u.%u MBit' to: '%u.%u/%u.%u MBit'\n",
                    down_curr / 10, down_curr % 10, up_curr / 10, up_curr % 10,
index 56384a4cd18c98a2ac9010ea14bb89acf3a2d06d..aa51165619476bfd654fda9cafca026e8fc9dea2 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_GATEWAY_COMMON_H_
index 57c2a19dcb5c8e19c410b27528f22eb671ed528a..1b12573bcf83ea497d201469773890f91b74ad27 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -25,6 +23,7 @@
 #include "translation-table.h"
 #include "routing.h"
 #include "sysfs.h"
+#include "debugfs.h"
 #include "originator.h"
 #include "hash.h"
 #include "bridge_loop_avoidance.h"
@@ -541,6 +540,7 @@ static void batadv_hardif_remove_interface_finish(struct work_struct *work)
        hard_iface = container_of(work, struct batadv_hard_iface,
                                  cleanup_work);
 
+       batadv_debugfs_del_hardif(hard_iface);
        batadv_sysfs_del_hardif(&hard_iface->hardif_obj);
        batadv_hardif_free_ref(hard_iface);
 }
@@ -571,6 +571,11 @@ batadv_hardif_add_interface(struct net_device *net_dev)
        hard_iface->net_dev = net_dev;
        hard_iface->soft_iface = NULL;
        hard_iface->if_status = BATADV_IF_NOT_IN_USE;
+
+       ret = batadv_debugfs_add_hardif(hard_iface);
+       if (ret)
+               goto free_sysfs;
+
        INIT_LIST_HEAD(&hard_iface->list);
        INIT_WORK(&hard_iface->cleanup_work,
                  batadv_hardif_remove_interface_finish);
@@ -587,6 +592,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
 
        return hard_iface;
 
+free_sysfs:
+       batadv_sysfs_del_hardif(&hard_iface->hardif_obj);
 free_if:
        kfree(hard_iface);
 release_dev:
index df4c8bd45c40748a5442999012ab581adf1d1d71..1918cd50b62ed7254a043f1cf02acce1ab207b4c 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_HARD_INTERFACE_H_
@@ -42,6 +40,7 @@ enum batadv_hard_if_cleanup {
 extern struct notifier_block batadv_hard_if_notifier;
 
 bool batadv_is_wifi_netdev(struct net_device *net_device);
+bool batadv_is_wifi_iface(int ifindex);
 struct batadv_hard_iface*
 batadv_hardif_get_by_netdev(const struct net_device *net_dev);
 int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
@@ -53,6 +52,11 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface);
 void batadv_update_min_mtu(struct net_device *soft_iface);
 void batadv_hardif_free_rcu(struct rcu_head *rcu);
 
+/**
+ * batadv_hardif_free_ref - decrement the hard interface refcounter and
+ *  possibly free it
+ * @hard_iface: the hard interface to free
+ */
 static inline void
 batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface)
 {
@@ -60,6 +64,18 @@ batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface)
                call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu);
 }
 
+/**
+ * batadv_hardif_free_ref_now - decrement the hard interface refcounter and
+ *  possibly free it (without rcu callback)
+ * @hard_iface: the hard interface to free
+ */
+static inline void
+batadv_hardif_free_ref_now(struct batadv_hard_iface *hard_iface)
+{
+       if (atomic_dec_and_test(&hard_iface->refcount))
+               batadv_hardif_free_rcu(&hard_iface->rcu);
+}
+
 static inline struct batadv_hard_iface *
 batadv_primary_if_get_selected(struct batadv_priv *bat_priv)
 {
index 7198dafd3bf353b97c13a798d1daeed705fb4e30..63bdf7e94f1ef59964ee39f51a0d0b802b2ca586 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2006-2014 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich, Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
index 1b4da72f2093e0f77b08702febf7a0f120e12ff8..539fc12667938f75319b34f3b0f4b45551d54053 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2006-2014 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich, Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_HASH_H_
index 29ae4efe3543e4bfc6ff013b9c97628b9e395209..abb9d6e0388be65a20e0c19d377f7bdda47ea1da 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -194,7 +192,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
                goto free_skb;
        }
 
-       if (icmp_header->header.packet_type != BATADV_ICMP) {
+       if (icmp_header->packet_type != BATADV_ICMP) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
                len = -EINVAL;
@@ -217,7 +215,8 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
                if (!orig_node)
                        goto dst_unreach;
 
-               neigh_node = batadv_orig_node_get_router(orig_node);
+               neigh_node = batadv_orig_router_get(orig_node,
+                                                   BATADV_IF_DEFAULT);
                if (!neigh_node)
                        goto dst_unreach;
 
@@ -243,9 +242,9 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
 
        icmp_header->uid = socket_client->index;
 
-       if (icmp_header->header.version != BATADV_COMPAT_VERSION) {
+       if (icmp_header->version != BATADV_COMPAT_VERSION) {
                icmp_header->msg_type = BATADV_PARAMETER_PROBLEM;
-               icmp_header->header.version = BATADV_COMPAT_VERSION;
+               icmp_header->version = BATADV_COMPAT_VERSION;
                batadv_socket_add_packet(socket_client, icmp_header,
                                         packet_len);
                goto free_skb;
index 6665080dff7950bc904c54fef35f91dd3135946a..0c33950aa4aac62f59eb23fa4141499760b2de24 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_ICMP_SOCKET_H_
index c51a5e568f0a80c08beb4ded5b34b1aff8d5cfdf..e56b4d6a43b6745d4a2b2870a04991e5b03d73d0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/crc32c.h>
@@ -383,17 +381,17 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data;
 
-       if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) {
+       if (batadv_ogm_packet->version != BATADV_COMPAT_VERSION) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Drop packet: incompatible batman version (%i)\n",
-                          batadv_ogm_packet->header.version);
+                          batadv_ogm_packet->version);
                goto err_free;
        }
 
        /* all receive handlers return whether they received or reused
         * the supplied skb. if not, we have to free the skb.
         */
-       idx = batadv_ogm_packet->header.packet_type;
+       idx = batadv_ogm_packet->packet_type;
        ret = (*batadv_rx_handler[idx])(skb, hard_iface);
 
        if (ret == NET_RX_DROP)
@@ -421,13 +419,23 @@ static void batadv_recv_handler_init(void)
        for (i = BATADV_UNICAST_MIN; i <= BATADV_UNICAST_MAX; i++)
                batadv_rx_handler[i] = batadv_recv_unhandled_unicast_packet;
 
-       /* compile time checks for struct member offsets */
-       BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10);
-       BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, icmph.dst) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, icmph.dst) != 4);
+       /* compile time checks for sizes */
+       BUILD_BUG_ON(sizeof(struct batadv_bla_claim_dst) != 6);
+       BUILD_BUG_ON(sizeof(struct batadv_ogm_packet) != 24);
+       BUILD_BUG_ON(sizeof(struct batadv_icmp_header) != 20);
+       BUILD_BUG_ON(sizeof(struct batadv_icmp_packet) != 20);
+       BUILD_BUG_ON(sizeof(struct batadv_icmp_packet_rr) != 116);
+       BUILD_BUG_ON(sizeof(struct batadv_unicast_packet) != 10);
+       BUILD_BUG_ON(sizeof(struct batadv_unicast_4addr_packet) != 18);
+       BUILD_BUG_ON(sizeof(struct batadv_frag_packet) != 20);
+       BUILD_BUG_ON(sizeof(struct batadv_bcast_packet) != 14);
+       BUILD_BUG_ON(sizeof(struct batadv_coded_packet) != 46);
+       BUILD_BUG_ON(sizeof(struct batadv_unicast_tvlv_packet) != 20);
+       BUILD_BUG_ON(sizeof(struct batadv_tvlv_hdr) != 4);
+       BUILD_BUG_ON(sizeof(struct batadv_tvlv_gateway_data) != 8);
+       BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_vlan_data) != 8);
+       BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_change) != 12);
+       BUILD_BUG_ON(sizeof(struct batadv_tvlv_roam_adv) != 8);
 
        /* broadcast packet */
        batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
@@ -1119,9 +1127,9 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
        skb_reserve(skb, ETH_HLEN);
        tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
        unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
-       unicast_tvlv_packet->header.packet_type = BATADV_UNICAST_TVLV;
-       unicast_tvlv_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_tvlv_packet->header.ttl = BATADV_TTL;
+       unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV;
+       unicast_tvlv_packet->version = BATADV_COMPAT_VERSION;
+       unicast_tvlv_packet->ttl = BATADV_TTL;
        unicast_tvlv_packet->reserved = 0;
        unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
        unicast_tvlv_packet->align = 0;
@@ -1173,6 +1181,32 @@ unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len)
        return vid;
 }
 
+/**
+ * batadv_vlan_ap_isola_get - return the AP isolation status for the given vlan
+ * @bat_priv: the bat priv with all the soft interface information
+ * @vid: the VLAN identifier for which the AP isolation attributed as to be
+ *  looked up
+ *
+ * Returns true if AP isolation is on for the VLAN idenfied by vid, false
+ * otherwise
+ */
+bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid)
+{
+       bool ap_isolation_enabled = false;
+       struct batadv_softif_vlan *vlan;
+
+       /* if the AP isolation is requested on a VLAN, then check for its
+        * setting in the proper VLAN private data structure
+        */
+       vlan = batadv_softif_vlan_get(bat_priv, vid);
+       if (vlan) {
+               ap_isolation_enabled = atomic_read(&vlan->ap_isolation);
+               batadv_softif_vlan_free_ref(vlan);
+       }
+
+       return ap_isolation_enabled;
+}
+
 static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
 {
        struct batadv_algo_ops *bat_algo_ops;
index 322dd7323732cf724f1bedbdc0f7d246bff1bb20..9374f1a51348514d7b5af1eb6767128bac4d744d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_MAIN_H_
@@ -26,7 +24,7 @@
 #define BATADV_DRIVER_DEVICE "batman-adv"
 
 #ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2013.5.0"
+#define BATADV_SOURCE_VERSION "2014.1.0"
 #endif
 
 /* B.A.T.M.A.N. parameters */
 
 #define BATADV_NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */
 
+#define BATADV_NO_MARK 0
+
+/* default interface for multi interface operation. The default interface is
+ * used for communication which originated locally (i.e. is not forwarded)
+ * or where special forwarding is not desired/necessary.
+ */
+#define BATADV_IF_DEFAULT      ((struct batadv_hard_iface *)NULL)
+
 #define BATADV_NUM_WORDS BITS_TO_LONGS(BATADV_TQ_LOCAL_WINDOW_SIZE)
 
 #define BATADV_LOG_BUF_LEN 8192          /* has to be a power of 2 */
@@ -369,5 +375,6 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
                              uint8_t *dst, uint8_t type, uint8_t version,
                              void *tvlv_value, uint16_t tvlv_value_len);
 unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len);
+bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid);
 
 #endif /* _NET_BATMAN_ADV_MAIN_H_ */
index 351e199bc0afff37aa9c1a4b3f40201956dfde91..f1b604d88dc3c2124c86083f36e5bafaad50b9bc 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2012-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2012-2014 B.A.T.M.A.N. contributors:
  *
  * Martin Hundebøll, Jeppe Ledet-Pedersen
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/debugfs.h>
@@ -720,9 +718,21 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
                                    struct batadv_orig_node *orig_node,
                                    struct batadv_ogm_packet *ogm_packet)
 {
-       if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno))
+       struct batadv_orig_ifinfo *orig_ifinfo;
+       uint32_t last_real_seqno;
+       uint8_t last_ttl;
+
+       orig_ifinfo = batadv_orig_ifinfo_get(orig_node, BATADV_IF_DEFAULT);
+       if (!orig_ifinfo)
                return false;
-       if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
+
+       last_ttl = orig_ifinfo->last_ttl;
+       last_real_seqno = orig_ifinfo->last_real_seqno;
+       batadv_orig_ifinfo_free_ref(orig_ifinfo);
+
+       if (last_real_seqno != ntohl(ogm_packet->seqno))
+               return false;
+       if (last_ttl != ogm_packet->ttl + 1)
                return false;
        if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
                return false;
@@ -1010,6 +1020,8 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        struct batadv_coded_packet *coded_packet;
        struct batadv_neigh_node *neigh_tmp, *router_neigh;
        struct batadv_neigh_node *router_coding = NULL;
+       struct batadv_neigh_ifinfo *router_neigh_ifinfo = NULL;
+       struct batadv_neigh_ifinfo *router_coding_ifinfo = NULL;
        uint8_t *first_source, *first_dest, *second_source, *second_dest;
        __be32 packet_id1, packet_id2;
        size_t count;
@@ -1019,19 +1031,34 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        int coded_size = sizeof(*coded_packet);
        int header_add = coded_size - unicast_size;
 
-       router_neigh = batadv_orig_node_get_router(neigh_node->orig_node);
+       /* TODO: do we need to consider the outgoing interface for
+        * coded packets?
+        */
+       router_neigh = batadv_orig_router_get(neigh_node->orig_node,
+                                             BATADV_IF_DEFAULT);
        if (!router_neigh)
                goto out;
 
+       router_neigh_ifinfo = batadv_neigh_ifinfo_get(router_neigh,
+                                                     BATADV_IF_DEFAULT);
+       if (!router_neigh_ifinfo)
+               goto out;
+
        neigh_tmp = nc_packet->neigh_node;
-       router_coding = batadv_orig_node_get_router(neigh_tmp->orig_node);
+       router_coding = batadv_orig_router_get(neigh_tmp->orig_node,
+                                              BATADV_IF_DEFAULT);
        if (!router_coding)
                goto out;
 
-       tq_tmp = batadv_nc_random_weight_tq(router_neigh->bat_iv.tq_avg);
-       tq_weighted_neigh = tq_tmp;
-       tq_tmp = batadv_nc_random_weight_tq(router_coding->bat_iv.tq_avg);
-       tq_weighted_coding = tq_tmp;
+       router_coding_ifinfo = batadv_neigh_ifinfo_get(router_coding,
+                                                      BATADV_IF_DEFAULT);
+       if (!router_coding_ifinfo)
+               goto out;
+
+       tq_tmp = router_neigh_ifinfo->bat_iv.tq_avg;
+       tq_weighted_neigh = batadv_nc_random_weight_tq(tq_tmp);
+       tq_tmp = router_coding_ifinfo->bat_iv.tq_avg;
+       tq_weighted_coding = batadv_nc_random_weight_tq(tq_tmp);
 
        /* Select one destination for the MAC-header dst-field based on
         * weighted TQ-values.
@@ -1082,9 +1109,9 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        coded_packet = (struct batadv_coded_packet *)skb_dest->data;
        skb_reset_mac_header(skb_dest);
 
-       coded_packet->header.packet_type = BATADV_CODED;
-       coded_packet->header.version = BATADV_COMPAT_VERSION;
-       coded_packet->header.ttl = packet1->header.ttl;
+       coded_packet->packet_type = BATADV_CODED;
+       coded_packet->version = BATADV_COMPAT_VERSION;
+       coded_packet->ttl = packet1->ttl;
 
        /* Info about first unicast packet */
        memcpy(coded_packet->first_source, first_source, ETH_ALEN);
@@ -1097,7 +1124,7 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        memcpy(coded_packet->second_source, second_source, ETH_ALEN);
        memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN);
        coded_packet->second_crc = packet_id2;
-       coded_packet->second_ttl = packet2->header.ttl;
+       coded_packet->second_ttl = packet2->ttl;
        coded_packet->second_ttvn = packet2->ttvn;
        coded_packet->coded_len = htons(coding_len);
 
@@ -1155,6 +1182,10 @@ out:
                batadv_neigh_node_free_ref(router_neigh);
        if (router_coding)
                batadv_neigh_node_free_ref(router_coding);
+       if (router_neigh_ifinfo)
+               batadv_neigh_ifinfo_free_ref(router_neigh_ifinfo);
+       if (router_coding_ifinfo)
+               batadv_neigh_ifinfo_free_ref(router_coding_ifinfo);
        return res;
 }
 
@@ -1452,7 +1483,7 @@ bool batadv_nc_skb_forward(struct sk_buff *skb,
        /* We only handle unicast packets */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Try to find a coding opportunity and send the skb if one is found */
@@ -1505,7 +1536,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
        /* Check for supported packet type */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Find existing nc_path or create a new */
@@ -1623,7 +1654,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
                ttvn = coded_packet_tmp.second_ttvn;
        } else {
                orig_dest = coded_packet_tmp.first_orig_dest;
-               ttl = coded_packet_tmp.header.ttl;
+               ttl = coded_packet_tmp.ttl;
                ttvn = coded_packet_tmp.first_ttvn;
        }
 
@@ -1648,9 +1679,9 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        /* Create decoded unicast packet */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.packet_type = BATADV_UNICAST;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_packet->header.ttl = ttl;
+       unicast_packet->packet_type = BATADV_UNICAST;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
+       unicast_packet->ttl = ttl;
        memcpy(unicast_packet->dest, orig_dest, ETH_ALEN);
        unicast_packet->ttvn = ttvn;
 
index d4fd315b5261904c1ca990578fc562b0bae41f89..358c0d686ab0aaf76c848aadcb40c5c4b340f7ad 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2012-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2012-2014 B.A.T.M.A.N. contributors:
  *
  * Martin Hundebøll, Jeppe Ledet-Pedersen
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_NETWORK_CODING_H_
@@ -64,7 +62,6 @@ static inline int batadv_nc_mesh_init(struct batadv_priv *bat_priv)
 
 static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv)
 {
-       return;
 }
 
 static inline void
@@ -74,7 +71,6 @@ batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
                         struct batadv_ogm_packet *ogm_packet,
                         int is_single_hop_neigh)
 {
-       return;
 }
 
 static inline void
@@ -83,17 +79,14 @@ batadv_nc_purge_orig(struct batadv_priv *bat_priv,
                     bool (*to_purge)(struct batadv_priv *,
                                      struct batadv_nc_node *))
 {
-       return;
 }
 
 static inline void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv)
 {
-       return;
 }
 
 static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
 {
-       return;
 }
 
 static inline bool batadv_nc_skb_forward(struct sk_buff *skb,
@@ -106,14 +99,12 @@ static inline void
 batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
                                 struct sk_buff *skb)
 {
-       return;
 }
 
 static inline void
 batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
                                    struct sk_buff *skb)
 {
-       return;
 }
 
 static inline int batadv_nc_nodes_seq_print_text(struct seq_file *seq,
index 8ab14340d10f6433c849face4852e4de1b5b9547..6df12a2e36052b7f8a07dea276565c362890863f 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -41,7 +39,7 @@ int batadv_compare_orig(const struct hlist_node *node, const void *data2)
        const void *data1 = container_of(node, struct batadv_orig_node,
                                         hash_entry);
 
-       return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+       return batadv_compare_eth(data1, data2);
 }
 
 /**
@@ -150,20 +148,114 @@ err:
        return -ENOMEM;
 }
 
+/**
+ * batadv_neigh_ifinfo_free_rcu - free the neigh_ifinfo object
+ * @rcu: rcu pointer of the neigh_ifinfo object
+ */
+static void batadv_neigh_ifinfo_free_rcu(struct rcu_head *rcu)
+{
+       struct batadv_neigh_ifinfo *neigh_ifinfo;
+
+       neigh_ifinfo = container_of(rcu, struct batadv_neigh_ifinfo, rcu);
+
+       if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
+               batadv_hardif_free_ref_now(neigh_ifinfo->if_outgoing);
+
+       kfree(neigh_ifinfo);
+}
+
+/**
+ * batadv_neigh_ifinfo_free_now - decrement the refcounter and possibly free
+ *  the neigh_ifinfo (without rcu callback)
+ * @neigh_ifinfo: the neigh_ifinfo object to release
+ */
+static void
+batadv_neigh_ifinfo_free_ref_now(struct batadv_neigh_ifinfo *neigh_ifinfo)
+{
+       if (atomic_dec_and_test(&neigh_ifinfo->refcount))
+               batadv_neigh_ifinfo_free_rcu(&neigh_ifinfo->rcu);
+}
+
+/**
+ * batadv_neigh_ifinfo_free_ref - decrement the refcounter and possibly free
+ *  the neigh_ifinfo
+ * @neigh_ifinfo: the neigh_ifinfo object to release
+ */
+void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo)
+{
+       if (atomic_dec_and_test(&neigh_ifinfo->refcount))
+               call_rcu(&neigh_ifinfo->rcu, batadv_neigh_ifinfo_free_rcu);
+}
+
+/**
+ * batadv_neigh_node_free_rcu - free the neigh_node
+ * @rcu: rcu pointer of the neigh_node
+ */
+static void batadv_neigh_node_free_rcu(struct rcu_head *rcu)
+{
+       struct hlist_node *node_tmp;
+       struct batadv_neigh_node *neigh_node;
+       struct batadv_neigh_ifinfo *neigh_ifinfo;
+
+       neigh_node = container_of(rcu, struct batadv_neigh_node, rcu);
+
+       hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
+                                 &neigh_node->ifinfo_list, list) {
+               batadv_neigh_ifinfo_free_ref_now(neigh_ifinfo);
+       }
+       batadv_hardif_free_ref_now(neigh_node->if_incoming);
+
+       kfree(neigh_node);
+}
+
+/**
+ * batadv_neigh_node_free_ref_now - decrement the neighbors refcounter
+ *  and possibly free it (without rcu callback)
+ * @neigh_node: neigh neighbor to free
+ */
+static void
+batadv_neigh_node_free_ref_now(struct batadv_neigh_node *neigh_node)
+{
+       if (atomic_dec_and_test(&neigh_node->refcount))
+               batadv_neigh_node_free_rcu(&neigh_node->rcu);
+}
+
+/**
+ * batadv_neigh_node_free_ref - decrement the neighbors refcounter
+ *  and possibly free it
+ * @neigh_node: neigh neighbor to free
+ */
 void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node)
 {
        if (atomic_dec_and_test(&neigh_node->refcount))
-               kfree_rcu(neigh_node, rcu);
+               call_rcu(&neigh_node->rcu, batadv_neigh_node_free_rcu);
 }
 
-/* increases the refcounter of a found router */
+/**
+ * batadv_orig_node_get_router - router to the originator depending on iface
+ * @orig_node: the orig node for the router
+ * @if_outgoing: the interface where the payload packet has been received or
+ *  the OGM should be sent to
+ *
+ * Returns the neighbor which should be router for this orig_node/iface.
+ *
+ * The object is returned with refcounter increased by 1.
+ */
 struct batadv_neigh_node *
-batadv_orig_node_get_router(struct batadv_orig_node *orig_node)
+batadv_orig_router_get(struct batadv_orig_node *orig_node,
+                      const struct batadv_hard_iface *if_outgoing)
 {
-       struct batadv_neigh_node *router;
+       struct batadv_orig_ifinfo *orig_ifinfo;
+       struct batadv_neigh_node *router = NULL;
 
        rcu_read_lock();
-       router = rcu_dereference(orig_node->router);
+       hlist_for_each_entry_rcu(orig_ifinfo, &orig_node->ifinfo_list, list) {
+               if (orig_ifinfo->if_outgoing != if_outgoing)
+                       continue;
+
+               router = rcu_dereference(orig_ifinfo->router);
+               break;
+       }
 
        if (router && !atomic_inc_not_zero(&router->refcount))
                router = NULL;
@@ -172,6 +264,164 @@ batadv_orig_node_get_router(struct batadv_orig_node *orig_node)
        return router;
 }
 
+/**
+ * batadv_orig_ifinfo_get - find the ifinfo from an orig_node
+ * @orig_node: the orig node to be queried
+ * @if_outgoing: the interface for which the ifinfo should be acquired
+ *
+ * Returns the requested orig_ifinfo or NULL if not found.
+ *
+ * The object is returned with refcounter increased by 1.
+ */
+struct batadv_orig_ifinfo *
+batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
+                      struct batadv_hard_iface *if_outgoing)
+{
+       struct batadv_orig_ifinfo *tmp, *orig_ifinfo = NULL;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(tmp, &orig_node->ifinfo_list,
+                                list) {
+               if (tmp->if_outgoing != if_outgoing)
+                       continue;
+
+               if (!atomic_inc_not_zero(&tmp->refcount))
+                       continue;
+
+               orig_ifinfo = tmp;
+               break;
+       }
+       rcu_read_unlock();
+
+       return orig_ifinfo;
+}
+
+/**
+ * batadv_orig_ifinfo_new - search and possibly create an orig_ifinfo object
+ * @orig_node: the orig node to be queried
+ * @if_outgoing: the interface for which the ifinfo should be acquired
+ *
+ * Returns NULL in case of failure or the orig_ifinfo object for the if_outgoing
+ * interface otherwise. The object is created and added to the list
+ * if it does not exist.
+ *
+ * The object is returned with refcounter increased by 1.
+ */
+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;
+       unsigned long reset_time;
+
+       spin_lock_bh(&orig_node->neigh_list_lock);
+
+       orig_ifinfo = batadv_orig_ifinfo_get(orig_node, if_outgoing);
+       if (orig_ifinfo)
+               goto out;
+
+       orig_ifinfo = kzalloc(sizeof(*orig_ifinfo), GFP_ATOMIC);
+       if (!orig_ifinfo)
+               goto out;
+
+       if (if_outgoing != BATADV_IF_DEFAULT &&
+           !atomic_inc_not_zero(&if_outgoing->refcount)) {
+               kfree(orig_ifinfo);
+               orig_ifinfo = NULL;
+               goto out;
+       }
+
+       reset_time = jiffies - 1;
+       reset_time -= msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
+       orig_ifinfo->batman_seqno_reset = reset_time;
+       orig_ifinfo->if_outgoing = if_outgoing;
+       INIT_HLIST_NODE(&orig_ifinfo->list);
+       atomic_set(&orig_ifinfo->refcount, 2);
+       hlist_add_head_rcu(&orig_ifinfo->list,
+                          &orig_node->ifinfo_list);
+out:
+       spin_unlock_bh(&orig_node->neigh_list_lock);
+       return orig_ifinfo;
+}
+
+/**
+ * batadv_neigh_ifinfo_get - find the ifinfo from an neigh_node
+ * @neigh_node: the neigh node to be queried
+ * @if_outgoing: the interface for which the ifinfo should be acquired
+ *
+ * The object is returned with refcounter increased by 1.
+ *
+ * Returns the requested neigh_ifinfo or NULL if not found
+ */
+struct batadv_neigh_ifinfo *
+batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
+                       struct batadv_hard_iface *if_outgoing)
+{
+       struct batadv_neigh_ifinfo *neigh_ifinfo = NULL,
+                                  *tmp_neigh_ifinfo;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(tmp_neigh_ifinfo, &neigh->ifinfo_list,
+                                list) {
+               if (tmp_neigh_ifinfo->if_outgoing != if_outgoing)
+                       continue;
+
+               if (!atomic_inc_not_zero(&tmp_neigh_ifinfo->refcount))
+                       continue;
+
+               neigh_ifinfo = tmp_neigh_ifinfo;
+               break;
+       }
+       rcu_read_unlock();
+
+       return neigh_ifinfo;
+}
+
+/**
+ * batadv_neigh_ifinfo_new - search and possibly create an neigh_ifinfo object
+ * @neigh_node: the neigh node to be queried
+ * @if_outgoing: the interface for which the ifinfo should be acquired
+ *
+ * Returns NULL in case of failure or the neigh_ifinfo object for the
+ * if_outgoing interface otherwise. The object is created and added to the list
+ * if it does not exist.
+ *
+ * The object is returned with refcounter increased by 1.
+ */
+struct batadv_neigh_ifinfo *
+batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
+                       struct batadv_hard_iface *if_outgoing)
+{
+       struct batadv_neigh_ifinfo *neigh_ifinfo;
+
+       spin_lock_bh(&neigh->ifinfo_lock);
+
+       neigh_ifinfo = batadv_neigh_ifinfo_get(neigh, if_outgoing);
+       if (neigh_ifinfo)
+               goto out;
+
+       neigh_ifinfo = kzalloc(sizeof(*neigh_ifinfo), GFP_ATOMIC);
+       if (!neigh_ifinfo)
+               goto out;
+
+       if (if_outgoing && !atomic_inc_not_zero(&if_outgoing->refcount)) {
+               kfree(neigh_ifinfo);
+               neigh_ifinfo = NULL;
+               goto out;
+       }
+
+       INIT_HLIST_NODE(&neigh_ifinfo->list);
+       atomic_set(&neigh_ifinfo->refcount, 2);
+       neigh_ifinfo->if_outgoing = if_outgoing;
+
+       hlist_add_head_rcu(&neigh_ifinfo->list, &neigh->ifinfo_list);
+
+out:
+       spin_unlock_bh(&neigh->ifinfo_lock);
+
+       return neigh_ifinfo;
+}
+
 /**
  * batadv_neigh_node_new - create and init a new neigh_node object
  * @hard_iface: the interface where the neighbour is connected to
@@ -193,13 +443,13 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
                goto out;
 
        INIT_HLIST_NODE(&neigh_node->list);
+       INIT_HLIST_HEAD(&neigh_node->ifinfo_list);
+       spin_lock_init(&neigh_node->ifinfo_lock);
 
        memcpy(neigh_node->addr, neigh_addr, ETH_ALEN);
        neigh_node->if_incoming = hard_iface;
        neigh_node->orig_node = orig_node;
 
-       INIT_LIST_HEAD(&neigh_node->bonding_list);
-
        /* extra reference for return */
        atomic_set(&neigh_node->refcount, 2);
 
@@ -207,30 +457,68 @@ out:
        return neigh_node;
 }
 
+/**
+ * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
+ * @rcu: rcu pointer of the orig_ifinfo object
+ */
+static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu)
+{
+       struct batadv_orig_ifinfo *orig_ifinfo;
+
+       orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu);
+
+       if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
+               batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing);
+
+       kfree(orig_ifinfo);
+}
+
+/**
+ * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free
+ *  the orig_ifinfo (without rcu callback)
+ * @orig_ifinfo: the orig_ifinfo object to release
+ */
+static void
+batadv_orig_ifinfo_free_ref_now(struct batadv_orig_ifinfo *orig_ifinfo)
+{
+       if (atomic_dec_and_test(&orig_ifinfo->refcount))
+               batadv_orig_ifinfo_free_rcu(&orig_ifinfo->rcu);
+}
+
+/**
+ * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free
+ *  the orig_ifinfo
+ * @orig_ifinfo: the orig_ifinfo object to release
+ */
+void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo)
+{
+       if (atomic_dec_and_test(&orig_ifinfo->refcount))
+               call_rcu(&orig_ifinfo->rcu, batadv_orig_ifinfo_free_rcu);
+}
+
 static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
 {
        struct hlist_node *node_tmp;
-       struct batadv_neigh_node *neigh_node, *tmp_neigh_node;
+       struct batadv_neigh_node *neigh_node;
        struct batadv_orig_node *orig_node;
+       struct batadv_orig_ifinfo *orig_ifinfo;
 
        orig_node = container_of(rcu, struct batadv_orig_node, rcu);
 
        spin_lock_bh(&orig_node->neigh_list_lock);
 
-       /* for all bonding members ... */
-       list_for_each_entry_safe(neigh_node, tmp_neigh_node,
-                                &orig_node->bond_list, bonding_list) {
-               list_del_rcu(&neigh_node->bonding_list);
-               batadv_neigh_node_free_ref(neigh_node);
-       }
-
        /* for all neighbors towards this originator ... */
        hlist_for_each_entry_safe(neigh_node, node_tmp,
                                  &orig_node->neigh_list, list) {
                hlist_del_rcu(&neigh_node->list);
-               batadv_neigh_node_free_ref(neigh_node);
+               batadv_neigh_node_free_ref_now(neigh_node);
        }
 
+       hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
+                                 &orig_node->ifinfo_list, list) {
+               hlist_del_rcu(&orig_ifinfo->list);
+               batadv_orig_ifinfo_free_ref_now(orig_ifinfo);
+       }
        spin_unlock_bh(&orig_node->neigh_list_lock);
 
        /* Free nc_nodes */
@@ -327,8 +615,8 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
                return NULL;
 
        INIT_HLIST_HEAD(&orig_node->neigh_list);
-       INIT_LIST_HEAD(&orig_node->bond_list);
        INIT_LIST_HEAD(&orig_node->vlan_list);
+       INIT_HLIST_HEAD(&orig_node->ifinfo_list);
        spin_lock_init(&orig_node->bcast_seqno_lock);
        spin_lock_init(&orig_node->neigh_list_lock);
        spin_lock_init(&orig_node->tt_buff_lock);
@@ -344,15 +632,11 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
        orig_node->bat_priv = bat_priv;
        memcpy(orig_node->orig, addr, ETH_ALEN);
        batadv_dat_init_orig_node_addr(orig_node);
-       orig_node->router = NULL;
        atomic_set(&orig_node->last_ttvn, 0);
        orig_node->tt_buff = NULL;
        orig_node->tt_buff_len = 0;
        reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
        orig_node->bcast_seqno_reset = reset_time;
-       orig_node->batman_seqno_reset = reset_time;
-
-       atomic_set(&orig_node->bond_candidates, 0);
 
        /* create a vlan object for the "untagged" LAN */
        vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
@@ -376,20 +660,76 @@ free_orig_node:
        return NULL;
 }
 
+/**
+ * batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: orig node which is to be checked
+ *
+ * Returns true if any ifinfo entry was purged, false otherwise.
+ */
+static bool
+batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv,
+                        struct batadv_orig_node *orig_node)
+{
+       struct batadv_orig_ifinfo *orig_ifinfo;
+       struct batadv_hard_iface *if_outgoing;
+       struct hlist_node *node_tmp;
+       bool ifinfo_purged = false;
+
+       spin_lock_bh(&orig_node->neigh_list_lock);
+
+       /* for all ifinfo objects for this originator */
+       hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
+                                 &orig_node->ifinfo_list, list) {
+               if_outgoing = orig_ifinfo->if_outgoing;
+
+               /* always keep the default interface */
+               if (if_outgoing == BATADV_IF_DEFAULT)
+                       continue;
+
+               /* don't purge if the interface is not (going) down */
+               if ((if_outgoing->if_status != BATADV_IF_INACTIVE) &&
+                   (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) &&
+                   (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED))
+                       continue;
+
+               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                          "router/ifinfo purge: originator %pM, iface: %s\n",
+                          orig_node->orig, if_outgoing->net_dev->name);
+
+               ifinfo_purged = true;
+
+               hlist_del_rcu(&orig_ifinfo->list);
+               batadv_orig_ifinfo_free_ref(orig_ifinfo);
+               if (orig_node->last_bonding_candidate == orig_ifinfo) {
+                       orig_node->last_bonding_candidate = NULL;
+                       batadv_orig_ifinfo_free_ref(orig_ifinfo);
+               }
+       }
+
+       spin_unlock_bh(&orig_node->neigh_list_lock);
+
+       return ifinfo_purged;
+}
+
+
+/**
+ * batadv_purge_orig_neighbors - purges neighbors from originator
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: orig node which is to be checked
+ *
+ * Returns true if any neighbor was purged, false otherwise
+ */
 static bool
 batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
-                           struct batadv_orig_node *orig_node,
-                           struct batadv_neigh_node **best_neigh)
+                           struct batadv_orig_node *orig_node)
 {
-       struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
        struct hlist_node *node_tmp;
        struct batadv_neigh_node *neigh_node;
        bool neigh_purged = false;
        unsigned long last_seen;
        struct batadv_hard_iface *if_incoming;
 
-       *best_neigh = NULL;
-
        spin_lock_bh(&orig_node->neigh_list_lock);
 
        /* for all neighbors towards this originator ... */
@@ -418,15 +758,7 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
                        neigh_purged = true;
 
                        hlist_del_rcu(&neigh_node->list);
-                       batadv_bonding_candidate_del(orig_node, neigh_node);
                        batadv_neigh_node_free_ref(neigh_node);
-               } else {
-                       /* store the best_neighbour if this is the first
-                        * iteration or if a better neighbor has been found
-                        */
-                       if (!*best_neigh ||
-                           bao->bat_neigh_cmp(neigh_node, *best_neigh) > 0)
-                               *best_neigh = neigh_node;
                }
        }
 
@@ -434,10 +766,57 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
        return neigh_purged;
 }
 
+/**
+ * batadv_find_best_neighbor - finds the best neighbor after purging
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: orig node which is to be checked
+ * @if_outgoing: the interface for which the metric should be compared
+ *
+ * Returns the current best neighbor, with refcount increased.
+ */
+static struct batadv_neigh_node *
+batadv_find_best_neighbor(struct batadv_priv *bat_priv,
+                         struct batadv_orig_node *orig_node,
+                         struct batadv_hard_iface *if_outgoing)
+{
+       struct batadv_neigh_node *best = NULL, *neigh;
+       struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(neigh, &orig_node->neigh_list, list) {
+               if (best && (bao->bat_neigh_cmp(neigh, if_outgoing,
+                                               best, if_outgoing) <= 0))
+                       continue;
+
+               if (!atomic_inc_not_zero(&neigh->refcount))
+                       continue;
+
+               if (best)
+                       batadv_neigh_node_free_ref(best);
+
+               best = neigh;
+       }
+       rcu_read_unlock();
+
+       return best;
+}
+
+/**
+ * batadv_purge_orig_node - purges obsolete information from an orig_node
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: orig node which is to be checked
+ *
+ * This function checks if the orig_node or substructures of it have become
+ * obsolete, and purges this information if that's the case.
+ *
+ * Returns true if the orig_node is to be removed, false otherwise.
+ */
 static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
                                   struct batadv_orig_node *orig_node)
 {
        struct batadv_neigh_node *best_neigh_node;
+       struct batadv_hard_iface *hard_iface;
+       bool changed;
 
        if (batadv_has_timed_out(orig_node->last_seen,
                                 2 * BATADV_PURGE_TIMEOUT)) {
@@ -446,12 +825,39 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
                           orig_node->orig,
                           jiffies_to_msecs(orig_node->last_seen));
                return true;
-       } else {
-               if (batadv_purge_orig_neighbors(bat_priv, orig_node,
-                                               &best_neigh_node))
-                       batadv_update_route(bat_priv, orig_node,
-                                           best_neigh_node);
        }
+       changed = batadv_purge_orig_ifinfo(bat_priv, orig_node);
+       changed = changed || batadv_purge_orig_neighbors(bat_priv, orig_node);
+
+       if (!changed)
+               return false;
+
+       /* first for NULL ... */
+       best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node,
+                                                   BATADV_IF_DEFAULT);
+       batadv_update_route(bat_priv, orig_node, BATADV_IF_DEFAULT,
+                           best_neigh_node);
+       if (best_neigh_node)
+               batadv_neigh_node_free_ref(best_neigh_node);
+
+       /* ... then for all other interfaces. */
+       rcu_read_lock();
+       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+               if (hard_iface->if_status != BATADV_IF_ACTIVE)
+                       continue;
+
+               if (hard_iface->soft_iface != bat_priv->soft_iface)
+                       continue;
+
+               best_neigh_node = batadv_find_best_neighbor(bat_priv,
+                                                           orig_node,
+                                                           hard_iface);
+               batadv_update_route(bat_priv, orig_node, hard_iface,
+                                   best_neigh_node);
+               if (best_neigh_node)
+                       batadv_neigh_node_free_ref(best_neigh_node);
+       }
+       rcu_read_unlock();
 
        return false;
 }
@@ -534,8 +940,54 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
                return 0;
        }
 
-       bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq);
+       bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq,
+                                              BATADV_IF_DEFAULT);
+
+       return 0;
+}
+
+/**
+ * batadv_orig_hardif_seq_print_text - writes originator infos for a specific
+ *  outgoing interface
+ * @seq: debugfs table seq_file struct
+ * @offset: not used
+ *
+ * Returns 0
+ */
+int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset)
+{
+       struct net_device *net_dev = (struct net_device *)seq->private;
+       struct batadv_hard_iface *hard_iface;
+       struct batadv_priv *bat_priv;
+
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);
+
+       if (!hard_iface || !hard_iface->soft_iface) {
+               seq_puts(seq, "Interface not known to B.A.T.M.A.N.\n");
+               goto out;
+       }
+
+       bat_priv = netdev_priv(hard_iface->soft_iface);
+       if (!bat_priv->bat_algo_ops->bat_orig_print) {
+               seq_puts(seq,
+                        "No printing function for this routing protocol\n");
+               goto out;
+       }
+
+       if (hard_iface->if_status != BATADV_IF_ACTIVE) {
+               seq_puts(seq, "Interface not active\n");
+               goto out;
+       }
 
+       seq_printf(seq, "[B.A.T.M.A.N. adv %s, IF/MAC: %s/%pM (%s %s)]\n",
+                  BATADV_SOURCE_VERSION, hard_iface->net_dev->name,
+                  hard_iface->net_dev->dev_addr,
+                  hard_iface->soft_iface->name, bat_priv->bat_algo_ops->name);
+
+       bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, hard_iface);
+
+out:
+       batadv_hardif_free_ref(hard_iface);
        return 0;
 }
 
index 6f77d808a91672d77a48426cd5d391abf366bfb4..37be290f63f6e603cb849e1484311389464682b3 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_ORIGINATOR_H_
@@ -36,8 +34,26 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
                      struct batadv_orig_node *orig_node);
 void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node);
 struct batadv_neigh_node *
-batadv_orig_node_get_router(struct batadv_orig_node *orig_node);
+batadv_orig_router_get(struct batadv_orig_node *orig_node,
+                      const struct batadv_hard_iface *if_outgoing);
+struct batadv_neigh_ifinfo *
+batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
+                       struct batadv_hard_iface *if_outgoing);
+struct batadv_neigh_ifinfo *
+batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
+                       struct batadv_hard_iface *if_outgoing);
+void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo);
+
+struct batadv_orig_ifinfo *
+batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
+                      struct batadv_hard_iface *if_outgoing);
+struct batadv_orig_ifinfo *
+batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
+                      struct batadv_hard_iface *if_outgoing);
+void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo);
+
 int batadv_orig_seq_print_text(struct seq_file *seq, void *offset);
+int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset);
 int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
                            int max_if_num);
 int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
index 207459b62966d0975bca70894fcf5ce266a5da29..0a381d1174c1fbb36a7c09173a004800d5d7d420 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_PACKET_H_
@@ -117,6 +115,7 @@ enum batadv_tt_client_flags {
        BATADV_TT_CLIENT_DEL     = BIT(0),
        BATADV_TT_CLIENT_ROAM    = BIT(1),
        BATADV_TT_CLIENT_WIFI    = BIT(4),
+       BATADV_TT_CLIENT_ISOLA   = BIT(5),
        BATADV_TT_CLIENT_NOPURGE = BIT(8),
        BATADV_TT_CLIENT_NEW     = BIT(9),
        BATADV_TT_CLIENT_PENDING = BIT(10),
@@ -155,6 +154,7 @@ enum batadv_tvlv_type {
        BATADV_TVLV_ROAM        = 0x05,
 };
 
+#pragma pack(2)
 /* the destination hardware field in the ARP frame is used to
  * transport the claim type and the group id
  */
@@ -163,24 +163,20 @@ struct batadv_bla_claim_dst {
        uint8_t type;           /* bla_claimframe */
        __be16 group;           /* group id */
 };
-
-struct batadv_header {
-       uint8_t  packet_type;
-       uint8_t  version;  /* batman version field */
-       uint8_t  ttl;
-       /* the parent struct has to add a byte after the header to make
-        * everything 4 bytes aligned again
-        */
-};
+#pragma pack()
 
 /**
  * struct batadv_ogm_packet - ogm (routing protocol) packet
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @flags: contains routing relevant flags - see enum batadv_iv_flags
  * @tvlv_len: length of tvlv data following the ogm header
  */
 struct batadv_ogm_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  flags;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -196,29 +192,51 @@ struct batadv_ogm_packet {
 #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
 
 /**
- * batadv_icmp_header - common ICMP header
- * @header: common batman header
+ * batadv_icmp_header - common members among all the ICMP packets
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @msg_type: ICMP packet type
  * @dst: address of the destination node
  * @orig: address of the source node
  * @uid: local ICMP socket identifier
+ * @align: not used - useful for alignment purposes only
+ *
+ * This structure is used for ICMP packets parsing only and it is never sent
+ * over the wire. The alignment field at the end is there to ensure that
+ * members are padded the same way as they are in real packets.
  */
 struct batadv_icmp_header {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  msg_type; /* see ICMP message types above */
        uint8_t  dst[ETH_ALEN];
        uint8_t  orig[ETH_ALEN];
        uint8_t  uid;
+       uint8_t  align[3];
 };
 
 /**
  * batadv_icmp_packet - ICMP packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @reserved: not used - useful for alignment
  * @seqno: ICMP sequence number
  */
 struct batadv_icmp_packet {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  reserved;
        __be16   seqno;
 };
@@ -227,13 +245,25 @@ struct batadv_icmp_packet {
 
 /**
  * batadv_icmp_packet_rr - ICMP RouteRecord packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @rr_cur: number of entries the rr array
  * @seqno: ICMP sequence number
  * @rr: route record array
  */
 struct batadv_icmp_packet_rr {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  rr_cur;
        __be16   seqno;
        uint8_t  rr[BATADV_RR_LEN][ETH_ALEN];
@@ -253,8 +283,18 @@ struct batadv_icmp_packet_rr {
  */
 #pragma pack(2)
 
+/**
+ * struct batadv_unicast_packet - unicast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @ttvn: translation table version number
+ * @dest: originator destination of the unicast packet
+ */
 struct batadv_unicast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  ttvn; /* destination translation table version number */
        uint8_t  dest[ETH_ALEN];
        /* "4 bytes boundary + 2 bytes" long to make the payload after the
@@ -280,7 +320,9 @@ struct batadv_unicast_4addr_packet {
 
 /**
  * struct batadv_frag_packet - fragmented packet
- * @header: common batman packet header with type, compatversion, and ttl
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @dest: final destination used when routing fragments
  * @orig: originator of the fragment used when merging the packet
  * @no: fragment number within this sequence
@@ -289,7 +331,9 @@ struct batadv_unicast_4addr_packet {
  * @total_size: size of the merged packet
  */
 struct batadv_frag_packet {
-       struct  batadv_header header;
+       uint8_t packet_type;
+       uint8_t version;  /* batman version field */
+       uint8_t ttl;
 #if defined(__BIG_ENDIAN_BITFIELD)
        uint8_t no:4;
        uint8_t reserved:4;
@@ -305,8 +349,19 @@ struct batadv_frag_packet {
        __be16  total_size;
 };
 
+/**
+ * struct batadv_bcast_packet - broadcast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @reserved: reserved byte for alignment
+ * @seqno: sequence identification
+ * @orig: originator of the broadcast packet
+ */
 struct batadv_bcast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -315,11 +370,11 @@ struct batadv_bcast_packet {
         */
 };
 
-#pragma pack()
-
 /**
  * struct batadv_coded_packet - network coded packet
- * @header: common batman packet header and ttl of first included packet
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: Align following fields to 2-byte boundaries
  * @first_source: original source of first included packet
  * @first_orig_dest: original destinal of first included packet
@@ -334,7 +389,9 @@ struct batadv_bcast_packet {
  * @coded_len: length of network coded part of the payload
  */
 struct batadv_coded_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  first_ttvn;
        /* uint8_t  first_dest[ETH_ALEN]; - saved in mac header destination */
        uint8_t  first_source[ETH_ALEN];
@@ -349,9 +406,13 @@ struct batadv_coded_packet {
        __be16   coded_len;
 };
 
+#pragma pack()
+
 /**
  * struct batadv_unicast_tvlv - generic unicast packet with tvlv payload
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: reserved field (for packet alignment)
  * @src: address of the source
  * @dst: address of the destination
@@ -359,7 +420,9 @@ struct batadv_coded_packet {
  * @align: 2 bytes to align the header to a 4 byte boundry
  */
 struct batadv_unicast_tvlv_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        uint8_t  dst[ETH_ALEN];
        uint8_t  src[ETH_ALEN];
@@ -420,13 +483,13 @@ struct batadv_tvlv_tt_vlan_data {
  * struct batadv_tvlv_tt_change - translation table diff data
  * @flags: status indicators concerning the non-mesh client (see
  *  batadv_tt_client_flags)
- * @reserved: reserved field
+ * @reserved: reserved field - useful for alignment purposes only
  * @addr: mac address of non-mesh client that triggered this tt change
  * @vid: VLAN identifier
  */
 struct batadv_tvlv_tt_change {
        uint8_t flags;
-       uint8_t reserved;
+       uint8_t reserved[3];
        uint8_t addr[ETH_ALEN];
        __be16 vid;
 };
index d4114d775ad61f659b59437c67aa7054d9a88f92..1ed9f7c9ecea4108f00d7beb6c2cb056f5ff87ed 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
 static int batadv_route_unicast_packet(struct sk_buff *skb,
                                       struct batadv_hard_iface *recv_if);
 
+/**
+ * _batadv_update_route - set the router for this originator
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: orig node which is to be configured
+ * @recv_if: the receive interface for which this route is set
+ * @neigh_node: neighbor which should be the next router
+ *
+ * This function does not perform any error checks
+ */
 static void _batadv_update_route(struct batadv_priv *bat_priv,
                                 struct batadv_orig_node *orig_node,
+                                struct batadv_hard_iface *recv_if,
                                 struct batadv_neigh_node *neigh_node)
 {
+       struct batadv_orig_ifinfo *orig_ifinfo;
        struct batadv_neigh_node *curr_router;
 
-       curr_router = batadv_orig_node_get_router(orig_node);
+       orig_ifinfo = batadv_orig_ifinfo_get(orig_node, recv_if);
+       if (!orig_ifinfo)
+               return;
+
+       rcu_read_lock();
+       curr_router = rcu_dereference(orig_ifinfo->router);
+       if (curr_router && !atomic_inc_not_zero(&curr_router->refcount))
+               curr_router = NULL;
+       rcu_read_unlock();
 
        /* route deleted */
        if ((curr_router) && (!neigh_node)) {
@@ -71,16 +88,25 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
                neigh_node = NULL;
 
        spin_lock_bh(&orig_node->neigh_list_lock);
-       rcu_assign_pointer(orig_node->router, neigh_node);
+       rcu_assign_pointer(orig_ifinfo->router, neigh_node);
        spin_unlock_bh(&orig_node->neigh_list_lock);
+       batadv_orig_ifinfo_free_ref(orig_ifinfo);
 
        /* decrease refcount of previous best neighbor */
        if (curr_router)
                batadv_neigh_node_free_ref(curr_router);
 }
 
+/**
+ * batadv_update_route - set the router for this originator
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: orig node which is to be configured
+ * @recv_if: the receive interface for which this route is set
+ * @neigh_node: neighbor which should be the next router
+ */
 void batadv_update_route(struct batadv_priv *bat_priv,
                         struct batadv_orig_node *orig_node,
+                        struct batadv_hard_iface *recv_if,
                         struct batadv_neigh_node *neigh_node)
 {
        struct batadv_neigh_node *router = NULL;
@@ -88,125 +114,16 @@ void batadv_update_route(struct batadv_priv *bat_priv,
        if (!orig_node)
                goto out;
 
-       router = batadv_orig_node_get_router(orig_node);
+       router = batadv_orig_router_get(orig_node, recv_if);
 
        if (router != neigh_node)
-               _batadv_update_route(bat_priv, orig_node, neigh_node);
+               _batadv_update_route(bat_priv, orig_node, recv_if, neigh_node);
 
 out:
        if (router)
                batadv_neigh_node_free_ref(router);
 }
 
-/* caller must hold the neigh_list_lock */
-void batadv_bonding_candidate_del(struct batadv_orig_node *orig_node,
-                                 struct batadv_neigh_node *neigh_node)
-{
-       /* this neighbor is not part of our candidate list */
-       if (list_empty(&neigh_node->bonding_list))
-               goto out;
-
-       list_del_rcu(&neigh_node->bonding_list);
-       INIT_LIST_HEAD(&neigh_node->bonding_list);
-       batadv_neigh_node_free_ref(neigh_node);
-       atomic_dec(&orig_node->bond_candidates);
-
-out:
-       return;
-}
-
-/**
- * batadv_bonding_candidate_add - consider a new link for bonding mode towards
- *  the given originator
- * @bat_priv: the bat priv with all the soft interface information
- * @orig_node: the target node
- * @neigh_node: the neighbor representing the new link to consider for bonding
- *  mode
- */
-void batadv_bonding_candidate_add(struct batadv_priv *bat_priv,
-                                 struct batadv_orig_node *orig_node,
-                                 struct batadv_neigh_node *neigh_node)
-{
-       struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
-       struct batadv_neigh_node *tmp_neigh_node, *router = NULL;
-       uint8_t interference_candidate = 0;
-
-       spin_lock_bh(&orig_node->neigh_list_lock);
-
-       /* only consider if it has the same primary address ...  */
-       if (!batadv_compare_eth(orig_node->orig,
-                               neigh_node->orig_node->primary_addr))
-               goto candidate_del;
-
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
-               goto candidate_del;
-
-
-       /* ... and is good enough to be considered */
-       if (bao->bat_neigh_is_equiv_or_better(neigh_node, router))
-               goto candidate_del;
-
-       /* check if we have another candidate with the same mac address or
-        * interface. If we do, we won't select this candidate because of
-        * possible interference.
-        */
-       hlist_for_each_entry_rcu(tmp_neigh_node,
-                                &orig_node->neigh_list, list) {
-               if (tmp_neigh_node == neigh_node)
-                       continue;
-
-               /* we only care if the other candidate is even
-                * considered as candidate.
-                */
-               if (list_empty(&tmp_neigh_node->bonding_list))
-                       continue;
-
-               if ((neigh_node->if_incoming == tmp_neigh_node->if_incoming) ||
-                   (batadv_compare_eth(neigh_node->addr,
-                                       tmp_neigh_node->addr))) {
-                       interference_candidate = 1;
-                       break;
-               }
-       }
-
-       /* don't care further if it is an interference candidate */
-       if (interference_candidate)
-               goto candidate_del;
-
-       /* this neighbor already is part of our candidate list */
-       if (!list_empty(&neigh_node->bonding_list))
-               goto out;
-
-       if (!atomic_inc_not_zero(&neigh_node->refcount))
-               goto out;
-
-       list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list);
-       atomic_inc(&orig_node->bond_candidates);
-       goto out;
-
-candidate_del:
-       batadv_bonding_candidate_del(orig_node, neigh_node);
-
-out:
-       spin_unlock_bh(&orig_node->neigh_list_lock);
-
-       if (router)
-               batadv_neigh_node_free_ref(router);
-}
-
-/* copy primary address for bonding */
-void
-batadv_bonding_save_primary(const struct batadv_orig_node *orig_node,
-                           struct batadv_orig_node *orig_neigh_node,
-                           const struct batadv_ogm_packet *batman_ogm_packet)
-{
-       if (!(batman_ogm_packet->flags & BATADV_PRIMARIES_FIRST_HOP))
-               return;
-
-       memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN);
-}
-
 /* checks whether the host restarted and is in the protection time.
  * returns:
  *  0 if the packet is to be accepted
@@ -308,7 +225,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
                memcpy(icmph->dst, icmph->orig, ETH_ALEN);
                memcpy(icmph->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
                icmph->msg_type = BATADV_ECHO_REPLY;
-               icmph->header.ttl = BATADV_TTL;
+               icmph->ttl = BATADV_TTL;
 
                res = batadv_send_skb_to_orig(skb, orig_node, NULL);
                if (res != NET_XMIT_DROP)
@@ -338,9 +255,9 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
        /* send TTL exceeded if packet is an echo request (traceroute) */
-       if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
+       if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) {
                pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
-                        icmp_packet->icmph.orig, icmp_packet->icmph.dst);
+                        icmp_packet->orig, icmp_packet->dst);
                goto out;
        }
 
@@ -349,7 +266,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
                goto out;
 
        /* get routing information */
-       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
+       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig);
        if (!orig_node)
                goto out;
 
@@ -359,11 +276,11 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
-       memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
-       memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
+       memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+       memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr,
               ETH_ALEN);
-       icmp_packet->icmph.msg_type = BATADV_TTL_EXCEEDED;
-       icmp_packet->icmph.header.ttl = BATADV_TTL;
+       icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
+       icmp_packet->ttl = BATADV_TTL;
 
        if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = NET_RX_SUCCESS;
@@ -434,7 +351,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
                return batadv_recv_my_icmp_packet(bat_priv, skb);
 
        /* TTL exceeded */
-       if (icmph->header.ttl < 2)
+       if (icmph->ttl < 2)
                return batadv_recv_icmp_ttl_exceeded(bat_priv, skb);
 
        /* get routing information */
@@ -449,7 +366,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        icmph = (struct batadv_icmp_header *)skb->data;
 
        /* decrement ttl */
-       icmph->header.ttl--;
+       icmph->ttl--;
 
        /* route it */
        if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
@@ -461,114 +378,6 @@ out:
        return ret;
 }
 
-/* In the bonding case, send the packets in a round
- * robin fashion over the remaining interfaces.
- *
- * This method rotates the bonding list and increases the
- * returned router's refcount.
- */
-static struct batadv_neigh_node *
-batadv_find_bond_router(struct batadv_orig_node *primary_orig,
-                       const struct batadv_hard_iface *recv_if)
-{
-       struct batadv_neigh_node *tmp_neigh_node;
-       struct batadv_neigh_node *router = NULL, *first_candidate = NULL;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list,
-                               bonding_list) {
-               if (!first_candidate)
-                       first_candidate = tmp_neigh_node;
-
-               /* recv_if == NULL on the first node. */
-               if (tmp_neigh_node->if_incoming == recv_if)
-                       continue;
-
-               if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
-                       continue;
-
-               router = tmp_neigh_node;
-               break;
-       }
-
-       /* use the first candidate if nothing was found. */
-       if (!router && first_candidate &&
-           atomic_inc_not_zero(&first_candidate->refcount))
-               router = first_candidate;
-
-       if (!router)
-               goto out;
-
-       /* selected should point to the next element
-        * after the current router
-        */
-       spin_lock_bh(&primary_orig->neigh_list_lock);
-       /* this is a list_move(), which unfortunately
-        * does not exist as rcu version
-        */
-       list_del_rcu(&primary_orig->bond_list);
-       list_add_rcu(&primary_orig->bond_list,
-                    &router->bonding_list);
-       spin_unlock_bh(&primary_orig->neigh_list_lock);
-
-out:
-       rcu_read_unlock();
-       return router;
-}
-
-/**
- * batadv_find_ifalter_router - find the best of the remaining candidates which
- *  are not using this interface
- * @bat_priv: the bat priv with all the soft interface information
- * @primary_orig: the destination
- * @recv_if: the interface that the router returned by this function has to not
- *  use
- *
- * Returns the best candidate towards primary_orig that is not using recv_if.
- * Increases the returned neighbor's refcount
- */
-static struct batadv_neigh_node *
-batadv_find_ifalter_router(struct batadv_priv *bat_priv,
-                          struct batadv_orig_node *primary_orig,
-                          const struct batadv_hard_iface *recv_if)
-{
-       struct batadv_neigh_node *router = NULL, *first_candidate = NULL;
-       struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
-       struct batadv_neigh_node *tmp_neigh_node;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list,
-                               bonding_list) {
-               if (!first_candidate)
-                       first_candidate = tmp_neigh_node;
-
-               /* recv_if == NULL on the first node. */
-               if (tmp_neigh_node->if_incoming == recv_if)
-                       continue;
-
-               if (router && bao->bat_neigh_cmp(tmp_neigh_node, router))
-                       continue;
-
-               if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
-                       continue;
-
-               /* decrement refcount of previously selected router */
-               if (router)
-                       batadv_neigh_node_free_ref(router);
-
-               /* we found a better router (or at least one valid router) */
-               router = tmp_neigh_node;
-       }
-
-       /* use the first candidate if nothing was found. */
-       if (!router && first_candidate &&
-           atomic_inc_not_zero(&first_candidate->refcount))
-               router = first_candidate;
-
-       rcu_read_unlock();
-       return router;
-}
-
 /**
  * batadv_check_unicast_packet - Check for malformed unicast packets
  * @bat_priv: the bat priv with all the soft interface information
@@ -606,95 +415,141 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
        return 0;
 }
 
-/* find a suitable router for this originator, and use
- * bonding if possible. increases the found neighbors
- * refcount.
+/**
+ * batadv_find_router - find a suitable router for this originator
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: the destination node
+ * @recv_if: pointer to interface this packet was received on
+ *
+ * Returns the router which should be used for this orig_node on
+ * this interface, or NULL if not available.
  */
 struct batadv_neigh_node *
 batadv_find_router(struct batadv_priv *bat_priv,
                   struct batadv_orig_node *orig_node,
-                  const struct batadv_hard_iface *recv_if)
+                  struct batadv_hard_iface *recv_if)
 {
-       struct batadv_orig_node *primary_orig_node;
-       struct batadv_orig_node *router_orig;
-       struct batadv_neigh_node *router;
-       static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
-       int bonding_enabled;
-       uint8_t *primary_addr;
+       struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
+       struct batadv_neigh_node *first_candidate_router = NULL;
+       struct batadv_neigh_node *next_candidate_router = NULL;
+       struct batadv_neigh_node *router, *cand_router = NULL;
+       struct batadv_neigh_node *last_cand_router = NULL;
+       struct batadv_orig_ifinfo *cand, *first_candidate = NULL;
+       struct batadv_orig_ifinfo *next_candidate = NULL;
+       struct batadv_orig_ifinfo *last_candidate;
+       bool last_candidate_found = false;
 
        if (!orig_node)
                return NULL;
 
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
-               goto err;
+       router = batadv_orig_router_get(orig_node, recv_if);
 
-       /* without bonding, the first node should
-        * always choose the default router.
+       /* only consider bonding for recv_if == BATADV_IF_DEFAULT (first hop)
+        * and if activated.
+        */
+       if (recv_if == BATADV_IF_DEFAULT || !atomic_read(&bat_priv->bonding) ||
+           !router)
+               return router;
+
+       /* bonding: loop through the list of possible routers found
+        * for the various outgoing interfaces and find a candidate after
+        * the last chosen bonding candidate (next_candidate). If no such
+        * router is found, use the first candidate found (the previously
+        * chosen bonding candidate might have been the last one in the list).
+        * If this can't be found either, return the previously choosen
+        * router - obviously there are no other candidates.
         */
-       bonding_enabled = atomic_read(&bat_priv->bonding);
-
        rcu_read_lock();
-       /* select default router to output */
-       router_orig = router->orig_node;
-       if (!router_orig)
-               goto err_unlock;
+       last_candidate = orig_node->last_bonding_candidate;
+       if (last_candidate)
+               last_cand_router = rcu_dereference(last_candidate->router);
 
-       if ((!recv_if) && (!bonding_enabled))
-               goto return_router;
+       hlist_for_each_entry_rcu(cand, &orig_node->ifinfo_list, list) {
+               /* acquire some structures and references ... */
+               if (!atomic_inc_not_zero(&cand->refcount))
+                       continue;
 
-       primary_addr = router_orig->primary_addr;
+               cand_router = rcu_dereference(cand->router);
+               if (!cand_router)
+                       goto next;
 
-       /* if we have something in the primary_addr, we can search
-        * for a potential bonding candidate.
-        */
-       if (batadv_compare_eth(primary_addr, zero_mac))
-               goto return_router;
+               if (!atomic_inc_not_zero(&cand_router->refcount)) {
+                       cand_router = NULL;
+                       goto next;
+               }
 
-       /* find the orig_node which has the primary interface. might
-        * even be the same as our router_orig in many cases
-        */
-       if (batadv_compare_eth(primary_addr, router_orig->orig)) {
-               primary_orig_node = router_orig;
-       } else {
-               primary_orig_node = batadv_orig_hash_find(bat_priv,
-                                                         primary_addr);
-               if (!primary_orig_node)
-                       goto return_router;
+               /* alternative candidate should be good enough to be
+                * considered
+                */
+               if (!bao->bat_neigh_is_equiv_or_better(cand_router,
+                                                      cand->if_outgoing,
+                                                      router, recv_if))
+                       goto next;
+
+               /* don't use the same router twice */
+               if (last_cand_router == cand_router)
+                       goto next;
+
+               /* mark the first possible candidate */
+               if (!first_candidate) {
+                       atomic_inc(&cand_router->refcount);
+                       atomic_inc(&cand->refcount);
+                       first_candidate = cand;
+                       first_candidate_router = cand_router;
+               }
+
+               /* check if the loop has already passed the previously selected
+                * candidate ... this function should select the next candidate
+                * AFTER the previously used bonding candidate.
+                */
+               if (!last_candidate || last_candidate_found) {
+                       next_candidate = cand;
+                       next_candidate_router = cand_router;
+                       break;
+               }
 
-               batadv_orig_node_free_ref(primary_orig_node);
+               if (last_candidate == cand)
+                       last_candidate_found = true;
+next:
+               /* free references */
+               if (cand_router) {
+                       batadv_neigh_node_free_ref(cand_router);
+                       cand_router = NULL;
+               }
+               batadv_orig_ifinfo_free_ref(cand);
        }
+       rcu_read_unlock();
 
-       /* with less than 2 candidates, we can't do any
-        * bonding and prefer the original router.
-        */
-       if (atomic_read(&primary_orig_node->bond_candidates) < 2)
-               goto return_router;
+       /* last_bonding_candidate is reset below, remove the old reference. */
+       if (orig_node->last_bonding_candidate)
+               batadv_orig_ifinfo_free_ref(orig_node->last_bonding_candidate);
 
-       /* all nodes between should choose a candidate which
-        * is is not on the interface where the packet came
-        * in.
+       /* After finding candidates, handle the three cases:
+        * 1) there is a next candidate, use that
+        * 2) there is no next candidate, use the first of the list
+        * 3) there is no candidate at all, return the default router
         */
-       batadv_neigh_node_free_ref(router);
+       if (next_candidate) {
+               batadv_neigh_node_free_ref(router);
 
-       if (bonding_enabled)
-               router = batadv_find_bond_router(primary_orig_node, recv_if);
-       else
-               router = batadv_find_ifalter_router(bat_priv, primary_orig_node,
-                                                   recv_if);
+               /* remove references to first candidate, we don't need it. */
+               if (first_candidate) {
+                       batadv_neigh_node_free_ref(first_candidate_router);
+                       batadv_orig_ifinfo_free_ref(first_candidate);
+               }
+               router = next_candidate_router;
+               orig_node->last_bonding_candidate = next_candidate;
+       } else if (first_candidate) {
+               batadv_neigh_node_free_ref(router);
 
-return_router:
-       if (router && router->if_incoming->if_status != BATADV_IF_ACTIVE)
-               goto err_unlock;
+               /* refcounting has already been done in the loop above. */
+               router = first_candidate_router;
+               orig_node->last_bonding_candidate = first_candidate;
+       } else {
+               orig_node->last_bonding_candidate = NULL;
+       }
 
-       rcu_read_unlock();
        return router;
-err_unlock:
-       rcu_read_unlock();
-err:
-       if (router)
-               batadv_neigh_node_free_ref(router);
-       return NULL;
 }
 
 static int batadv_route_unicast_packet(struct sk_buff *skb,
@@ -709,7 +564,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
        /* TTL exceeded */
-       if (unicast_packet->header.ttl < 2) {
+       if (unicast_packet->ttl < 2) {
                pr_debug("Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n",
                         ethhdr->h_source, unicast_packet->dest);
                goto out;
@@ -727,9 +582,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
 
        /* decrement ttl */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.ttl--;
+       unicast_packet->ttl--;
 
-       switch (unicast_packet->header.packet_type) {
+       switch (unicast_packet->packet_type) {
        case BATADV_UNICAST_4ADDR:
                hdr_len = sizeof(struct batadv_unicast_4addr_packet);
                break;
@@ -970,7 +825,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR;
+       is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR;
        /* the caller function should have already pulled 2 bytes */
        if (is4addr)
                hdr_size = sizeof(*unicast_4addr_packet);
@@ -1135,6 +990,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
        int hdr_size = sizeof(*bcast_packet);
        int ret = NET_RX_DROP;
        int32_t seq_diff;
+       uint32_t seqno;
 
        /* drop packet if it has not necessary minimum size */
        if (unlikely(!pskb_may_pull(skb, hdr_size)))
@@ -1160,7 +1016,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
        if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
                goto out;
 
-       if (bcast_packet->header.ttl < 2)
+       if (bcast_packet->ttl < 2)
                goto out;
 
        orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig);
@@ -1170,12 +1026,13 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
 
        spin_lock_bh(&orig_node->bcast_seqno_lock);
 
+       seqno = ntohl(bcast_packet->seqno);
        /* check whether the packet is a duplicate */
        if (batadv_test_bit(orig_node->bcast_bits, orig_node->last_bcast_seqno,
-                           ntohl(bcast_packet->seqno)))
+                           seqno))
                goto spin_unlock;
 
-       seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
+       seq_diff = seqno - orig_node->last_bcast_seqno;
 
        /* check whether the packet is old and the host just restarted. */
        if (batadv_window_protected(bat_priv, seq_diff,
@@ -1186,7 +1043,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
         * if required.
         */
        if (batadv_bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1))
-               orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
+               orig_node->last_bcast_seqno = seqno;
 
        spin_unlock_bh(&orig_node->bcast_seqno_lock);
 
index 19544ddb81b5abf417b69484c096aff239989a10..557d3d12a9ab0c8edf583d8e28fa22dbfd8ad6fe 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_ROUTING_H_
@@ -25,6 +23,7 @@ bool batadv_check_management_packet(struct sk_buff *skb,
                                    int header_len);
 void batadv_update_route(struct batadv_priv *bat_priv,
                         struct batadv_orig_node *orig_node,
+                        struct batadv_hard_iface *recv_if,
                         struct batadv_neigh_node *neigh_node);
 int batadv_recv_icmp_packet(struct sk_buff *skb,
                            struct batadv_hard_iface *recv_if);
@@ -45,16 +44,7 @@ int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
 struct batadv_neigh_node *
 batadv_find_router(struct batadv_priv *bat_priv,
                   struct batadv_orig_node *orig_node,
-                  const struct batadv_hard_iface *recv_if);
-void batadv_bonding_candidate_del(struct batadv_orig_node *orig_node,
-                                 struct batadv_neigh_node *neigh_node);
-void batadv_bonding_candidate_add(struct batadv_priv *bat_priv,
-                                 struct batadv_orig_node *orig_node,
-                                 struct batadv_neigh_node *neigh_node);
-void batadv_bonding_save_primary(const struct batadv_orig_node *orig_node,
-                                struct batadv_orig_node *orig_neigh_node,
-                                const struct batadv_ogm_packet
-                                *batman_ogm_packet);
+                  struct batadv_hard_iface *recv_if);
 int batadv_window_protected(struct batadv_priv *bat_priv, int32_t seq_num_diff,
                            unsigned long *last_reset);
 
index c83be5ebaa285dffe64d051850e87f2fca02624b..579f5f00a385689f29a60ac111adf8b8682e1aa6 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -161,11 +159,11 @@ batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size,
                return false;
 
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
        /* batman packet type: unicast */
-       unicast_packet->header.packet_type = BATADV_UNICAST;
+       unicast_packet->packet_type = BATADV_UNICAST;
        /* set unicast ttl */
-       unicast_packet->header.ttl = BATADV_TTL;
+       unicast_packet->ttl = BATADV_TTL;
        /* copy the destination for faster routing */
        memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
        /* set the destination tt version number */
@@ -221,7 +219,7 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
                goto out;
 
        uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
-       uc_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
+       uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR;
        memcpy(uc_4addr_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
        uc_4addr_packet->subtype = packet_subtype;
        uc_4addr_packet->reserved = 0;
@@ -321,13 +319,23 @@ out:
  */
 int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv,
                                   struct sk_buff *skb, int packet_type,
-                                  int packet_subtype, unsigned short vid)
+                                  int packet_subtype, uint8_t *dst_hint,
+                                  unsigned short vid)
 {
        struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
        struct batadv_orig_node *orig_node;
+       uint8_t *src, *dst;
+
+       src = ethhdr->h_source;
+       dst = ethhdr->h_dest;
+
+       /* if we got an hint! let's send the packet to this client (if any) */
+       if (dst_hint) {
+               src = NULL;
+               dst = dst_hint;
+       }
+       orig_node = batadv_transtable_search(bat_priv, src, dst, vid);
 
-       orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
-                                            ethhdr->h_dest, vid);
        return batadv_send_skb_unicast(bat_priv, skb, packet_type,
                                       packet_subtype, orig_node, vid);
 }
@@ -379,6 +387,8 @@ static void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet)
                kfree_skb(forw_packet->skb);
        if (forw_packet->if_incoming)
                batadv_hardif_free_ref(forw_packet->if_incoming);
+       if (forw_packet->if_outgoing)
+               batadv_hardif_free_ref(forw_packet->if_outgoing);
        kfree(forw_packet);
 }
 
@@ -436,12 +446,13 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
 
        /* as we have a copy now, it is safe to decrease the TTL */
        bcast_packet = (struct batadv_bcast_packet *)newskb->data;
-       bcast_packet->header.ttl--;
+       bcast_packet->ttl--;
 
        skb_reset_mac_header(newskb);
 
        forw_packet->skb = newskb;
        forw_packet->if_incoming = primary_if;
+       forw_packet->if_outgoing = NULL;
 
        /* how often did we send the bcast packet ? */
        forw_packet->num_packets = 0;
@@ -537,11 +548,16 @@ void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work)
 
        bat_priv->bat_algo_ops->bat_ogm_emit(forw_packet);
 
-       /* we have to have at least one packet in the queue
-        * to determine the queues wake up time unless we are
-        * shutting down
+       /* we have to have at least one packet in the queue to determine the
+        * queues wake up time unless we are shutting down.
+        *
+        * only re-schedule if this is the "original" copy, e.g. the OGM of the
+        * primary interface should only be rescheduled once per period, but
+        * this function will be called for the forw_packet instances of the
+        * other secondary interfaces as well.
         */
-       if (forw_packet->own)
+       if (forw_packet->own &&
+           forw_packet->if_incoming == forw_packet->if_outgoing)
                batadv_schedule_bat_ogm(forw_packet->if_incoming);
 
 out:
@@ -602,7 +618,8 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
                 * we delete only packets belonging to the given interface
                 */
                if ((hard_iface) &&
-                   (forw_packet->if_incoming != hard_iface))
+                   (forw_packet->if_incoming != hard_iface) &&
+                   (forw_packet->if_outgoing != hard_iface))
                        continue;
 
                spin_unlock_bh(&bat_priv->forw_bat_list_lock);
index aa2e2537a739297f76afa54b30d87d69976d35d2..aaddaa9661ce49752f11af09700e6f0ab7d9b387 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_SEND_H_
@@ -40,7 +38,8 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
                                           int packet_subtype);
 int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv,
                                   struct sk_buff *skb, int packet_type,
-                                  int packet_subtype, unsigned short vid);
+                                  int packet_subtype, uint8_t *dst_hint,
+                                  unsigned short vid);
 int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb,
                           unsigned short vid);
 
@@ -57,11 +56,11 @@ int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb,
  * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
  */
 static inline int batadv_send_skb_via_tt(struct batadv_priv *bat_priv,
-                                        struct sk_buff *skb,
+                                        struct sk_buff *skb, uint8_t *dst_hint,
                                         unsigned short vid)
 {
        return batadv_send_skb_via_tt_generic(bat_priv, skb, BATADV_UNICAST, 0,
-                                             vid);
+                                             dst_hint, vid);
 }
 
 /**
@@ -81,11 +80,12 @@ static inline int batadv_send_skb_via_tt(struct batadv_priv *bat_priv,
 static inline int batadv_send_skb_via_tt_4addr(struct batadv_priv *bat_priv,
                                               struct sk_buff *skb,
                                               int packet_subtype,
+                                              uint8_t *dst_hint,
                                               unsigned short vid)
 {
        return batadv_send_skb_via_tt_generic(bat_priv, skb,
                                              BATADV_UNICAST_4ADDR,
-                                             packet_subtype, vid);
+                                             packet_subtype, dst_hint, vid);
 }
 
 #endif /* _NET_BATMAN_ADV_SEND_H_ */
index 36f050876f8260245a008de079cf0974fa97b76e..f82c267e1886ee04cb50339d91e20fa559161737 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -121,7 +119,7 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
                batadv_tt_local_remove(bat_priv, old_addr, BATADV_NO_FLAGS,
                                       "mac address changed", false);
                batadv_tt_local_add(dev, addr->sa_data, BATADV_NO_FLAGS,
-                                   BATADV_NULL_IFINDEX);
+                                   BATADV_NULL_IFINDEX, BATADV_NO_MARK);
        }
 
        return 0;
@@ -162,6 +160,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
                                                   0x00, 0x00};
        static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
                                                    0x00, 0x00};
+       enum batadv_dhcp_recipient dhcp_rcp = BATADV_DHCP_NO;
+       uint8_t *dst_hint = NULL, chaddr[ETH_ALEN];
        struct vlan_ethhdr *vhdr;
        unsigned int header_len = 0;
        int data_len = skb->len, ret;
@@ -169,6 +169,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
        bool do_bcast = false, client_added;
        unsigned short vid;
        uint32_t seqno;
+       int gw_mode;
 
        if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
                goto dropped;
@@ -198,7 +199,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
        /* Register the client MAC in the transtable */
        if (!is_multicast_ether_addr(ethhdr->h_source)) {
                client_added = batadv_tt_local_add(soft_iface, ethhdr->h_source,
-                                                  vid, skb->skb_iif);
+                                                  vid, skb->skb_iif,
+                                                  skb->mark);
                if (!client_added)
                        goto dropped;
        }
@@ -215,36 +217,39 @@ static int batadv_interface_tx(struct sk_buff *skb,
        if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
                goto dropped;
 
+       gw_mode = atomic_read(&bat_priv->gw_mode);
        if (is_multicast_ether_addr(ethhdr->h_dest)) {
-               do_bcast = true;
-
-               switch (atomic_read(&bat_priv->gw_mode)) {
-               case BATADV_GW_MODE_SERVER:
-                       /* gateway servers should not send dhcp
-                        * requests into the mesh
-                        */
-                       ret = batadv_gw_is_dhcp_target(skb, &header_len);
-                       if (ret)
-                               goto dropped;
-                       break;
-               case BATADV_GW_MODE_CLIENT:
-                       /* gateway clients should send dhcp requests
-                        * via unicast to their gateway
-                        */
-                       ret = batadv_gw_is_dhcp_target(skb, &header_len);
-                       if (ret)
-                               do_bcast = false;
-                       break;
-               case BATADV_GW_MODE_OFF:
-               default:
-                       break;
+               /* if gw mode is off, broadcast every packet */
+               if (gw_mode == BATADV_GW_MODE_OFF) {
+                       do_bcast = true;
+                       goto send;
                }
 
-               /* reminder: ethhdr might have become unusable from here on
-                * (batadv_gw_is_dhcp_target() might have reallocated skb data)
+               dhcp_rcp = batadv_gw_dhcp_recipient_get(skb, &header_len,
+                                                       chaddr);
+               /* skb->data may have been modified by
+                * batadv_gw_dhcp_recipient_get()
+                */
+               ethhdr = (struct ethhdr *)skb->data;
+               /* if gw_mode is on, broadcast any non-DHCP message.
+                * All the DHCP packets are going to be sent as unicast
                 */
+               if (dhcp_rcp == BATADV_DHCP_NO) {
+                       do_bcast = true;
+                       goto send;
+               }
+
+               if (dhcp_rcp == BATADV_DHCP_TO_CLIENT)
+                       dst_hint = chaddr;
+               else if ((gw_mode == BATADV_GW_MODE_SERVER) &&
+                        (dhcp_rcp == BATADV_DHCP_TO_SERVER))
+                       /* gateways should not forward any DHCP message if
+                        * directed to a DHCP server
+                        */
+                       goto dropped;
        }
 
+send:
        batadv_skb_set_priority(skb, 0);
 
        /* ethernet packet should be broadcasted */
@@ -264,11 +269,11 @@ static int batadv_interface_tx(struct sk_buff *skb,
                        goto dropped;
 
                bcast_packet = (struct batadv_bcast_packet *)skb->data;
-               bcast_packet->header.version = BATADV_COMPAT_VERSION;
-               bcast_packet->header.ttl = BATADV_TTL;
+               bcast_packet->version = BATADV_COMPAT_VERSION;
+               bcast_packet->ttl = BATADV_TTL;
 
                /* batman packet type: broadcast */
-               bcast_packet->header.packet_type = BATADV_BCAST;
+               bcast_packet->packet_type = BATADV_BCAST;
                bcast_packet->reserved = 0;
 
                /* hw address of first interface is the orig mac because only
@@ -290,22 +295,22 @@ static int batadv_interface_tx(struct sk_buff *skb,
 
        /* unicast packet */
        } else {
-               if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) {
+               /* DHCP packets going to a server will use the GW feature */
+               if (dhcp_rcp == BATADV_DHCP_TO_SERVER) {
                        ret = batadv_gw_out_of_range(bat_priv, skb);
                        if (ret)
                                goto dropped;
-               }
-
-               if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
-                       goto dropped;
-
-               batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
-
-               if (is_multicast_ether_addr(ethhdr->h_dest))
                        ret = batadv_send_skb_via_gw(bat_priv, skb, vid);
-               else
-                       ret = batadv_send_skb_via_tt(bat_priv, skb, vid);
+               } else {
+                       if (batadv_dat_snoop_outgoing_arp_request(bat_priv,
+                                                                 skb))
+                               goto dropped;
+
+                       batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
 
+                       ret = batadv_send_skb_via_tt(bat_priv, skb, dst_hint,
+                                                    vid);
+               }
                if (ret == NET_XMIT_DROP)
                        goto dropped_freed;
        }
@@ -328,7 +333,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
                         struct sk_buff *skb, struct batadv_hard_iface *recv_if,
                         int hdr_size, struct batadv_orig_node *orig_node)
 {
-       struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
+       struct batadv_bcast_packet *batadv_bcast_packet;
        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
        __be16 ethertype = htons(ETH_P_BATMAN);
        struct vlan_ethhdr *vhdr;
@@ -336,7 +341,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
        unsigned short vid;
        bool is_bcast;
 
-       is_bcast = (batadv_header->packet_type == BATADV_BCAST);
+       batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data;
+       is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST);
 
        /* check if enough space is available for pulling, and pull */
        if (!pskb_may_pull(skb, hdr_size))
@@ -345,7 +351,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
        skb_pull_rcsum(skb, hdr_size);
        skb_reset_mac_header(skb);
 
-       vid = batadv_get_vid(skb, hdr_size);
+       /* clean the netfilter state now that the batman-adv header has been
+        * removed
+        */
+       nf_reset(skb);
+
+       vid = batadv_get_vid(skb, 0);
        ethhdr = eth_hdr(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
@@ -388,9 +399,23 @@ void batadv_interface_rx(struct net_device *soft_iface,
                batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
                                                     ethhdr->h_source, vid);
 
-       if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest,
-                                 vid))
+       if (is_multicast_ether_addr(ethhdr->h_dest)) {
+               /* set the mark on broadcast packets if AP isolation is ON and
+                * the packet is coming from an "isolated" client
+                */
+               if (batadv_vlan_ap_isola_get(bat_priv, vid) &&
+                   batadv_tt_global_is_isolated(bat_priv, ethhdr->h_source,
+                                                vid)) {
+                       /* save bits in skb->mark not covered by the mask and
+                        * apply the mark on the rest
+                        */
+                       skb->mark &= ~bat_priv->isolation_mark_mask;
+                       skb->mark |= bat_priv->isolation_mark;
+               }
+       } else if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source,
+                                        ethhdr->h_dest, vid)) {
                goto dropped;
+       }
 
        netif_rx(skb);
        goto out;
@@ -479,7 +504,7 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
         */
        batadv_tt_local_add(bat_priv->soft_iface,
                            bat_priv->soft_iface->dev_addr, vid,
-                           BATADV_NULL_IFINDEX);
+                           BATADV_NULL_IFINDEX, BATADV_NO_MARK);
 
        spin_lock_bh(&bat_priv->softif_vlan_list_lock);
        hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list);
@@ -672,7 +697,7 @@ static int batadv_softif_init_late(struct net_device *dev)
        atomic_set(&bat_priv->gw.bandwidth_down, 100);
        atomic_set(&bat_priv->gw.bandwidth_up, 20);
        atomic_set(&bat_priv->orig_interval, 1000);
-       atomic_set(&bat_priv->hop_penalty, 30);
+       atomic_set(&bat_priv->hop_penalty, 15);
 #ifdef CONFIG_BATMAN_ADV_DEBUG
        atomic_set(&bat_priv->log_level, 0);
 #endif
@@ -691,6 +716,8 @@ static int batadv_softif_init_late(struct net_device *dev)
 #endif
        bat_priv->tt.last_changeset = NULL;
        bat_priv->tt.last_changeset_len = 0;
+       bat_priv->isolation_mark = 0;
+       bat_priv->isolation_mark_mask = 0;
 
        /* randomize initial seqno to avoid collision */
        get_random_bytes(&random_seqno, sizeof(random_seqno));
index 06fc91ff5a021bf584db73e75624e7d13d2560f7..dbab22fd89a51aa4e228d0df062a2b2094df9afd 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_SOFT_INTERFACE_H_
index 6335433310aff37a0438bc61367ce142d96cb07f..e456bf6bb2844e61560fa961a6984d5ef83a8817 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2010-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -329,10 +327,10 @@ static ssize_t batadv_show_bat_algo(struct kobject *kobj,
        return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name);
 }
 
-static void batadv_post_gw_deselect(struct net_device *net_dev)
+static void batadv_post_gw_reselect(struct net_device *net_dev)
 {
        struct batadv_priv *bat_priv = netdev_priv(net_dev);
-       batadv_gw_deselect(bat_priv);
+       batadv_gw_reselect(bat_priv);
 }
 
 static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr,
@@ -408,7 +406,16 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj,
        batadv_info(net_dev, "Changing gw mode from: %s to: %s\n",
                    curr_gw_mode_str, buff);
 
-       batadv_gw_deselect(bat_priv);
+       /* Invoking batadv_gw_reselect() is not enough to really de-select the
+        * current GW. It will only instruct the gateway client code to perform
+        * a re-election the next time that this is needed.
+        *
+        * When gw client mode is being switched off the current GW must be
+        * de-selected explicitly otherwise no GW_ADD uevent is thrown on
+        * client mode re-activation. This is operation is performed in
+        * batadv_gw_check_client_stop().
+        */
+       batadv_gw_reselect(bat_priv);
        /* always call batadv_gw_check_client_stop() before changing the gateway
         * state
         */
@@ -443,6 +450,74 @@ static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
        return batadv_gw_bandwidth_set(net_dev, buff, count);
 }
 
+/**
+ * batadv_show_isolation_mark - print the current isolation mark/mask
+ * @kobj: kobject representing the private mesh sysfs directory
+ * @attr: the batman-adv attribute the user is interacting with
+ * @buff: the buffer that will contain the data to send back to the user
+ *
+ * Returns the number of bytes written into 'buff' on success or a negative
+ * error code in case of failure
+ */
+static ssize_t batadv_show_isolation_mark(struct kobject *kobj,
+                                         struct attribute *attr, char *buff)
+{
+       struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
+
+       return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->isolation_mark,
+                      bat_priv->isolation_mark_mask);
+}
+
+/**
+ * batadv_store_isolation_mark - parse and store the isolation mark/mask entered
+ *  by the user
+ * @kobj: kobject representing the private mesh sysfs directory
+ * @attr: the batman-adv attribute the user is interacting with
+ * @buff: the buffer containing the user data
+ * @count: number of bytes in the buffer
+ *
+ * Returns 'count' on success or a negative error code in case of failure
+ */
+static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
+                                          struct attribute *attr, char *buff,
+                                          size_t count)
+{
+       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
+       struct batadv_priv *bat_priv = netdev_priv(net_dev);
+       uint32_t mark, mask;
+       char *mask_ptr;
+
+       /* parse the mask if it has been specified, otherwise assume the mask is
+        * the biggest possible
+        */
+       mask = 0xFFFFFFFF;
+       mask_ptr = strchr(buff, '/');
+       if (mask_ptr) {
+               *mask_ptr = '\0';
+               mask_ptr++;
+
+               /* the mask must be entered in hex base as it is going to be a
+                * bitmask and not a prefix length
+                */
+               if (kstrtou32(mask_ptr, 16, &mask) < 0)
+                       return -EINVAL;
+       }
+
+       /* the mark can be entered in any base */
+       if (kstrtou32(buff, 0, &mark) < 0)
+               return -EINVAL;
+
+       bat_priv->isolation_mark_mask = mask;
+       /* erase bits not covered by the mask */
+       bat_priv->isolation_mark = mark & bat_priv->isolation_mark_mask;
+
+       batadv_info(net_dev,
+                   "New skb mark for extended isolation: %#.8x/%#.8x\n",
+                   bat_priv->isolation_mark, bat_priv->isolation_mark_mask);
+
+       return count;
+}
+
 BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
 BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
 #ifdef CONFIG_BATMAN_ADV_BLA
@@ -461,7 +536,7 @@ BATADV_ATTR_SIF_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * BATADV_JITTER,
 BATADV_ATTR_SIF_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, BATADV_TQ_MAX_VALUE,
                     NULL);
 BATADV_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, BATADV_TQ_MAX_VALUE,
-                    batadv_post_gw_deselect);
+                    batadv_post_gw_reselect);
 static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
                   batadv_store_gw_bwidth);
 #ifdef CONFIG_BATMAN_ADV_DEBUG
@@ -471,6 +546,8 @@ BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL);
 BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
                     batadv_nc_status_update);
 #endif
+static BATADV_ATTR(isolation_mark, S_IRUGO | S_IWUSR,
+                  batadv_show_isolation_mark, batadv_store_isolation_mark);
 
 static struct batadv_attribute *batadv_mesh_attrs[] = {
        &batadv_attr_aggregated_ogms,
@@ -494,6 +571,7 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
 #ifdef CONFIG_BATMAN_ADV_NC
        &batadv_attr_network_coding,
 #endif
+       &batadv_attr_isolation_mark,
        NULL,
 };
 
index c7d725de50ade81593c0913ab5d868b23383058c..b715b60db7cd6551b77ea77d869e7e68764f9063 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2010-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_SYSFS_H_
index 4add57d4857f11e5ea9edfa13aae1f46dab3e4f9..a6fb1ff25f506b029f5c3fa6432de40f6ce7eacb 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich, Antonio Quartulli
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "main.h"
@@ -51,7 +49,7 @@ static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
        const void *data1 = container_of(node, struct batadv_tt_common_entry,
                                         hash_entry);
 
-       return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+       return batadv_compare_eth(data1, data2);
 }
 
 /**
@@ -333,7 +331,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
                return;
 
        tt_change_node->change.flags = flags;
-       tt_change_node->change.reserved = 0;
+       memset(tt_change_node->change.reserved, 0,
+              sizeof(tt_change_node->change.reserved));
        memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
        tt_change_node->change.vid = htons(common->vid);
 
@@ -475,11 +474,13 @@ static void batadv_tt_global_free(struct batadv_priv *bat_priv,
  * @vid: VLAN identifier
  * @ifindex: index of the interface where the client is connected to (useful to
  *  identify wireless clients)
+ * @mark: the value contained in the skb->mark field of the received packet (if
+ *  any)
  *
  * Returns true if the client was successfully added, false otherwise.
  */
 bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
-                        unsigned short vid, int ifindex)
+                        unsigned short vid, int ifindex, uint32_t mark)
 {
        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
        struct batadv_tt_local_entry *tt_local;
@@ -490,6 +491,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
        int hash_added, table_size, packet_size_max;
        bool ret = false, roamed_back = false;
        uint8_t remote_flags;
+       uint32_t match_mark;
 
        if (ifindex != BATADV_NULL_IFINDEX)
                in_dev = dev_get_by_index(&init_net, ifindex);
@@ -614,6 +616,17 @@ check_roaming:
        else
                tt_local->common.flags &= ~BATADV_TT_CLIENT_WIFI;
 
+       /* check the mark in the skb: if it's equal to the configured
+        * isolation_mark, it means the packet is coming from an isolated
+        * non-mesh client
+        */
+       match_mark = (mark & bat_priv->isolation_mark_mask);
+       if (bat_priv->isolation_mark_mask &&
+           match_mark == bat_priv->isolation_mark)
+               tt_local->common.flags |= BATADV_TT_CLIENT_ISOLA;
+       else
+               tt_local->common.flags &= ~BATADV_TT_CLIENT_ISOLA;
+
        /* if any "dynamic" flag has been modified, resend an ADD event for this
         * entry so that all the nodes can get the new flags
         */
@@ -874,7 +887,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
        seq_printf(seq,
                   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
                   net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn));
-       seq_printf(seq, "       %-13s  %s %-7s %-9s (%-10s)\n", "Client", "VID",
+       seq_printf(seq, "       %-13s  %s %-8s %-9s (%-10s)\n", "Client", "VID",
                   "Flags", "Last seen", "CRC");
 
        for (i = 0; i < hash->size; i++) {
@@ -902,7 +915,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
                        }
 
                        seq_printf(seq,
-                                  " * %pM %4i [%c%c%c%c%c] %3u.%03u   (%#.8x)\n",
+                                  " * %pM %4i [%c%c%c%c%c%c] %3u.%03u   (%#.8x)\n",
                                   tt_common_entry->addr,
                                   BATADV_PRINT_VID(tt_common_entry->vid),
                                   (tt_common_entry->flags &
@@ -914,6 +927,8 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
                                    BATADV_TT_CLIENT_PENDING ? 'X' : '.'),
                                   (tt_common_entry->flags &
                                    BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
+                                  (tt_common_entry->flags &
+                                   BATADV_TT_CLIENT_ISOLA ? 'I' : '.'),
                                   no_purge ? 0 : last_seen_secs,
                                   no_purge ? 0 : last_seen_msecs,
                                   vlan->tt.crc);
@@ -1385,12 +1400,14 @@ batadv_transtable_best_orig(struct batadv_priv *bat_priv,
 
        head = &tt_global_entry->orig_list;
        hlist_for_each_entry_rcu(orig_entry, head, list) {
-               router = batadv_orig_node_get_router(orig_entry->orig_node);
+               router = batadv_orig_router_get(orig_entry->orig_node,
+                                               BATADV_IF_DEFAULT);
                if (!router)
                        continue;
 
                if (best_router &&
-                   bao->bat_neigh_cmp(router, best_router) <= 0) {
+                   bao->bat_neigh_cmp(router, BATADV_IF_DEFAULT,
+                                      best_router, BATADV_IF_DEFAULT) <= 0) {
                        batadv_neigh_node_free_ref(router);
                        continue;
                }
@@ -1446,13 +1463,14 @@ batadv_tt_global_print_entry(struct batadv_priv *bat_priv,
 
                last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
                seq_printf(seq,
-                          " %c %pM %4i   (%3u) via %pM     (%3u)   (%#.8x) [%c%c%c]\n",
+                          " %c %pM %4i   (%3u) via %pM     (%3u)   (%#.8x) [%c%c%c%c]\n",
                           '*', tt_global_entry->common.addr,
                           BATADV_PRINT_VID(tt_global_entry->common.vid),
                           best_entry->ttvn, best_entry->orig_node->orig,
                           last_ttvn, vlan->tt.crc,
                           (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
                           (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
+                          (flags & BATADV_TT_CLIENT_ISOLA ? 'I' : '.'),
                           (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
 
                batadv_orig_node_vlan_free_ref(vlan);
@@ -1477,13 +1495,14 @@ print_list:
 
                last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
                seq_printf(seq,
-                          " %c %pM %4d   (%3u) via %pM     (%3u)   (%#.8x) [%c%c%c]\n",
+                          " %c %pM %4d   (%3u) via %pM     (%3u)   (%#.8x) [%c%c%c%c]\n",
                           '+', tt_global_entry->common.addr,
                           BATADV_PRINT_VID(tt_global_entry->common.vid),
                           orig_entry->ttvn, orig_entry->orig_node->orig,
                           last_ttvn, vlan->tt.crc,
                           (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
                           (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
+                          (flags & BATADV_TT_CLIENT_ISOLA ? 'I' : '.'),
                           (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
 
                batadv_orig_node_vlan_free_ref(vlan);
@@ -1852,6 +1871,11 @@ _batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
            tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
                ret = true;
 
+       /* check if the two clients are marked as isolated */
+       if (tt_local_entry->common.flags & BATADV_TT_CLIENT_ISOLA &&
+           tt_global_entry->common.flags & BATADV_TT_CLIENT_ISOLA)
+               ret = true;
+
        return ret;
 }
 
@@ -1878,19 +1902,8 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
        struct batadv_tt_global_entry *tt_global_entry = NULL;
        struct batadv_orig_node *orig_node = NULL;
        struct batadv_tt_orig_list_entry *best_entry;
-       bool ap_isolation_enabled = false;
-       struct batadv_softif_vlan *vlan;
 
-       /* if the AP isolation is requested on a VLAN, then check for its
-        * setting in the proper VLAN private data structure
-        */
-       vlan = batadv_softif_vlan_get(bat_priv, vid);
-       if (vlan) {
-               ap_isolation_enabled = atomic_read(&vlan->ap_isolation);
-               batadv_softif_vlan_free_ref(vlan);
-       }
-
-       if (src && ap_isolation_enabled) {
+       if (src && batadv_vlan_ap_isola_get(bat_priv, vid)) {
                tt_local_entry = batadv_tt_local_hash_find(bat_priv, src, vid);
                if (!tt_local_entry ||
                    (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
@@ -2221,7 +2234,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
                               ETH_ALEN);
                        tt_change->flags = tt_common_entry->flags;
                        tt_change->vid = htons(tt_common_entry->vid);
-                       tt_change->reserved = 0;
+                       memset(tt_change->reserved, 0,
+                              sizeof(tt_change->reserved));
 
                        tt_num_entries++;
                        tt_change++;
@@ -3565,3 +3579,29 @@ int batadv_tt_init(struct batadv_priv *bat_priv)
 
        return 1;
 }
+
+/**
+ * batadv_tt_global_is_isolated - check if a client is marked as isolated
+ * @bat_priv: the bat priv with all the soft interface information
+ * @addr: the mac address of the client
+ * @vid: the identifier of the VLAN where this client is connected
+ *
+ * Returns true if the client is marked with the TT_CLIENT_ISOLA flag, false
+ * otherwise
+ */
+bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
+                                 const uint8_t *addr, unsigned short vid)
+{
+       struct batadv_tt_global_entry *tt;
+       bool ret;
+
+       tt = batadv_tt_global_hash_find(bat_priv, addr, vid);
+       if (!tt)
+               return false;
+
+       ret = tt->common.flags & BATADV_TT_CLIENT_ISOLA;
+
+       batadv_tt_global_entry_free_ref(tt);
+
+       return ret;
+}
index 026b1ffa674699ea7561df5456dd0c91f15d3521..20a1d7861ded99ecb18cace18af3b85f06fbe018 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich, Antonio Quartulli
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
@@ -22,7 +20,7 @@
 
 int batadv_tt_init(struct batadv_priv *bat_priv);
 bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
-                        unsigned short vid, int ifindex);
+                        unsigned short vid, int ifindex, uint32_t mark);
 uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
                                const uint8_t *addr, unsigned short vid,
                                const char *message, bool roaming);
@@ -50,5 +48,7 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
                                          struct batadv_orig_node *orig_node,
                                          const unsigned char *addr,
                                          unsigned short vid);
+bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
+                                 const uint8_t *addr, unsigned short vid);
 
 #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
index 91dd369b0ff21790b9fae41b88005be95bf0ffe4..b53f90d85db9a26d70312c5e93bd3a6a18a579b3 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -12,9 +12,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _NET_BATMAN_ADV_TYPES_H_
 
 #endif /* CONFIG_BATMAN_ADV_DAT */
 
+/**
+ * enum batadv_dhcp_recipient - dhcp destination
+ * @BATADV_DHCP_NO: packet is not a dhcp message
+ * @BATADV_DHCP_TO_SERVER: dhcp message is directed to a server
+ * @BATADV_DHCP_TO_CLIENT: dhcp message is directed to a client
+ */
+enum batadv_dhcp_recipient {
+       BATADV_DHCP_NO = 0,
+       BATADV_DHCP_TO_SERVER,
+       BATADV_DHCP_TO_CLIENT,
+};
+
 /**
  * BATADV_TT_REMOTE_MASK - bitmask selecting the flags that are sent over the
  *  wire only
@@ -74,6 +84,7 @@ struct batadv_hard_iface_bat_iv {
  * @rcu: struct used for freeing in an RCU-safe manner
  * @bat_iv: BATMAN IV specific per hard interface data
  * @cleanup_work: work queue callback item for hard interface deinit
+ * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs
  */
 struct batadv_hard_iface {
        struct list_head list;
@@ -88,6 +99,29 @@ struct batadv_hard_iface {
        struct rcu_head rcu;
        struct batadv_hard_iface_bat_iv bat_iv;
        struct work_struct cleanup_work;
+       struct dentry *debug_dir;
+};
+
+/**
+ * struct batadv_orig_ifinfo - originator info per outgoing interface
+ * @list: list node for orig_node::ifinfo_list
+ * @if_outgoing: pointer to outgoing hard interface
+ * @router: router that should be used to reach this originator
+ * @last_real_seqno: last and best known sequence number
+ * @last_ttl: ttl of last received packet
+ * @batman_seqno_reset: time when the batman seqno window was reset
+ * @refcount: number of contexts the object is used
+ * @rcu: struct used for freeing in an RCU-safe manner
+ */
+struct batadv_orig_ifinfo {
+       struct hlist_node list;
+       struct batadv_hard_iface *if_outgoing;
+       struct batadv_neigh_node __rcu *router; /* rcu protected pointer */
+       uint32_t last_real_seqno;
+       uint8_t last_ttl;
+       unsigned long batman_seqno_reset;
+       atomic_t refcount;
+       struct rcu_head rcu;
 };
 
 /**
@@ -165,11 +199,11 @@ struct batadv_orig_bat_iv {
  * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh
  * @orig: originator ethernet address
  * @primary_addr: hosts primary interface address
- * @router: router that should be used to reach this originator
+ * @ifinfo_list: list for routers per outgoing interface
+ * @last_bonding_candidate: pointer to last ifinfo of last used router
  * @batadv_dat_addr_t:  address of the orig node in the distributed hash
  * @last_seen: time when last packet from this node was received
  * @bcast_seqno_reset: time when the broadcast seqno window was reset
- * @batman_seqno_reset: time when the batman seqno window was reset
  * @capabilities: announced capabilities of this originator
  * @last_ttvn: last seen translation table version number
  * @tt_buff: last tt changeset this node received from the orig node
@@ -182,19 +216,15 @@ struct batadv_orig_bat_iv {
  *  made up by two operations (data structure update and metdata -CRC/TTVN-
  *  recalculation) and they have to be executed atomically in order to avoid
  *  another thread to read the table/metadata between those.
- * @last_real_seqno: last and best known sequence number
- * @last_ttl: ttl of last received packet
  * @bcast_bits: bitfield containing the info which payload broadcast originated
  *  from this orig node this host already has seen (relative to
  *  last_bcast_seqno)
  * @last_bcast_seqno: last broadcast sequence number received by this host
  * @neigh_list: list of potential next hop neighbor towards this orig node
- * @neigh_list_lock: lock protecting neigh_list, router and bonding_list
+ * @neigh_list_lock: lock protecting neigh_list and router
  * @hash_entry: hlist node for batadv_priv::orig_hash
  * @bat_priv: pointer to soft_iface this orig node belongs to
  * @bcast_seqno_lock: lock protecting bcast_bits & last_bcast_seqno
- * @bond_candidates: how many candidates are available
- * @bond_list: list of bonding candidates
  * @refcount: number of contexts the object is used
  * @rcu: struct used for freeing in an RCU-safe manner
  * @in_coding_list: list of nodes this orig can hear
@@ -210,13 +240,13 @@ struct batadv_orig_bat_iv {
 struct batadv_orig_node {
        uint8_t orig[ETH_ALEN];
        uint8_t primary_addr[ETH_ALEN];
-       struct batadv_neigh_node __rcu *router; /* rcu protected pointer */
+       struct hlist_head ifinfo_list;
+       struct batadv_orig_ifinfo *last_bonding_candidate;
 #ifdef CONFIG_BATMAN_ADV_DAT
        batadv_dat_addr_t dat_addr;
 #endif
        unsigned long last_seen;
        unsigned long bcast_seqno_reset;
-       unsigned long batman_seqno_reset;
        uint8_t capabilities;
        atomic_t last_ttvn;
        unsigned char *tt_buff;
@@ -225,19 +255,15 @@ struct batadv_orig_node {
        bool tt_initialised;
        /* prevents from changing the table while reading it */
        spinlock_t tt_lock;
-       uint32_t last_real_seqno;
-       uint8_t last_ttl;
        DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
        uint32_t last_bcast_seqno;
        struct hlist_head neigh_list;
-       /* neigh_list_lock protects: neigh_list, router & bonding_list */
+       /* neigh_list_lock protects: neigh_list and router */
        spinlock_t neigh_list_lock;
        struct hlist_node hash_entry;
        struct batadv_priv *bat_priv;
        /* bcast_seqno_lock protects: bcast_bits & last_bcast_seqno */
        spinlock_t bcast_seqno_lock;
-       atomic_t bond_candidates;
-       struct list_head bond_list;
        atomic_t refcount;
        struct rcu_head rcu;
 #ifdef CONFIG_BATMAN_ADV_NC
@@ -283,49 +309,62 @@ struct batadv_gw_node {
 };
 
 /**
- * struct batadv_neigh_bat_iv - B.A.T.M.A.N. IV specific structure for single
- *  hop neighbors
+ * struct batadv_neigh_node - structure for single hops neighbors
+ * @list: list node for batadv_orig_node::neigh_list
+ * @orig_node: pointer to corresponding orig_node
+ * @addr: the MAC address of the neighboring interface
+ * @ifinfo_list: list for routing metrics per outgoing interface
+ * @ifinfo_lock: lock protecting private ifinfo members and list
+ * @if_incoming: pointer to incoming hard interface
+ * @last_seen: when last packet via this neighbor was received
+ * @last_ttl: last received ttl from this neigh node
+ * @rcu: struct used for freeing in an RCU-safe manner
+ * @bat_iv: B.A.T.M.A.N. IV private structure
+ */
+struct batadv_neigh_node {
+       struct hlist_node list;
+       struct batadv_orig_node *orig_node;
+       uint8_t addr[ETH_ALEN];
+       struct hlist_head ifinfo_list;
+       spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */
+       struct batadv_hard_iface *if_incoming;
+       unsigned long last_seen;
+       atomic_t refcount;
+       struct rcu_head rcu;
+};
+
+/* struct batadv_neigh_node_bat_iv - neighbor information per outgoing
+ *  interface for BATMAN IV
  * @tq_recv: ring buffer of received TQ values from this neigh node
  * @tq_index: ring buffer index
  * @tq_avg: averaged tq of all tq values in the ring buffer (tq_recv)
  * @real_bits: bitfield containing the number of OGMs received from this neigh
  *  node (relative to orig_node->last_real_seqno)
  * @real_packet_count: counted result of real_bits
- * @lq_update_lock: lock protecting tq_recv & tq_index
  */
-struct batadv_neigh_bat_iv {
+struct batadv_neigh_ifinfo_bat_iv {
        uint8_t tq_recv[BATADV_TQ_GLOBAL_WINDOW_SIZE];
        uint8_t tq_index;
        uint8_t tq_avg;
        DECLARE_BITMAP(real_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
        uint8_t real_packet_count;
-       spinlock_t lq_update_lock; /* protects tq_recv & tq_index */
 };
 
-/**
- * struct batadv_neigh_node - structure for single hops neighbors
- * @list: list node for batadv_orig_node::neigh_list
- * @orig_node: pointer to corresponding orig_node
- * @addr: the MAC address of the neighboring interface
- * @if_incoming: pointer to incoming hard interface
- * @last_seen: when last packet via this neighbor was received
+/* struct batadv_neigh_ifinfo - neighbor information per outgoing interface
+ * @list: list node for batadv_neigh_node::ifinfo_list
+ * @if_outgoing: pointer to outgoing hard interface
+ * @bat_iv: B.A.T.M.A.N. IV private structure
  * @last_ttl: last received ttl from this neigh node
- * @bonding_list: list node for batadv_orig_node::bond_list
  * @refcount: number of contexts the object is used
- * @rcu: struct used for freeing in an RCU-safe manner
- * @bat_iv: B.A.T.M.A.N. IV private structure
+ * @rcu: struct used for freeing in a RCU-safe manner
  */
-struct batadv_neigh_node {
+struct batadv_neigh_ifinfo {
        struct hlist_node list;
-       struct batadv_orig_node *orig_node;
-       uint8_t addr[ETH_ALEN];
-       struct batadv_hard_iface *if_incoming;
-       unsigned long last_seen;
+       struct batadv_hard_iface *if_outgoing;
+       struct batadv_neigh_ifinfo_bat_iv bat_iv;
        uint8_t last_ttl;
-       struct list_head bonding_list;
        atomic_t refcount;
        struct rcu_head rcu;
-       struct batadv_neigh_bat_iv bat_iv;
 };
 
 /**
@@ -687,6 +726,8 @@ struct batadv_priv {
 #ifdef CONFIG_BATMAN_ADV_DEBUG
        atomic_t log_level;
 #endif
+       uint32_t isolation_mark;
+       uint32_t isolation_mark_mask;
        atomic_t bcast_seqno;
        atomic_t bcast_queue_left;
        atomic_t batman_queue_left;
@@ -981,8 +1022,10 @@ struct batadv_skb_cb {
  * @direct_link_flags: direct link flags for aggregated OGM packets
  * @num_packets: counter for bcast packet retransmission
  * @delayed_work: work queue callback item for packet sending
- * @if_incoming: pointer incoming hard-iface or primary iface if locally
- *  generated packet
+ * @if_incoming: pointer to incoming hard-iface or primary iface if
+ *  locally generated packet
+ * @if_outgoing: packet where the packet should be sent to, or NULL if
+ *  unspecified
  */
 struct batadv_forw_packet {
        struct hlist_node list;
@@ -994,6 +1037,7 @@ struct batadv_forw_packet {
        uint8_t num_packets;
        struct delayed_work delayed_work;
        struct batadv_hard_iface *if_incoming;
+       struct batadv_hard_iface *if_outgoing;
 };
 
 /**
@@ -1007,9 +1051,11 @@ struct batadv_forw_packet {
  * @bat_primary_iface_set: called when primary interface is selected / changed
  * @bat_ogm_schedule: prepare a new outgoing OGM for the send queue
  * @bat_ogm_emit: send scheduled OGM
- * @bat_neigh_cmp: compare the metrics of two neighbors
- * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or
- *  better than neigh2 from the metric prospective
+ * @bat_neigh_cmp: compare the metrics of two neighbors for their respective
+ *  outgoing interfaces
+ * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or better
+ *  than neigh2 for their respective outgoing interface from the metric
+ *  prospective
  * @bat_orig_print: print the originator table (optional)
  * @bat_orig_free: free the resources allocated by the routing algorithm for an
  *  orig_node object
@@ -1028,11 +1074,17 @@ struct batadv_algo_ops {
        void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface);
        void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet);
        int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1,
-                            struct batadv_neigh_node *neigh2);
-       bool (*bat_neigh_is_equiv_or_better)(struct batadv_neigh_node *neigh1,
-                                            struct batadv_neigh_node *neigh2);
+                            struct batadv_hard_iface *if_outgoing1,
+                            struct batadv_neigh_node *neigh2,
+                            struct batadv_hard_iface *if_outgoing2);
+       bool (*bat_neigh_is_equiv_or_better)
+               (struct batadv_neigh_node *neigh1,
+                struct batadv_hard_iface *if_outgoing1,
+                struct batadv_neigh_node *neigh2,
+                struct batadv_hard_iface *if_outgoing2);
        /* orig_node handling API */
-       void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq);
+       void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq,
+                              struct batadv_hard_iface *hard_iface);
        void (*bat_orig_free)(struct batadv_orig_node *orig_node);
        int (*bat_orig_add_if)(struct batadv_orig_node *orig_node,
                               int max_if_num);
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
new file mode 100644 (file)
index 0000000..adb3ea0
--- /dev/null
@@ -0,0 +1,860 @@
+/*
+   Copyright (c) 2013 Intel Corp.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 and
+   only version 2 as published by the Free Software Foundation.
+
+   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/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/addrconf.h>
+
+#include <net/af_ieee802154.h> /* to get the address type */
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+
+#include "6lowpan.h"
+
+#include "../ieee802154/6lowpan.h" /* for the compression support */
+
+#define IFACE_NAME_TEMPLATE "bt%d"
+#define EUI64_ADDR_LEN 8
+
+struct skb_cb {
+       struct in6_addr addr;
+       struct l2cap_conn *conn;
+};
+#define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb))
+
+/* The devices list contains those devices that we are acting
+ * as a proxy. The BT 6LoWPAN device is a virtual device that
+ * connects to the Bluetooth LE device. The real connection to
+ * BT device is done via l2cap layer. There exists one
+ * virtual device / one BT 6LoWPAN network (=hciX device).
+ * The list contains struct lowpan_dev elements.
+ */
+static LIST_HEAD(bt_6lowpan_devices);
+static DEFINE_RWLOCK(devices_lock);
+
+struct lowpan_peer {
+       struct list_head list;
+       struct l2cap_conn *conn;
+
+       /* peer addresses in various formats */
+       unsigned char eui64_addr[EUI64_ADDR_LEN];
+       struct in6_addr peer_addr;
+};
+
+struct lowpan_dev {
+       struct list_head list;
+
+       struct hci_dev *hdev;
+       struct net_device *netdev;
+       struct list_head peers;
+       atomic_t peer_count; /* number of items in peers list */
+
+       struct work_struct delete_netdev;
+       struct delayed_work notify_peers;
+};
+
+static inline struct lowpan_dev *lowpan_dev(const struct net_device *netdev)
+{
+       return netdev_priv(netdev);
+}
+
+static inline void peer_add(struct lowpan_dev *dev, struct lowpan_peer *peer)
+{
+       list_add(&peer->list, &dev->peers);
+       atomic_inc(&dev->peer_count);
+}
+
+static inline bool peer_del(struct lowpan_dev *dev, struct lowpan_peer *peer)
+{
+       list_del(&peer->list);
+
+       if (atomic_dec_and_test(&dev->peer_count)) {
+               BT_DBG("last peer");
+               return true;
+       }
+
+       return false;
+}
+
+static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_dev *dev,
+                                                bdaddr_t *ba, __u8 type)
+{
+       struct lowpan_peer *peer, *tmp;
+
+       BT_DBG("peers %d addr %pMR type %d", atomic_read(&dev->peer_count),
+              ba, type);
+
+       list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
+               BT_DBG("addr %pMR type %d",
+                      &peer->conn->hcon->dst, peer->conn->hcon->dst_type);
+
+               if (bacmp(&peer->conn->hcon->dst, ba))
+                       continue;
+
+               if (type == peer->conn->hcon->dst_type)
+                       return peer;
+       }
+
+       return NULL;
+}
+
+static inline struct lowpan_peer *peer_lookup_conn(struct lowpan_dev *dev,
+                                                  struct l2cap_conn *conn)
+{
+       struct lowpan_peer *peer, *tmp;
+
+       list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
+               if (peer->conn == conn)
+                       return peer;
+       }
+
+       return NULL;
+}
+
+static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn)
+{
+       struct lowpan_dev *entry, *tmp;
+       struct lowpan_peer *peer = NULL;
+       unsigned long flags;
+
+       read_lock_irqsave(&devices_lock, flags);
+
+       list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+               peer = peer_lookup_conn(entry, conn);
+               if (peer)
+                       break;
+       }
+
+       read_unlock_irqrestore(&devices_lock, flags);
+
+       return peer;
+}
+
+static struct lowpan_dev *lookup_dev(struct l2cap_conn *conn)
+{
+       struct lowpan_dev *entry, *tmp;
+       struct lowpan_dev *dev = NULL;
+       unsigned long flags;
+
+       read_lock_irqsave(&devices_lock, flags);
+
+       list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+               if (conn->hcon->hdev == entry->hdev) {
+                       dev = entry;
+                       break;
+               }
+       }
+
+       read_unlock_irqrestore(&devices_lock, flags);
+
+       return dev;
+}
+
+static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
+{
+       struct sk_buff *skb_cp;
+       int ret;
+
+       skb_cp = skb_copy(skb, GFP_ATOMIC);
+       if (!skb_cp)
+               return -ENOMEM;
+
+       ret = netif_rx(skb_cp);
+
+       BT_DBG("receive skb %d", ret);
+       if (ret < 0)
+               return NET_RX_DROP;
+
+       return ret;
+}
+
+static int process_data(struct sk_buff *skb, struct net_device *netdev,
+                       struct l2cap_conn *conn)
+{
+       const u8 *saddr, *daddr;
+       u8 iphc0, iphc1;
+       struct lowpan_dev *dev;
+       struct lowpan_peer *peer;
+       unsigned long flags;
+
+       dev = lowpan_dev(netdev);
+
+       read_lock_irqsave(&devices_lock, flags);
+       peer = peer_lookup_conn(dev, conn);
+       read_unlock_irqrestore(&devices_lock, flags);
+       if (!peer)
+               goto drop;
+
+       saddr = peer->eui64_addr;
+       daddr = dev->netdev->dev_addr;
+
+       /* at least two bytes will be used for the encoding */
+       if (skb->len < 2)
+               goto drop;
+
+       if (lowpan_fetch_skb_u8(skb, &iphc0))
+               goto drop;
+
+       if (lowpan_fetch_skb_u8(skb, &iphc1))
+               goto drop;
+
+       return lowpan_process_data(skb, netdev,
+                                  saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+                                  daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+                                  iphc0, iphc1, give_skb_to_upper);
+
+drop:
+       kfree_skb(skb);
+       return -EINVAL;
+}
+
+static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
+                   struct l2cap_conn *conn)
+{
+       struct sk_buff *local_skb;
+       int ret;
+
+       if (!netif_running(dev))
+               goto drop;
+
+       if (dev->type != ARPHRD_6LOWPAN)
+               goto drop;
+
+       /* check that it's our buffer */
+       if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
+               /* Copy the packet so that the IPv6 header is
+                * properly aligned.
+                */
+               local_skb = skb_copy_expand(skb, NET_SKB_PAD - 1,
+                                           skb_tailroom(skb), GFP_ATOMIC);
+               if (!local_skb)
+                       goto drop;
+
+               local_skb->protocol = htons(ETH_P_IPV6);
+               local_skb->pkt_type = PACKET_HOST;
+
+               skb_reset_network_header(local_skb);
+               skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
+
+               if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) {
+                       kfree_skb(local_skb);
+                       goto drop;
+               }
+
+               dev->stats.rx_bytes += skb->len;
+               dev->stats.rx_packets++;
+
+               kfree_skb(local_skb);
+               kfree_skb(skb);
+       } else {
+               switch (skb->data[0] & 0xe0) {
+               case LOWPAN_DISPATCH_IPHC:      /* ipv6 datagram */
+                       local_skb = skb_clone(skb, GFP_ATOMIC);
+                       if (!local_skb)
+                               goto drop;
+
+                       ret = process_data(local_skb, dev, conn);
+                       if (ret != NET_RX_SUCCESS)
+                               goto drop;
+
+                       dev->stats.rx_bytes += skb->len;
+                       dev->stats.rx_packets++;
+
+                       kfree_skb(skb);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return NET_RX_SUCCESS;
+
+drop:
+       kfree_skb(skb);
+       return NET_RX_DROP;
+}
+
+/* Packet from BT LE device */
+int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+       struct lowpan_dev *dev;
+       struct lowpan_peer *peer;
+       int err;
+
+       peer = lookup_peer(conn);
+       if (!peer)
+               return -ENOENT;
+
+       dev = lookup_dev(conn);
+       if (!dev || !dev->netdev)
+               return -ENOENT;
+
+       err = recv_pkt(skb, dev->netdev, conn);
+       BT_DBG("recv pkt %d", err);
+
+       return err;
+}
+
+static inline int skbuff_copy(void *msg, int len, int count, int mtu,
+                             struct sk_buff *skb, struct net_device *dev)
+{
+       struct sk_buff **frag;
+       int sent = 0;
+
+       memcpy(skb_put(skb, count), msg, count);
+
+       sent += count;
+       msg  += count;
+       len  -= count;
+
+       dev->stats.tx_bytes += count;
+       dev->stats.tx_packets++;
+
+       raw_dump_table(__func__, "Sending", skb->data, skb->len);
+
+       /* Continuation fragments (no L2CAP header) */
+       frag = &skb_shinfo(skb)->frag_list;
+       while (len > 0) {
+               struct sk_buff *tmp;
+
+               count = min_t(unsigned int, mtu, len);
+
+               tmp = bt_skb_alloc(count, GFP_ATOMIC);
+               if (!tmp)
+                       return -ENOMEM;
+
+               *frag = tmp;
+
+               memcpy(skb_put(*frag, count), msg, count);
+
+               raw_dump_table(__func__, "Sending fragment",
+                              (*frag)->data, count);
+
+               (*frag)->priority = skb->priority;
+
+               sent += count;
+               msg  += count;
+               len  -= count;
+
+               skb->len += (*frag)->len;
+               skb->data_len += (*frag)->len;
+
+               frag = &(*frag)->next;
+
+               dev->stats.tx_bytes += count;
+               dev->stats.tx_packets++;
+       }
+
+       return sent;
+}
+
+static struct sk_buff *create_pdu(struct l2cap_conn *conn, void *msg,
+                                 size_t len, u32 priority,
+                                 struct net_device *dev)
+{
+       struct sk_buff *skb;
+       int err, count;
+       struct l2cap_hdr *lh;
+
+       /* FIXME: This mtu check should be not needed and atm is only used for
+        * testing purposes
+        */
+       if (conn->mtu > (L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE))
+               conn->mtu = L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE;
+
+       count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
+
+       BT_DBG("conn %p len %zu mtu %d count %d", conn, len, conn->mtu, count);
+
+       skb = bt_skb_alloc(count + L2CAP_HDR_SIZE, GFP_ATOMIC);
+       if (!skb)
+               return ERR_PTR(-ENOMEM);
+
+       skb->priority = priority;
+
+       lh = (struct l2cap_hdr *)skb_put(skb, L2CAP_HDR_SIZE);
+       lh->cid = cpu_to_le16(L2CAP_FC_6LOWPAN);
+       lh->len = cpu_to_le16(len);
+
+       err = skbuff_copy(msg, len, count, conn->mtu, skb, dev);
+       if (unlikely(err < 0)) {
+               kfree_skb(skb);
+               BT_DBG("skbuff copy %d failed", err);
+               return ERR_PTR(err);
+       }
+
+       return skb;
+}
+
+static int conn_send(struct l2cap_conn *conn,
+                    void *msg, size_t len, u32 priority,
+                    struct net_device *dev)
+{
+       struct sk_buff *skb;
+
+       skb = create_pdu(conn, msg, len, priority, dev);
+       if (IS_ERR(skb))
+               return -EINVAL;
+
+       BT_DBG("conn %p skb %p len %d priority %u", conn, skb, skb->len,
+              skb->priority);
+
+       hci_send_acl(conn->hchan, skb, ACL_START);
+
+       return 0;
+}
+
+static void get_dest_bdaddr(struct in6_addr *ip6_daddr,
+                           bdaddr_t *addr, u8 *addr_type)
+{
+       u8 *eui64;
+
+       eui64 = ip6_daddr->s6_addr + 8;
+
+       addr->b[0] = eui64[7];
+       addr->b[1] = eui64[6];
+       addr->b[2] = eui64[5];
+       addr->b[3] = eui64[2];
+       addr->b[4] = eui64[1];
+       addr->b[5] = eui64[0];
+
+       addr->b[5] ^= 2;
+
+       /* Set universal/local bit to 0 */
+       if (addr->b[5] & 1) {
+               addr->b[5] &= ~1;
+               *addr_type = ADDR_LE_DEV_PUBLIC;
+       } else {
+               *addr_type = ADDR_LE_DEV_RANDOM;
+       }
+}
+
+static int header_create(struct sk_buff *skb, struct net_device *netdev,
+                        unsigned short type, const void *_daddr,
+                        const void *_saddr, unsigned int len)
+{
+       struct ipv6hdr *hdr;
+       struct lowpan_dev *dev;
+       struct lowpan_peer *peer;
+       bdaddr_t addr, *any = BDADDR_ANY;
+       u8 *saddr, *daddr = any->b;
+       u8 addr_type;
+
+       if (type != ETH_P_IPV6)
+               return -EINVAL;
+
+       hdr = ipv6_hdr(skb);
+
+       dev = lowpan_dev(netdev);
+
+       if (ipv6_addr_is_multicast(&hdr->daddr)) {
+               memcpy(&lowpan_cb(skb)->addr, &hdr->daddr,
+                      sizeof(struct in6_addr));
+               lowpan_cb(skb)->conn = NULL;
+       } else {
+               unsigned long flags;
+
+               /* Get destination BT device from skb.
+                * If there is no such peer then discard the packet.
+                */
+               get_dest_bdaddr(&hdr->daddr, &addr, &addr_type);
+
+               BT_DBG("dest addr %pMR type %d", &addr, addr_type);
+
+               read_lock_irqsave(&devices_lock, flags);
+               peer = peer_lookup_ba(dev, &addr, addr_type);
+               read_unlock_irqrestore(&devices_lock, flags);
+
+               if (!peer) {
+                       BT_DBG("no such peer %pMR found", &addr);
+                       return -ENOENT;
+               }
+
+               daddr = peer->eui64_addr;
+
+               memcpy(&lowpan_cb(skb)->addr, &hdr->daddr,
+                      sizeof(struct in6_addr));
+               lowpan_cb(skb)->conn = peer->conn;
+       }
+
+       saddr = dev->netdev->dev_addr;
+
+       return lowpan_header_compress(skb, netdev, type, daddr, saddr, len);
+}
+
+/* Packet to BT LE device */
+static int send_pkt(struct l2cap_conn *conn, const void *saddr,
+                   const void *daddr, struct sk_buff *skb,
+                   struct net_device *netdev)
+{
+       raw_dump_table(__func__, "raw skb data dump before fragmentation",
+                      skb->data, skb->len);
+
+       return conn_send(conn, skb->data, skb->len, 0, netdev);
+}
+
+static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct sk_buff *local_skb;
+       struct lowpan_dev *entry, *tmp;
+       unsigned long flags;
+
+       read_lock_irqsave(&devices_lock, flags);
+
+       list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+               struct lowpan_peer *pentry, *ptmp;
+               struct lowpan_dev *dev;
+
+               if (entry->netdev != netdev)
+                       continue;
+
+               dev = lowpan_dev(entry->netdev);
+
+               list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) {
+                       local_skb = skb_clone(skb, GFP_ATOMIC);
+
+                       send_pkt(pentry->conn, netdev->dev_addr,
+                                pentry->eui64_addr, local_skb, netdev);
+
+                       kfree_skb(local_skb);
+               }
+       }
+
+       read_unlock_irqrestore(&devices_lock, flags);
+}
+
+static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+       int err = 0;
+       unsigned char *eui64_addr;
+       struct lowpan_dev *dev;
+       struct lowpan_peer *peer;
+       bdaddr_t addr;
+       u8 addr_type;
+
+       if (ipv6_addr_is_multicast(&lowpan_cb(skb)->addr)) {
+               /* We need to send the packet to every device
+                * behind this interface.
+                */
+               send_mcast_pkt(skb, netdev);
+       } else {
+               unsigned long flags;
+
+               get_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
+               eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8;
+               dev = lowpan_dev(netdev);
+
+               read_lock_irqsave(&devices_lock, flags);
+               peer = peer_lookup_ba(dev, &addr, addr_type);
+               read_unlock_irqrestore(&devices_lock, flags);
+
+               BT_DBG("xmit from %s to %pMR (%pI6c) peer %p", netdev->name,
+                      &addr, &lowpan_cb(skb)->addr, peer);
+
+               if (peer && peer->conn)
+                       err = send_pkt(peer->conn, netdev->dev_addr,
+                                      eui64_addr, skb, netdev);
+       }
+       dev_kfree_skb(skb);
+
+       if (err)
+               BT_DBG("ERROR: xmit failed (%d)", err);
+
+       return (err < 0) ? NET_XMIT_DROP : err;
+}
+
+static const struct net_device_ops netdev_ops = {
+       .ndo_start_xmit         = bt_xmit,
+};
+
+static struct header_ops header_ops = {
+       .create = header_create,
+};
+
+static void netdev_setup(struct net_device *dev)
+{
+       dev->addr_len           = EUI64_ADDR_LEN;
+       dev->type               = ARPHRD_6LOWPAN;
+
+       dev->hard_header_len    = 0;
+       dev->needed_tailroom    = 0;
+       dev->mtu                = IPV6_MIN_MTU;
+       dev->tx_queue_len       = 0;
+       dev->flags              = IFF_RUNNING | IFF_POINTOPOINT;
+       dev->watchdog_timeo     = 0;
+
+       dev->netdev_ops         = &netdev_ops;
+       dev->header_ops         = &header_ops;
+       dev->destructor         = free_netdev;
+}
+
+static struct device_type bt_type = {
+       .name   = "bluetooth",
+};
+
+static void set_addr(u8 *eui, u8 *addr, u8 addr_type)
+{
+       /* addr is the BT address in little-endian format */
+       eui[0] = addr[5];
+       eui[1] = addr[4];
+       eui[2] = addr[3];
+       eui[3] = 0xFF;
+       eui[4] = 0xFE;
+       eui[5] = addr[2];
+       eui[6] = addr[1];
+       eui[7] = addr[0];
+
+       eui[0] ^= 2;
+
+       /* Universal/local bit set, RFC 4291 */
+       if (addr_type == ADDR_LE_DEV_PUBLIC)
+               eui[0] |= 1;
+       else
+               eui[0] &= ~1;
+}
+
+static void set_dev_addr(struct net_device *netdev, bdaddr_t *addr,
+                        u8 addr_type)
+{
+       netdev->addr_assign_type = NET_ADDR_PERM;
+       set_addr(netdev->dev_addr, addr->b, addr_type);
+       netdev->dev_addr[0] ^= 2;
+}
+
+static void ifup(struct net_device *netdev)
+{
+       int err;
+
+       rtnl_lock();
+       err = dev_open(netdev);
+       if (err < 0)
+               BT_INFO("iface %s cannot be opened (%d)", netdev->name, err);
+       rtnl_unlock();
+}
+
+static void do_notify_peers(struct work_struct *work)
+{
+       struct lowpan_dev *dev = container_of(work, struct lowpan_dev,
+                                             notify_peers.work);
+
+       netdev_notify_peers(dev->netdev); /* send neighbour adv at startup */
+}
+
+static bool is_bt_6lowpan(struct hci_conn *hcon)
+{
+       if (hcon->type != LE_LINK)
+               return false;
+
+       return test_bit(HCI_CONN_6LOWPAN, &hcon->flags);
+}
+
+static int add_peer_conn(struct l2cap_conn *conn, struct lowpan_dev *dev)
+{
+       struct lowpan_peer *peer;
+       unsigned long flags;
+
+       peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
+       if (!peer)
+               return -ENOMEM;
+
+       peer->conn = conn;
+       memset(&peer->peer_addr, 0, sizeof(struct in6_addr));
+
+       /* RFC 2464 ch. 5 */
+       peer->peer_addr.s6_addr[0] = 0xFE;
+       peer->peer_addr.s6_addr[1] = 0x80;
+       set_addr((u8 *)&peer->peer_addr.s6_addr + 8, conn->hcon->dst.b,
+                conn->hcon->dst_type);
+
+       memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8,
+              EUI64_ADDR_LEN);
+       peer->eui64_addr[0] ^= 2; /* second bit-flip (Universe/Local)
+                                  * is done according RFC2464
+                                  */
+
+       raw_dump_inline(__func__, "peer IPv6 address",
+                       (unsigned char *)&peer->peer_addr, 16);
+       raw_dump_inline(__func__, "peer EUI64 address", peer->eui64_addr, 8);
+
+       write_lock_irqsave(&devices_lock, flags);
+       INIT_LIST_HEAD(&peer->list);
+       peer_add(dev, peer);
+       write_unlock_irqrestore(&devices_lock, flags);
+
+       /* Notifying peers about us needs to be done without locks held */
+       INIT_DELAYED_WORK(&dev->notify_peers, do_notify_peers);
+       schedule_delayed_work(&dev->notify_peers, msecs_to_jiffies(100));
+
+       return 0;
+}
+
+/* This gets called when BT LE 6LoWPAN device is connected. We then
+ * create network device that acts as a proxy between BT LE device
+ * and kernel network stack.
+ */
+int bt_6lowpan_add_conn(struct l2cap_conn *conn)
+{
+       struct lowpan_peer *peer = NULL;
+       struct lowpan_dev *dev;
+       struct net_device *netdev;
+       int err = 0;
+       unsigned long flags;
+
+       if (!is_bt_6lowpan(conn->hcon))
+               return 0;
+
+       peer = lookup_peer(conn);
+       if (peer)
+               return -EEXIST;
+
+       dev = lookup_dev(conn);
+       if (dev)
+               return add_peer_conn(conn, dev);
+
+       netdev = alloc_netdev(sizeof(*dev), IFACE_NAME_TEMPLATE, netdev_setup);
+       if (!netdev)
+               return -ENOMEM;
+
+       set_dev_addr(netdev, &conn->hcon->src, conn->hcon->src_type);
+
+       netdev->netdev_ops = &netdev_ops;
+       SET_NETDEV_DEV(netdev, &conn->hcon->dev);
+       SET_NETDEV_DEVTYPE(netdev, &bt_type);
+
+       err = register_netdev(netdev);
+       if (err < 0) {
+               BT_INFO("register_netdev failed %d", err);
+               free_netdev(netdev);
+               goto out;
+       }
+
+       BT_DBG("ifindex %d peer bdaddr %pMR my addr %pMR",
+              netdev->ifindex, &conn->hcon->dst, &conn->hcon->src);
+       set_bit(__LINK_STATE_PRESENT, &netdev->state);
+
+       dev = netdev_priv(netdev);
+       dev->netdev = netdev;
+       dev->hdev = conn->hcon->hdev;
+       INIT_LIST_HEAD(&dev->peers);
+
+       write_lock_irqsave(&devices_lock, flags);
+       INIT_LIST_HEAD(&dev->list);
+       list_add(&dev->list, &bt_6lowpan_devices);
+       write_unlock_irqrestore(&devices_lock, flags);
+
+       ifup(netdev);
+
+       return add_peer_conn(conn, dev);
+
+out:
+       return err;
+}
+
+static void delete_netdev(struct work_struct *work)
+{
+       struct lowpan_dev *entry = container_of(work, struct lowpan_dev,
+                                               delete_netdev);
+
+       unregister_netdev(entry->netdev);
+
+       /* The entry pointer is deleted in device_event() */
+}
+
+int bt_6lowpan_del_conn(struct l2cap_conn *conn)
+{
+       struct lowpan_dev *entry, *tmp;
+       struct lowpan_dev *dev = NULL;
+       struct lowpan_peer *peer;
+       int err = -ENOENT;
+       unsigned long flags;
+       bool last = false;
+
+       if (!conn || !is_bt_6lowpan(conn->hcon))
+               return 0;
+
+       write_lock_irqsave(&devices_lock, flags);
+
+       list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+               dev = lowpan_dev(entry->netdev);
+               peer = peer_lookup_conn(dev, conn);
+               if (peer) {
+                       last = peer_del(dev, peer);
+                       err = 0;
+                       break;
+               }
+       }
+
+       if (!err && last && dev && !atomic_read(&dev->peer_count)) {
+               write_unlock_irqrestore(&devices_lock, flags);
+
+               cancel_delayed_work_sync(&dev->notify_peers);
+
+               /* bt_6lowpan_del_conn() is called with hci dev lock held which
+                * means that we must delete the netdevice in worker thread.
+                */
+               INIT_WORK(&entry->delete_netdev, delete_netdev);
+               schedule_work(&entry->delete_netdev);
+       } else {
+               write_unlock_irqrestore(&devices_lock, flags);
+       }
+
+       return err;
+}
+
+static int device_event(struct notifier_block *unused,
+                       unsigned long event, void *ptr)
+{
+       struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
+       struct lowpan_dev *entry, *tmp;
+       unsigned long flags;
+
+       if (netdev->type != ARPHRD_6LOWPAN)
+               return NOTIFY_DONE;
+
+       switch (event) {
+       case NETDEV_UNREGISTER:
+               write_lock_irqsave(&devices_lock, flags);
+               list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices,
+                                        list) {
+                       if (entry->netdev == netdev) {
+                               list_del(&entry->list);
+                               kfree(entry);
+                               break;
+                       }
+               }
+               write_unlock_irqrestore(&devices_lock, flags);
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block bt_6lowpan_dev_notifier = {
+       .notifier_call = device_event,
+};
+
+int bt_6lowpan_init(void)
+{
+       return register_netdevice_notifier(&bt_6lowpan_dev_notifier);
+}
+
+void bt_6lowpan_cleanup(void)
+{
+       unregister_netdevice_notifier(&bt_6lowpan_dev_notifier);
+}
diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h
new file mode 100644 (file)
index 0000000..680eac8
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+   Copyright (c) 2013 Intel Corp.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 and
+   only version 2 as published by the Free Software Foundation.
+
+   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 __6LOWPAN_H
+#define __6LOWPAN_H
+
+#include <linux/skbuff.h>
+#include <net/bluetooth/l2cap.h>
+
+int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
+int bt_6lowpan_add_conn(struct l2cap_conn *conn);
+int bt_6lowpan_del_conn(struct l2cap_conn *conn);
+int bt_6lowpan_init(void);
+void bt_6lowpan_cleanup(void);
+
+#endif /* __6LOWPAN_H */
index 6a791e73e39d936f0d9958d506c540c5a2805727..cc6827e2ce68b093be549a1be17b7159b23c1ddc 100644 (file)
@@ -10,6 +10,10 @@ obj-$(CONFIG_BT_HIDP)        += hidp/
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
        hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
-       a2mp.o amp.o
+       a2mp.o amp.o 6lowpan.o
+
+ifeq ($(CONFIG_IEEE802154_6LOWPAN),)
+  bluetooth-y +=  ../ieee802154/6lowpan_iphc.o
+endif
 
 subdir-ccflags-y += -D__CHECK_ENDIAN__
index 8b8b5f80dd89e2aaa6a9e3bb67f0ad5f371eae1d..5e8663c194c18e3c29ab221efe667dd311944294 100644 (file)
@@ -636,6 +636,49 @@ static int conn_max_interval_get(void *data, u64 *val)
 DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get,
                        conn_max_interval_set, "%llu\n");
 
+static ssize_t lowpan_read(struct file *file, char __user *user_buf,
+                          size_t count, loff_t *ppos)
+{
+       struct hci_dev *hdev = file->private_data;
+       char buf[3];
+
+       buf[0] = test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags) ? 'Y' : 'N';
+       buf[1] = '\n';
+       buf[2] = '\0';
+       return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t lowpan_write(struct file *fp, const char __user *user_buffer,
+                           size_t count, loff_t *position)
+{
+       struct hci_dev *hdev = fp->private_data;
+       bool enable;
+       char buf[32];
+       size_t buf_size = min(count, (sizeof(buf)-1));
+
+       if (copy_from_user(buf, user_buffer, buf_size))
+               return -EFAULT;
+
+       buf[buf_size] = '\0';
+
+       if (strtobool(buf, &enable) < 0)
+               return -EINVAL;
+
+       if (enable == test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
+               return -EALREADY;
+
+       change_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags);
+
+       return count;
+}
+
+static const struct file_operations lowpan_debugfs_fops = {
+       .open           = simple_open,
+       .read           = lowpan_read,
+       .write          = lowpan_write,
+       .llseek         = default_llseek,
+};
+
 /* ---- HCI requests ---- */
 
 static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
@@ -1261,8 +1304,13 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
         * as supported send it. If not supported assume that the controller
         * does not have actual support for stored link keys which makes this
         * command redundant anyway.
+        *
+        * Some controllers indicate that they support handling deleting
+        * stored link keys, but they don't. The quirk lets a driver
+        * just disable this command.
         */
-       if (hdev->commands[6] & 0x80) {
+       if (hdev->commands[6] & 0x80 &&
+           !test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) {
                struct hci_cp_delete_stored_link_key cp;
 
                bacpy(&cp.bdaddr, BDADDR_ANY);
@@ -1406,6 +1454,8 @@ static int __hci_init(struct hci_dev *hdev)
                                    hdev, &conn_min_interval_fops);
                debugfs_create_file("conn_max_interval", 0644, hdev->debugfs,
                                    hdev, &conn_max_interval_fops);
+               debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev,
+                                   &lowpan_debugfs_fops);
        }
 
        return 0;
index 5fb3df66c2cd5bda5b0ba7fa6cfda11565dbcde3..5f812455a4504260927cb2dd5a3bdc018e0e20d4 100644 (file)
@@ -3533,6 +3533,9 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
        conn->handle = __le16_to_cpu(ev->handle);
        conn->state = BT_CONNECTED;
 
+       if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
+               set_bit(HCI_CONN_6LOWPAN, &conn->flags);
+
        hci_conn_add_sysfs(conn);
 
        hci_proto_connect_cfm(conn, ev->status);
index 6a6c8bb4fd72d4f2d4294b9f7fed772d81e57b93..7552f9e3089ce790040268f1ce0a067d6ef728cb 100644 (file)
@@ -940,8 +940,22 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
        skb_pull(skb, 1);
 
-       if (hci_pi(sk)->channel == HCI_CHANNEL_RAW &&
-           bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
+       if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
+               /* No permission check is needed for user channel
+                * since that gets enforced when binding the socket.
+                *
+                * However check that the packet type is valid.
+                */
+               if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
+                       err = -EINVAL;
+                       goto drop;
+               }
+
+               skb_queue_tail(&hdev->raw_q, skb);
+               queue_work(hdev->workqueue, &hdev->tx_work);
+       } else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
                u16 opcode = get_unaligned_le16(skb->data);
                u16 ogf = hci_opcode_ogf(opcode);
                u16 ocf = hci_opcode_ocf(opcode);
@@ -972,14 +986,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                        goto drop;
                }
 
-               if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
-                   bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
-                       err = -EINVAL;
-                       goto drop;
-               }
-
                skb_queue_tail(&hdev->raw_q, skb);
                queue_work(hdev->workqueue, &hdev->tx_work);
        }
index b6bca64b320d23ba786573598174e7d0a8b73d32..b0ad2c752d738039cff8ec32c028dd109a10388b 100644 (file)
@@ -40,6 +40,7 @@
 #include "smp.h"
 #include "a2mp.h"
 #include "amp.h"
+#include "6lowpan.h"
 
 bool disable_ertm;
 
@@ -1468,6 +1469,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
        BT_DBG("");
 
+       bt_6lowpan_add_conn(conn);
+
        /* Check if we have socket listening on cid */
        pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
                                          &hcon->src, &hcon->dst);
@@ -7119,6 +7122,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
                        l2cap_conn_del(conn->hcon, EACCES);
                break;
 
+       case L2CAP_FC_6LOWPAN:
+               bt_6lowpan_recv(conn, skb);
+               break;
+
        default:
                l2cap_data_channel(conn, cid, skb);
                break;
@@ -7186,6 +7193,8 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
 {
        BT_DBG("hcon %p reason %d", hcon, reason);
 
+       bt_6lowpan_del_conn(hcon->l2cap_data);
+
        l2cap_conn_del(hcon, bt_to_errno(reason));
 }
 
@@ -7467,11 +7476,14 @@ int __init l2cap_init(void)
        debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs,
                           &le_default_mps);
 
+       bt_6lowpan_init();
+
        return 0;
 }
 
 void l2cap_exit(void)
 {
+       bt_6lowpan_cleanup();
        debugfs_remove(l2cap_debugfs);
        l2cap_cleanup_sockets();
 }
index e7806e6d282c29af9c64f92aaee4632b50a6c8b6..20ef748b290602c0156833970193f490800e429a 100644 (file)
@@ -147,6 +147,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
                    __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM)
                        chan->sec_level = BT_SECURITY_SDP;
                break;
+       case L2CAP_CHAN_RAW:
+               chan->sec_level = BT_SECURITY_SDP;
+               break;
        }
 
        bacpy(&chan->src, &la.l2_bdaddr);
index 84fcf9fff3ea52e4235b7e478deb487fb075b53c..f9c0980abeeac9eaf1d94d70f3e001fd6e1f0870 100644 (file)
@@ -58,6 +58,7 @@ struct rfcomm_dev {
        uint                    modem_status;
 
        struct rfcomm_dlc       *dlc;
+       wait_queue_head_t       conn_wait;
 
        struct device           *tty_dev;
 
@@ -103,20 +104,60 @@ static void rfcomm_dev_destruct(struct tty_port *port)
        module_put(THIS_MODULE);
 }
 
-/* device-specific initialization: open the dlc */
-static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
+static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
 {
-       struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
+       struct hci_dev *hdev;
+       struct hci_conn *conn;
 
-       return rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
+       hdev = hci_get_route(&dev->dst, &dev->src);
+       if (!hdev)
+               return NULL;
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
+
+       hci_dev_put(hdev);
+
+       return conn ? &conn->dev : NULL;
 }
 
-/* we block the open until the dlc->state becomes BT_CONNECTED */
-static int rfcomm_dev_carrier_raised(struct tty_port *port)
+/* device-specific initialization: open the dlc */
+static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
 {
        struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
+       DEFINE_WAIT(wait);
+       int err;
+
+       err = rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
+       if (err)
+               return err;
+
+       while (1) {
+               prepare_to_wait(&dev->conn_wait, &wait, TASK_INTERRUPTIBLE);
+
+               if (dev->dlc->state == BT_CLOSED) {
+                       err = -dev->err;
+                       break;
+               }
+
+               if (dev->dlc->state == BT_CONNECTED)
+                       break;
+
+               if (signal_pending(current)) {
+                       err = -ERESTARTSYS;
+                       break;
+               }
+
+               tty_unlock(tty);
+               schedule();
+               tty_lock(tty);
+       }
+       finish_wait(&dev->conn_wait, &wait);
+
+       if (!err)
+               device_move(dev->tty_dev, rfcomm_get_device(dev),
+                           DPM_ORDER_DEV_AFTER_PARENT);
 
-       return (dev->dlc->state == BT_CONNECTED);
+       return err;
 }
 
 /* device-specific cleanup: close the dlc */
@@ -135,7 +176,6 @@ static const struct tty_port_operations rfcomm_port_ops = {
        .destruct = rfcomm_dev_destruct,
        .activate = rfcomm_dev_activate,
        .shutdown = rfcomm_dev_shutdown,
-       .carrier_raised = rfcomm_dev_carrier_raised,
 };
 
 static struct rfcomm_dev *__rfcomm_dev_get(int id)
@@ -169,22 +209,6 @@ static struct rfcomm_dev *rfcomm_dev_get(int id)
        return dev;
 }
 
-static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
-{
-       struct hci_dev *hdev;
-       struct hci_conn *conn;
-
-       hdev = hci_get_route(&dev->dst, &dev->src);
-       if (!hdev)
-               return NULL;
-
-       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
-
-       hci_dev_put(hdev);
-
-       return conn ? &conn->dev : NULL;
-}
-
 static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
 {
        struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
@@ -258,6 +282,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
 
        tty_port_init(&dev->port);
        dev->port.ops = &rfcomm_port_ops;
+       init_waitqueue_head(&dev->conn_wait);
 
        skb_queue_head_init(&dev->pending);
 
@@ -437,7 +462,8 @@ static int rfcomm_release_dev(void __user *arg)
                tty_kref_put(tty);
        }
 
-       if (!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+       if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
+           !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
                tty_port_put(&dev->port);
 
        tty_port_put(&dev->port);
@@ -575,12 +601,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
        BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
 
        dev->err = err;
-       if (dlc->state == BT_CONNECTED) {
-               device_move(dev->tty_dev, rfcomm_get_device(dev),
-                           DPM_ORDER_DEV_AFTER_PARENT);
+       wake_up_interruptible(&dev->conn_wait);
 
-               wake_up_interruptible(&dev->port.open_wait);
-       } else if (dlc->state == BT_CLOSED)
+       if (dlc->state == BT_CLOSED)
                tty_port_tty_hangup(&dev->port, false);
 }
 
@@ -670,10 +693,20 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
 
        /* install the tty_port */
        err = tty_port_install(&dev->port, driver, tty);
-       if (err)
+       if (err) {
                rfcomm_tty_cleanup(tty);
+               return err;
+       }
 
-       return err;
+       /* take over the tty_port reference if the port was created with the
+        * flag RFCOMM_RELEASE_ONHUP. This will force the release of the port
+        * when the last process closes the tty. The behaviour is expected by
+        * userspace.
+        */
+       if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
+               tty_port_put(&dev->port);
+
+       return 0;
 }
 
 static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
@@ -1010,10 +1043,6 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
        BT_DBG("tty %p dev %p", tty, dev);
 
        tty_port_hangup(&dev->port);
-
-       if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
-           !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
-               tty_port_put(&dev->port);
 }
 
 static int rfcomm_tty_tiocmget(struct tty_struct *tty)
@@ -1096,7 +1125,7 @@ int __init rfcomm_init_ttys(void)
        rfcomm_tty_driver->subtype      = SERIAL_TYPE_NORMAL;
        rfcomm_tty_driver->flags        = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        rfcomm_tty_driver->init_termios = tty_std_termios;
-       rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+       rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
        rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
        tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
 
index f00cfd2a0143e0e8868ca808cb6a236bb1124e3c..e4401a531afbd4bc1b22819282ff1a6d1b539bb0 100644 (file)
@@ -32,7 +32,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        const unsigned char *dest = skb->data;
        struct net_bridge_fdb_entry *dst;
        struct net_bridge_mdb_entry *mdst;
-       struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
+       struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats);
        u16 vid = 0;
 
        rcu_read_lock();
@@ -90,12 +90,12 @@ static int br_dev_init(struct net_device *dev)
        struct net_bridge *br = netdev_priv(dev);
        int i;
 
-       br->stats = alloc_percpu(struct br_cpu_netstats);
+       br->stats = alloc_percpu(struct pcpu_sw_netstats);
        if (!br->stats)
                return -ENOMEM;
 
        for_each_possible_cpu(i) {
-               struct br_cpu_netstats *br_dev_stats;
+               struct pcpu_sw_netstats *br_dev_stats;
                br_dev_stats = per_cpu_ptr(br->stats, i);
                u64_stats_init(&br_dev_stats->syncp);
        }
@@ -135,12 +135,12 @@ static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev,
                                                struct rtnl_link_stats64 *stats)
 {
        struct net_bridge *br = netdev_priv(dev);
-       struct br_cpu_netstats tmp, sum = { 0 };
+       struct pcpu_sw_netstats tmp, sum = { 0 };
        unsigned int cpu;
 
        for_each_possible_cpu(cpu) {
                unsigned int start;
-               const struct br_cpu_netstats *bstats
+               const struct pcpu_sw_netstats *bstats
                        = per_cpu_ptr(br->stats, cpu);
                do {
                        start = u64_stats_fetch_begin_bh(&bstats->syncp);
index 7e73c32e205d10517595395ed2bed91ab48868b9..bf8dc7d308d6d0b0a092d080723118d327a19b10 100644 (file)
@@ -28,7 +28,7 @@ static int br_pass_frame_up(struct sk_buff *skb)
 {
        struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
        struct net_bridge *br = netdev_priv(brdev);
-       struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
+       struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats);
 
        u64_stats_update_begin(&brstats->syncp);
        brstats->rx_packets++;
index 4c214b2b88efa01d81be93a8b8d77e57229c1fa4..ef66365b7354da9f2fe2c4d87d2056d9a781f3c8 100644 (file)
@@ -1998,7 +1998,7 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
        u32 old;
        struct net_bridge_mdb_htable *mdb;
 
-       spin_lock(&br->multicast_lock);
+       spin_lock_bh(&br->multicast_lock);
        if (!netif_running(br->dev))
                goto unlock;
 
@@ -2030,7 +2030,7 @@ rollback:
        }
 
 unlock:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock_bh(&br->multicast_lock);
 
        return err;
 }
index 6526ac89bbfa8f2ebf5532a55b662d4eb714b22e..e74b6d530cb6a3ab3dc650ee1900df06d3b3441a 100644 (file)
@@ -481,9 +481,7 @@ int __init br_netlink_init(void)
        int err;
 
        br_mdb_init();
-       err = rtnl_af_register(&br_af_ops);
-       if (err)
-               goto out;
+       rtnl_af_register(&br_af_ops);
 
        err = rtnl_link_register(&br_link_ops);
        if (err)
@@ -493,7 +491,6 @@ int __init br_netlink_init(void)
 
 out_af:
        rtnl_af_unregister(&br_af_ops);
-out:
        br_mdb_uninit();
        return err;
 }
index 2e77d923c8ee3a9943ed356362b5c8712227d4ff..3733f152351c2eedcea3f63a1d35499a0c618a1f 100644 (file)
@@ -210,21 +210,13 @@ static inline struct net_bridge_port *br_port_get_rtnl(const struct net_device *
                rtnl_dereference(dev->rx_handler_data) : NULL;
 }
 
-struct br_cpu_netstats {
-       u64                     rx_packets;
-       u64                     rx_bytes;
-       u64                     tx_packets;
-       u64                     tx_bytes;
-       struct u64_stats_sync   syncp;
-};
-
 struct net_bridge
 {
        spinlock_t                      lock;
        struct list_head                port_list;
        struct net_device               *dev;
 
-       struct br_cpu_netstats __percpu *stats;
+       struct pcpu_sw_netstats         __percpu *stats;
        spinlock_t                      hash_lock;
        struct hlist_head               hash[BR_HASH_SIZE];
 #ifdef CONFIG_BRIDGE_NETFILTER
index 3b9637fb7939a146e8a172a1e009e84c6ca4e841..8dac65552f1901817489421c2042553a663cbaf9 100644 (file)
@@ -49,53 +49,51 @@ static ssize_t store_bridge_parm(struct device *d,
 }
 
 
-static ssize_t show_forward_delay(struct device *d,
+static ssize_t forward_delay_show(struct device *d,
                                  struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
 }
 
-static ssize_t store_forward_delay(struct device *d,
+static ssize_t forward_delay_store(struct device *d,
                                   struct device_attribute *attr,
                                   const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, br_set_forward_delay);
 }
-static DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
-                  show_forward_delay, store_forward_delay);
+static DEVICE_ATTR_RW(forward_delay);
 
-static ssize_t show_hello_time(struct device *d, struct device_attribute *attr,
+static ssize_t hello_time_show(struct device *d, struct device_attribute *attr,
                               char *buf)
 {
        return sprintf(buf, "%lu\n",
                       jiffies_to_clock_t(to_bridge(d)->hello_time));
 }
 
-static ssize_t store_hello_time(struct device *d,
+static ssize_t hello_time_store(struct device *d,
                                struct device_attribute *attr, const char *buf,
                                size_t len)
 {
        return store_bridge_parm(d, buf, len, br_set_hello_time);
 }
-static DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
-                  store_hello_time);
+static DEVICE_ATTR_RW(hello_time);
 
-static ssize_t show_max_age(struct device *d, struct device_attribute *attr,
+static ssize_t max_age_show(struct device *d, struct device_attribute *attr,
                            char *buf)
 {
        return sprintf(buf, "%lu\n",
                       jiffies_to_clock_t(to_bridge(d)->max_age));
 }
 
-static ssize_t store_max_age(struct device *d, struct device_attribute *attr,
+static ssize_t max_age_store(struct device *d, struct device_attribute *attr,
                             const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, br_set_max_age);
 }
-static DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age);
+static DEVICE_ATTR_RW(max_age);
 
-static ssize_t show_ageing_time(struct device *d,
+static ssize_t ageing_time_show(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -108,16 +106,15 @@ static int set_ageing_time(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_ageing_time(struct device *d,
+static ssize_t ageing_time_store(struct device *d,
                                 struct device_attribute *attr,
                                 const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, set_ageing_time);
 }
-static DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
-                  store_ageing_time);
+static DEVICE_ATTR_RW(ageing_time);
 
-static ssize_t show_stp_state(struct device *d,
+static ssize_t stp_state_show(struct device *d,
                              struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -125,7 +122,7 @@ static ssize_t show_stp_state(struct device *d,
 }
 
 
-static ssize_t store_stp_state(struct device *d,
+static ssize_t stp_state_store(struct device *d,
                               struct device_attribute *attr, const char *buf,
                               size_t len)
 {
@@ -147,20 +144,21 @@ static ssize_t store_stp_state(struct device *d,
 
        return len;
 }
-static DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
-                  store_stp_state);
+static DEVICE_ATTR_RW(stp_state);
 
-static ssize_t show_group_fwd_mask(struct device *d,
-                             struct device_attribute *attr, char *buf)
+static ssize_t group_fwd_mask_show(struct device *d,
+                                  struct device_attribute *attr,
+                                  char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%#x\n", br->group_fwd_mask);
 }
 
 
-static ssize_t store_group_fwd_mask(struct device *d,
-                              struct device_attribute *attr, const char *buf,
-                              size_t len)
+static ssize_t group_fwd_mask_store(struct device *d,
+                                   struct device_attribute *attr,
+                                   const char *buf,
+                                   size_t len)
 {
        struct net_bridge *br = to_bridge(d);
        char *endp;
@@ -180,10 +178,9 @@ static ssize_t store_group_fwd_mask(struct device *d,
 
        return len;
 }
-static DEVICE_ATTR(group_fwd_mask, S_IRUGO | S_IWUSR, show_group_fwd_mask,
-                  store_group_fwd_mask);
+static DEVICE_ATTR_RW(group_fwd_mask);
 
-static ssize_t show_priority(struct device *d, struct device_attribute *attr,
+static ssize_t priority_show(struct device *d, struct device_attribute *attr,
                             char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -197,93 +194,91 @@ static int set_priority(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_priority(struct device *d, struct device_attribute *attr,
-                              const char *buf, size_t len)
+static ssize_t priority_store(struct device *d, struct device_attribute *attr,
+                             const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, set_priority);
 }
-static DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority);
+static DEVICE_ATTR_RW(priority);
 
-static ssize_t show_root_id(struct device *d, struct device_attribute *attr,
+static ssize_t root_id_show(struct device *d, struct device_attribute *attr,
                            char *buf)
 {
        return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
 }
-static DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
+static DEVICE_ATTR_RO(root_id);
 
-static ssize_t show_bridge_id(struct device *d, struct device_attribute *attr,
+static ssize_t bridge_id_show(struct device *d, struct device_attribute *attr,
                              char *buf)
 {
        return br_show_bridge_id(buf, &to_bridge(d)->bridge_id);
 }
-static DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
+static DEVICE_ATTR_RO(bridge_id);
 
-static ssize_t show_root_port(struct device *d, struct device_attribute *attr,
+static ssize_t root_port_show(struct device *d, struct device_attribute *attr,
                              char *buf)
 {
        return sprintf(buf, "%d\n", to_bridge(d)->root_port);
 }
-static DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
+static DEVICE_ATTR_RO(root_port);
 
-static ssize_t show_root_path_cost(struct device *d,
+static ssize_t root_path_cost_show(struct device *d,
                                   struct device_attribute *attr, char *buf)
 {
        return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost);
 }
-static DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
+static DEVICE_ATTR_RO(root_path_cost);
 
-static ssize_t show_topology_change(struct device *d,
+static ssize_t topology_change_show(struct device *d,
                                    struct device_attribute *attr, char *buf)
 {
        return sprintf(buf, "%d\n", to_bridge(d)->topology_change);
 }
-static DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
+static DEVICE_ATTR_RO(topology_change);
 
-static ssize_t show_topology_change_detected(struct device *d,
+static ssize_t topology_change_detected_show(struct device *d,
                                             struct device_attribute *attr,
                                             char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%d\n", br->topology_change_detected);
 }
-static DEVICE_ATTR(topology_change_detected, S_IRUGO,
-                  show_topology_change_detected, NULL);
+static DEVICE_ATTR_RO(topology_change_detected);
 
-static ssize_t show_hello_timer(struct device *d,
+static ssize_t hello_timer_show(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer));
 }
-static DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
+static DEVICE_ATTR_RO(hello_timer);
 
-static ssize_t show_tcn_timer(struct device *d, struct device_attribute *attr,
+static ssize_t tcn_timer_show(struct device *d, struct device_attribute *attr,
                              char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer));
 }
-static DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
+static DEVICE_ATTR_RO(tcn_timer);
 
-static ssize_t show_topology_change_timer(struct device *d,
+static ssize_t topology_change_timer_show(struct device *d,
                                          struct device_attribute *attr,
                                          char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer));
 }
-static DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer,
-                  NULL);
+static DEVICE_ATTR_RO(topology_change_timer);
 
-static ssize_t show_gc_timer(struct device *d, struct device_attribute *attr,
+static ssize_t gc_timer_show(struct device *d, struct device_attribute *attr,
                             char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%ld\n", br_timer_value(&br->gc_timer));
 }
-static DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
+static DEVICE_ATTR_RO(gc_timer);
 
-static ssize_t show_group_addr(struct device *d,
+static ssize_t group_addr_show(struct device *d,
                               struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -293,7 +288,7 @@ static ssize_t show_group_addr(struct device *d,
                       br->group_addr[4], br->group_addr[5]);
 }
 
-static ssize_t store_group_addr(struct device *d,
+static ssize_t group_addr_store(struct device *d,
                                struct device_attribute *attr,
                                const char *buf, size_t len)
 {
@@ -324,10 +319,9 @@ static ssize_t store_group_addr(struct device *d,
        return len;
 }
 
-static DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR,
-                  show_group_addr, store_group_addr);
+static DEVICE_ATTR_RW(group_addr);
 
-static ssize_t store_flush(struct device *d,
+static ssize_t flush_store(struct device *d,
                           struct device_attribute *attr,
                           const char *buf, size_t len)
 {
@@ -339,26 +333,25 @@ static ssize_t store_flush(struct device *d,
        br_fdb_flush(br);
        return len;
 }
-static DEVICE_ATTR(flush, S_IWUSR, NULL, store_flush);
+static DEVICE_ATTR_WO(flush);
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
-static ssize_t show_multicast_router(struct device *d,
+static ssize_t multicast_router_show(struct device *d,
                                     struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%d\n", br->multicast_router);
 }
 
-static ssize_t store_multicast_router(struct device *d,
+static ssize_t multicast_router_store(struct device *d,
                                      struct device_attribute *attr,
                                      const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, br_multicast_set_router);
 }
-static DEVICE_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
-                  store_multicast_router);
+static DEVICE_ATTR_RW(multicast_router);
 
-static ssize_t show_multicast_snooping(struct device *d,
+static ssize_t multicast_snooping_show(struct device *d,
                                       struct device_attribute *attr,
                                       char *buf)
 {
@@ -366,18 +359,17 @@ static ssize_t show_multicast_snooping(struct device *d,
        return sprintf(buf, "%d\n", !br->multicast_disabled);
 }
 
-static ssize_t store_multicast_snooping(struct device *d,
+static ssize_t multicast_snooping_store(struct device *d,
                                        struct device_attribute *attr,
                                        const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, br_multicast_toggle);
 }
-static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR,
-                  show_multicast_snooping, store_multicast_snooping);
+static DEVICE_ATTR_RW(multicast_snooping);
 
-static ssize_t show_multicast_query_use_ifaddr(struct device *d,
-                                     struct device_attribute *attr,
-                                     char *buf)
+static ssize_t multicast_query_use_ifaddr_show(struct device *d,
+                                              struct device_attribute *attr,
+                                              char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%d\n", br->multicast_query_use_ifaddr);
@@ -390,17 +382,15 @@ static int set_query_use_ifaddr(struct net_bridge *br, unsigned long val)
 }
 
 static ssize_t
-store_multicast_query_use_ifaddr(struct device *d,
+multicast_query_use_ifaddr_store(struct device *d,
                                 struct device_attribute *attr,
                                 const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, set_query_use_ifaddr);
 }
-static DEVICE_ATTR(multicast_query_use_ifaddr, S_IRUGO | S_IWUSR,
-                  show_multicast_query_use_ifaddr,
-                  store_multicast_query_use_ifaddr);
+static DEVICE_ATTR_RW(multicast_query_use_ifaddr);
 
-static ssize_t show_multicast_querier(struct device *d,
+static ssize_t multicast_querier_show(struct device *d,
                                      struct device_attribute *attr,
                                      char *buf)
 {
@@ -408,16 +398,15 @@ static ssize_t show_multicast_querier(struct device *d,
        return sprintf(buf, "%d\n", br->multicast_querier);
 }
 
-static ssize_t store_multicast_querier(struct device *d,
+static ssize_t multicast_querier_store(struct device *d,
                                       struct device_attribute *attr,
                                       const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, br_multicast_set_querier);
 }
-static DEVICE_ATTR(multicast_querier, S_IRUGO | S_IWUSR,
-                  show_multicast_querier, store_multicast_querier);
+static DEVICE_ATTR_RW(multicast_querier);
 
-static ssize_t show_hash_elasticity(struct device *d,
+static ssize_t hash_elasticity_show(struct device *d,
                                    struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -430,31 +419,29 @@ static int set_elasticity(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_hash_elasticity(struct device *d,
+static ssize_t hash_elasticity_store(struct device *d,
                                     struct device_attribute *attr,
                                     const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, set_elasticity);
 }
-static DEVICE_ATTR(hash_elasticity, S_IRUGO | S_IWUSR, show_hash_elasticity,
-                  store_hash_elasticity);
+static DEVICE_ATTR_RW(hash_elasticity);
 
-static ssize_t show_hash_max(struct device *d, struct device_attribute *attr,
+static ssize_t hash_max_show(struct device *d, struct device_attribute *attr,
                             char *buf)
 {
        struct net_bridge *br = to_bridge(d);
        return sprintf(buf, "%u\n", br->hash_max);
 }
 
-static ssize_t store_hash_max(struct device *d, struct device_attribute *attr,
+static ssize_t hash_max_store(struct device *d, struct device_attribute *attr,
                              const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, br_multicast_set_hash_max);
 }
-static DEVICE_ATTR(hash_max, S_IRUGO | S_IWUSR, show_hash_max,
-                  store_hash_max);
+static DEVICE_ATTR_RW(hash_max);
 
-static ssize_t show_multicast_last_member_count(struct device *d,
+static ssize_t multicast_last_member_count_show(struct device *d,
                                                struct device_attribute *attr,
                                                char *buf)
 {
@@ -468,17 +455,15 @@ static int set_last_member_count(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_multicast_last_member_count(struct device *d,
+static ssize_t multicast_last_member_count_store(struct device *d,
                                                 struct device_attribute *attr,
                                                 const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, set_last_member_count);
 }
-static DEVICE_ATTR(multicast_last_member_count, S_IRUGO | S_IWUSR,
-                  show_multicast_last_member_count,
-                  store_multicast_last_member_count);
+static DEVICE_ATTR_RW(multicast_last_member_count);
 
-static ssize_t show_multicast_startup_query_count(
+static ssize_t multicast_startup_query_count_show(
        struct device *d, struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -491,17 +476,15 @@ static int set_startup_query_count(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_multicast_startup_query_count(
+static ssize_t multicast_startup_query_count_store(
        struct device *d, struct device_attribute *attr, const char *buf,
        size_t len)
 {
        return store_bridge_parm(d, buf, len, set_startup_query_count);
 }
-static DEVICE_ATTR(multicast_startup_query_count, S_IRUGO | S_IWUSR,
-                  show_multicast_startup_query_count,
-                  store_multicast_startup_query_count);
+static DEVICE_ATTR_RW(multicast_startup_query_count);
 
-static ssize_t show_multicast_last_member_interval(
+static ssize_t multicast_last_member_interval_show(
        struct device *d, struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -515,17 +498,15 @@ static int set_last_member_interval(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_multicast_last_member_interval(
+static ssize_t multicast_last_member_interval_store(
        struct device *d, struct device_attribute *attr, const char *buf,
        size_t len)
 {
        return store_bridge_parm(d, buf, len, set_last_member_interval);
 }
-static DEVICE_ATTR(multicast_last_member_interval, S_IRUGO | S_IWUSR,
-                  show_multicast_last_member_interval,
-                  store_multicast_last_member_interval);
+static DEVICE_ATTR_RW(multicast_last_member_interval);
 
-static ssize_t show_multicast_membership_interval(
+static ssize_t multicast_membership_interval_show(
        struct device *d, struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -539,17 +520,15 @@ static int set_membership_interval(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_multicast_membership_interval(
+static ssize_t multicast_membership_interval_store(
        struct device *d, struct device_attribute *attr, const char *buf,
        size_t len)
 {
        return store_bridge_parm(d, buf, len, set_membership_interval);
 }
-static DEVICE_ATTR(multicast_membership_interval, S_IRUGO | S_IWUSR,
-                  show_multicast_membership_interval,
-                  store_multicast_membership_interval);
+static DEVICE_ATTR_RW(multicast_membership_interval);
 
-static ssize_t show_multicast_querier_interval(struct device *d,
+static ssize_t multicast_querier_interval_show(struct device *d,
                                               struct device_attribute *attr,
                                               char *buf)
 {
@@ -564,17 +543,15 @@ static int set_querier_interval(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_multicast_querier_interval(struct device *d,
+static ssize_t multicast_querier_interval_store(struct device *d,
                                                struct device_attribute *attr,
                                                const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, set_querier_interval);
 }
-static DEVICE_ATTR(multicast_querier_interval, S_IRUGO | S_IWUSR,
-                  show_multicast_querier_interval,
-                  store_multicast_querier_interval);
+static DEVICE_ATTR_RW(multicast_querier_interval);
 
-static ssize_t show_multicast_query_interval(struct device *d,
+static ssize_t multicast_query_interval_show(struct device *d,
                                             struct device_attribute *attr,
                                             char *buf)
 {
@@ -589,17 +566,15 @@ static int set_query_interval(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_multicast_query_interval(struct device *d,
+static ssize_t multicast_query_interval_store(struct device *d,
                                              struct device_attribute *attr,
                                              const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, set_query_interval);
 }
-static DEVICE_ATTR(multicast_query_interval, S_IRUGO | S_IWUSR,
-                  show_multicast_query_interval,
-                  store_multicast_query_interval);
+static DEVICE_ATTR_RW(multicast_query_interval);
 
-static ssize_t show_multicast_query_response_interval(
+static ssize_t multicast_query_response_interval_show(
        struct device *d, struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -614,17 +589,15 @@ static int set_query_response_interval(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_multicast_query_response_interval(
+static ssize_t multicast_query_response_interval_store(
        struct device *d, struct device_attribute *attr, const char *buf,
        size_t len)
 {
        return store_bridge_parm(d, buf, len, set_query_response_interval);
 }
-static DEVICE_ATTR(multicast_query_response_interval, S_IRUGO | S_IWUSR,
-                  show_multicast_query_response_interval,
-                  store_multicast_query_response_interval);
+static DEVICE_ATTR_RW(multicast_query_response_interval);
 
-static ssize_t show_multicast_startup_query_interval(
+static ssize_t multicast_startup_query_interval_show(
        struct device *d, struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -639,18 +612,16 @@ static int set_startup_query_interval(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_multicast_startup_query_interval(
+static ssize_t multicast_startup_query_interval_store(
        struct device *d, struct device_attribute *attr, const char *buf,
        size_t len)
 {
        return store_bridge_parm(d, buf, len, set_startup_query_interval);
 }
-static DEVICE_ATTR(multicast_startup_query_interval, S_IRUGO | S_IWUSR,
-                  show_multicast_startup_query_interval,
-                  store_multicast_startup_query_interval);
+static DEVICE_ATTR_RW(multicast_startup_query_interval);
 #endif
 #ifdef CONFIG_BRIDGE_NETFILTER
-static ssize_t show_nf_call_iptables(
+static ssize_t nf_call_iptables_show(
        struct device *d, struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -663,16 +634,15 @@ static int set_nf_call_iptables(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_nf_call_iptables(
+static ssize_t nf_call_iptables_store(
        struct device *d, struct device_attribute *attr, const char *buf,
        size_t len)
 {
        return store_bridge_parm(d, buf, len, set_nf_call_iptables);
 }
-static DEVICE_ATTR(nf_call_iptables, S_IRUGO | S_IWUSR,
-                  show_nf_call_iptables, store_nf_call_iptables);
+static DEVICE_ATTR_RW(nf_call_iptables);
 
-static ssize_t show_nf_call_ip6tables(
+static ssize_t nf_call_ip6tables_show(
        struct device *d, struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -685,16 +655,15 @@ static int set_nf_call_ip6tables(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_nf_call_ip6tables(
+static ssize_t nf_call_ip6tables_store(
        struct device *d, struct device_attribute *attr, const char *buf,
        size_t len)
 {
        return store_bridge_parm(d, buf, len, set_nf_call_ip6tables);
 }
-static DEVICE_ATTR(nf_call_ip6tables, S_IRUGO | S_IWUSR,
-                  show_nf_call_ip6tables, store_nf_call_ip6tables);
+static DEVICE_ATTR_RW(nf_call_ip6tables);
 
-static ssize_t show_nf_call_arptables(
+static ssize_t nf_call_arptables_show(
        struct device *d, struct device_attribute *attr, char *buf)
 {
        struct net_bridge *br = to_bridge(d);
@@ -707,17 +676,16 @@ static int set_nf_call_arptables(struct net_bridge *br, unsigned long val)
        return 0;
 }
 
-static ssize_t store_nf_call_arptables(
+static ssize_t nf_call_arptables_store(
        struct device *d, struct device_attribute *attr, const char *buf,
        size_t len)
 {
        return store_bridge_parm(d, buf, len, set_nf_call_arptables);
 }
-static DEVICE_ATTR(nf_call_arptables, S_IRUGO | S_IWUSR,
-                  show_nf_call_arptables, store_nf_call_arptables);
+static DEVICE_ATTR_RW(nf_call_arptables);
 #endif
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
-static ssize_t show_vlan_filtering(struct device *d,
+static ssize_t vlan_filtering_show(struct device *d,
                                   struct device_attribute *attr,
                                   char *buf)
 {
@@ -725,14 +693,13 @@ static ssize_t show_vlan_filtering(struct device *d,
        return sprintf(buf, "%d\n", br->vlan_enabled);
 }
 
-static ssize_t store_vlan_filtering(struct device *d,
+static ssize_t vlan_filtering_store(struct device *d,
                                    struct device_attribute *attr,
                                    const char *buf, size_t len)
 {
        return store_bridge_parm(d, buf, len, br_vlan_filter_toggle);
 }
-static DEVICE_ATTR(vlan_filtering, S_IRUGO | S_IWUSR,
-                  show_vlan_filtering, store_vlan_filtering);
+static DEVICE_ATTR_RW(vlan_filtering);
 #endif
 
 static struct attribute *bridge_attrs[] = {
index cf54b22818c889172b9207fcc2f3898c454c37e3..5bcc0d8b31f22dff5b0368a77ae249f60e4bad9e 100644 (file)
 #include <linux/netfilter_bridge.h>
 #include <net/netfilter/nf_tables.h>
 
+static unsigned int
+nft_do_chain_bridge(const struct nf_hook_ops *ops,
+                   struct sk_buff *skb,
+                   const struct net_device *in,
+                   const struct net_device *out,
+                   int (*okfn)(struct sk_buff *))
+{
+       struct nft_pktinfo pkt;
+
+       nft_set_pktinfo(&pkt, ops, skb, in, out);
+
+       return nft_do_chain(&pkt, ops);
+}
+
 static struct nft_af_info nft_af_bridge __read_mostly = {
        .family         = NFPROTO_BRIDGE,
        .nhooks         = NF_BR_NUMHOOKS,
        .owner          = THIS_MODULE,
+       .nops           = 1,
+       .hooks          = {
+               [NF_BR_LOCAL_IN]        = nft_do_chain_bridge,
+               [NF_BR_FORWARD]         = nft_do_chain_bridge,
+               [NF_BR_LOCAL_OUT]       = nft_do_chain_bridge,
+       },
 };
 
 static int nf_tables_bridge_init_net(struct net *net)
@@ -48,32 +68,14 @@ static struct pernet_operations nf_tables_bridge_net_ops = {
        .exit   = nf_tables_bridge_exit_net,
 };
 
-static unsigned int
-nft_do_chain_bridge(const struct nf_hook_ops *ops,
-                   struct sk_buff *skb,
-                   const struct net_device *in,
-                   const struct net_device *out,
-                   int (*okfn)(struct sk_buff *))
-{
-       struct nft_pktinfo pkt;
-
-       nft_set_pktinfo(&pkt, ops, skb, in, out);
-
-       return nft_do_chain_pktinfo(&pkt, ops);
-}
-
-static struct nf_chain_type filter_bridge = {
-       .family         = NFPROTO_BRIDGE,
+static const struct nf_chain_type filter_bridge = {
        .name           = "filter",
        .type           = NFT_CHAIN_T_DEFAULT,
+       .family         = NFPROTO_BRIDGE,
+       .owner          = THIS_MODULE,
        .hook_mask      = (1 << NF_BR_LOCAL_IN) |
                          (1 << NF_BR_FORWARD) |
                          (1 << NF_BR_LOCAL_OUT),
-       .fn             = {
-               [NF_BR_LOCAL_IN]        = nft_do_chain_bridge,
-               [NF_BR_FORWARD]         = nft_do_chain_bridge,
-               [NF_BR_LOCAL_OUT]       = nft_do_chain_bridge,
-       },
 };
 
 static int __init nf_tables_bridge_init(void)
index 3f9b0f3a281876e7d8ec7de0366ed98712759aad..88c8a39c173df1e16c2b14f0a027910a241c2ca1 100644 (file)
@@ -844,8 +844,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh)
        if (!gwj->src.dev)
                goto out;
 
-       /* check for CAN netdev not using header_ops - see gw_rcv() */
-       if (gwj->src.dev->type != ARPHRD_CAN || gwj->src.dev->header_ops)
+       if (gwj->src.dev->type != ARPHRD_CAN)
                goto put_src_out;
 
        gwj->dst.dev = dev_get_by_index(&init_net, gwj->ccgw.dst_idx);
@@ -853,8 +852,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh)
        if (!gwj->dst.dev)
                goto put_src_out;
 
-       /* check for CAN netdev not using header_ops - see gw_rcv() */
-       if (gwj->dst.dev->type != ARPHRD_CAN || gwj->dst.dev->header_ops)
+       if (gwj->dst.dev->type != ARPHRD_CAN)
                goto put_src_dst_out;
 
        gwj->limit_hops = limhops;
index b33b996f5dd695f1c51498fedd7a1fe5aa368607..9628c20acff682f7967ebddc1bdbd94cfb2a4bed 100644 (file)
@@ -21,4 +21,5 @@ obj-$(CONFIG_FIB_RULES) += fib_rules.o
 obj-$(CONFIG_TRACEPOINTS) += net-traces.o
 obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o
 obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o
-obj-$(CONFIG_NETPRIO_CGROUP) += netprio_cgroup.o
+obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
+obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
index c482fe8abf8768e54ebfa9642731216540112090..87312dcf0aa848412f200e00f5bab26433b8b080 100644 (file)
@@ -480,7 +480,7 @@ EXPORT_SYMBOL(dev_add_offload);
  *     and must not be freed until after all the CPU's have gone
  *     through a quiescent state.
  */
-void __dev_remove_offload(struct packet_offload *po)
+static void __dev_remove_offload(struct packet_offload *po)
 {
        struct list_head *head = &offload_base;
        struct packet_offload *po1;
@@ -498,7 +498,6 @@ void __dev_remove_offload(struct packet_offload *po)
 out:
        spin_unlock(&offload_lock);
 }
-EXPORT_SYMBOL(__dev_remove_offload);
 
 /**
  *     dev_remove_offload       - remove packet offload handler
@@ -1566,14 +1565,14 @@ EXPORT_SYMBOL(unregister_netdevice_notifier);
  *     are as for raw_notifier_call_chain().
  */
 
-int call_netdevice_notifiers_info(unsigned long val, struct net_device *dev,
-                                 struct netdev_notifier_info *info)
+static int call_netdevice_notifiers_info(unsigned long val,
+                                        struct net_device *dev,
+                                        struct netdev_notifier_info *info)
 {
        ASSERT_RTNL();
        netdev_notifier_info_init(info, dev);
        return raw_notifier_call_chain(&netdev_chain, val, info);
 }
-EXPORT_SYMBOL(call_netdevice_notifiers_info);
 
 /**
  *     call_netdevice_notifiers - call all network notifier blocks
@@ -2454,13 +2453,8 @@ static void dev_gso_skb_destructor(struct sk_buff *skb)
 {
        struct dev_gso_cb *cb;
 
-       do {
-               struct sk_buff *nskb = skb->next;
-
-               skb->next = nskb->next;
-               nskb->next = NULL;
-               kfree_skb(nskb);
-       } while (skb->next);
+       kfree_skb_list(skb->next);
+       skb->next = NULL;
 
        cb = DEV_GSO_CB(skb);
        if (cb->destructor)
@@ -2747,7 +2741,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
        return rc;
 }
 
-#if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
+#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
 static void skb_update_prio(struct sk_buff *skb)
 {
        struct netprio_map *map = rcu_dereference_bh(skb->dev->priomap);
@@ -3852,6 +3846,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
 
        skb_gro_reset_offset(skb);
        gro_list_prepare(napi, skb);
+       NAPI_GRO_CB(skb)->csum = skb->csum; /* Needed for CHECKSUM_COMPLETE */
 
        rcu_read_lock();
        list_for_each_entry_rcu(ptype, head, list) {
@@ -3887,10 +3882,23 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        if (same_flow)
                goto ok;
 
-       if (NAPI_GRO_CB(skb)->flush || napi->gro_count >= MAX_GRO_SKBS)
+       if (NAPI_GRO_CB(skb)->flush)
                goto normal;
 
-       napi->gro_count++;
+       if (unlikely(napi->gro_count >= MAX_GRO_SKBS)) {
+               struct sk_buff *nskb = napi->gro_list;
+
+               /* locate the end of the list to select the 'oldest' flow */
+               while (nskb->next) {
+                       pp = &nskb->next;
+                       nskb = *pp;
+               }
+               *pp = NULL;
+               nskb->next = NULL;
+               napi_gro_complete(nskb);
+       } else {
+               napi->gro_count++;
+       }
        NAPI_GRO_CB(skb)->count = 1;
        NAPI_GRO_CB(skb)->age = jiffies;
        skb_shinfo(skb)->gso_size = skb_gro_len(skb);
@@ -3928,6 +3936,31 @@ normal:
        goto pull;
 }
 
+struct packet_offload *gro_find_receive_by_type(__be16 type)
+{
+       struct list_head *offload_head = &offload_base;
+       struct packet_offload *ptype;
+
+       list_for_each_entry_rcu(ptype, offload_head, list) {
+               if (ptype->type != type || !ptype->callbacks.gro_receive)
+                       continue;
+               return ptype;
+       }
+       return NULL;
+}
+
+struct packet_offload *gro_find_complete_by_type(__be16 type)
+{
+       struct list_head *offload_head = &offload_base;
+       struct packet_offload *ptype;
+
+       list_for_each_entry_rcu(ptype, offload_head, list) {
+               if (ptype->type != type || !ptype->callbacks.gro_complete)
+                       continue;
+               return ptype;
+       }
+       return NULL;
+}
 
 static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 {
@@ -4035,7 +4068,7 @@ gro_result_t napi_gro_frags(struct napi_struct *napi)
 EXPORT_SYMBOL(napi_gro_frags);
 
 /*
- * net_rps_action sends any pending IPI's for rps.
+ * net_rps_action_and_irq_enable sends any pending IPI's for rps.
  * Note: called with local irq disabled, but exits with local irq enabled.
  */
 static void net_rps_action_and_irq_enable(struct softnet_data *sd)
@@ -4240,17 +4273,10 @@ EXPORT_SYMBOL(netif_napi_add);
 
 void netif_napi_del(struct napi_struct *napi)
 {
-       struct sk_buff *skb, *next;
-
        list_del_init(&napi->dev_list);
        napi_free_frags(napi);
 
-       for (skb = napi->gro_list; skb; skb = next) {
-               next = skb->next;
-               skb->next = NULL;
-               kfree_skb(skb);
-       }
-
+       kfree_skb_list(napi->gro_list);
        napi->gro_list = NULL;
        napi->gro_count = 0;
 }
@@ -4367,19 +4393,6 @@ struct netdev_adjacent {
        struct rcu_head rcu;
 };
 
-static struct netdev_adjacent *__netdev_find_adj_rcu(struct net_device *dev,
-                                                    struct net_device *adj_dev,
-                                                    struct list_head *adj_list)
-{
-       struct netdev_adjacent *adj;
-
-       list_for_each_entry_rcu(adj, adj_list, list) {
-               if (adj->dev == adj_dev)
-                       return adj;
-       }
-       return NULL;
-}
-
 static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
                                                 struct net_device *adj_dev,
                                                 struct list_head *adj_list)
@@ -4418,13 +4431,12 @@ EXPORT_SYMBOL(netdev_has_upper_dev);
  * Find out if a device is linked to an upper device and return true in case
  * it is. The caller must hold the RTNL lock.
  */
-bool netdev_has_any_upper_dev(struct net_device *dev)
+static bool netdev_has_any_upper_dev(struct net_device *dev)
 {
        ASSERT_RTNL();
 
        return !list_empty(&dev->all_adj_list.upper);
 }
-EXPORT_SYMBOL(netdev_has_any_upper_dev);
 
 /**
  * netdev_master_upper_dev_get - Get master upper device
@@ -4473,7 +4485,7 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
 {
        struct netdev_adjacent *upper;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held());
 
        upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
 
@@ -4656,9 +4668,9 @@ free_adj:
        return ret;
 }
 
-void __netdev_adjacent_dev_remove(struct net_device *dev,
-                                 struct net_device *adj_dev,
-                                 struct list_head *dev_list)
+static void __netdev_adjacent_dev_remove(struct net_device *dev,
+                                        struct net_device *adj_dev,
+                                        struct list_head *dev_list)
 {
        struct netdev_adjacent *adj;
        char linkname[IFNAMSIZ+7];
@@ -4696,11 +4708,11 @@ void __netdev_adjacent_dev_remove(struct net_device *dev,
        kfree_rcu(adj, rcu);
 }
 
-int __netdev_adjacent_dev_link_lists(struct net_device *dev,
-                                    struct net_device *upper_dev,
-                                    struct list_head *up_list,
-                                    struct list_head *down_list,
-                                    void *private, bool master)
+static int __netdev_adjacent_dev_link_lists(struct net_device *dev,
+                                           struct net_device *upper_dev,
+                                           struct list_head *up_list,
+                                           struct list_head *down_list,
+                                           void *private, bool master)
 {
        int ret;
 
@@ -4719,8 +4731,8 @@ int __netdev_adjacent_dev_link_lists(struct net_device *dev,
        return 0;
 }
 
-int __netdev_adjacent_dev_link(struct net_device *dev,
-                              struct net_device *upper_dev)
+static int __netdev_adjacent_dev_link(struct net_device *dev,
+                                     struct net_device *upper_dev)
 {
        return __netdev_adjacent_dev_link_lists(dev, upper_dev,
                                                &dev->all_adj_list.upper,
@@ -4728,26 +4740,26 @@ int __netdev_adjacent_dev_link(struct net_device *dev,
                                                NULL, false);
 }
 
-void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
-                                       struct net_device *upper_dev,
-                                       struct list_head *up_list,
-                                       struct list_head *down_list)
+static void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
+                                              struct net_device *upper_dev,
+                                              struct list_head *up_list,
+                                              struct list_head *down_list)
 {
        __netdev_adjacent_dev_remove(dev, upper_dev, up_list);
        __netdev_adjacent_dev_remove(upper_dev, dev, down_list);
 }
 
-void __netdev_adjacent_dev_unlink(struct net_device *dev,
-                                 struct net_device *upper_dev)
+static void __netdev_adjacent_dev_unlink(struct net_device *dev,
+                                        struct net_device *upper_dev)
 {
        __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
                                           &dev->all_adj_list.upper,
                                           &upper_dev->all_adj_list.lower);
 }
 
-int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
-                                        struct net_device *upper_dev,
-                                        void *private, bool master)
+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);
 
@@ -4766,8 +4778,8 @@ int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
        return 0;
 }
 
-void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
-                                           struct net_device *upper_dev)
+static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
+                                                  struct net_device *upper_dev)
 {
        __netdev_adjacent_dev_unlink(dev, upper_dev);
        __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
@@ -4956,21 +4968,6 @@ void netdev_upper_dev_unlink(struct net_device *dev,
 }
 EXPORT_SYMBOL(netdev_upper_dev_unlink);
 
-void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
-                                      struct net_device *lower_dev)
-{
-       struct netdev_adjacent *lower;
-
-       if (!lower_dev)
-               return NULL;
-       lower = __netdev_find_adj_rcu(dev, lower_dev, &dev->adj_list.lower);
-       if (!lower)
-               return NULL;
-
-       return lower->private;
-}
-EXPORT_SYMBOL(netdev_lower_dev_get_private_rcu);
-
 void *netdev_lower_dev_get_private(struct net_device *dev,
                                   struct net_device *lower_dev)
 {
@@ -5303,6 +5300,17 @@ int dev_change_flags(struct net_device *dev, unsigned int flags)
 }
 EXPORT_SYMBOL(dev_change_flags);
 
+static int __dev_set_mtu(struct net_device *dev, int new_mtu)
+{
+       const struct net_device_ops *ops = dev->netdev_ops;
+
+       if (ops->ndo_change_mtu)
+               return ops->ndo_change_mtu(dev, new_mtu);
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+
 /**
  *     dev_set_mtu - Change maximum transfer unit
  *     @dev: device
@@ -5312,8 +5320,7 @@ EXPORT_SYMBOL(dev_change_flags);
  */
 int dev_set_mtu(struct net_device *dev, int new_mtu)
 {
-       const struct net_device_ops *ops = dev->netdev_ops;
-       int err;
+       int err, orig_mtu;
 
        if (new_mtu == dev->mtu)
                return 0;
@@ -5325,14 +5332,20 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
        if (!netif_device_present(dev))
                return -ENODEV;
 
-       err = 0;
-       if (ops->ndo_change_mtu)
-               err = ops->ndo_change_mtu(dev, new_mtu);
-       else
-               dev->mtu = new_mtu;
+       orig_mtu = dev->mtu;
+       err = __dev_set_mtu(dev, new_mtu);
 
-       if (!err)
-               call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
+       if (!err) {
+               err = call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
+               err = notifier_to_errno(err);
+               if (err) {
+                       /* setting mtu back and notifying everyone again,
+                        * so that they have a chance to revert changes.
+                        */
+                       __dev_set_mtu(dev, orig_mtu);
+                       call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
+               }
+       }
        return err;
 }
 EXPORT_SYMBOL(dev_set_mtu);
@@ -5825,13 +5838,8 @@ int register_netdevice(struct net_device *dev)
        dev->features |= NETIF_F_SOFT_FEATURES;
        dev->wanted_features = dev->features & dev->hw_features;
 
-       /* Turn on no cache copy if HW is doing checksum */
        if (!(dev->flags & IFF_LOOPBACK)) {
                dev->hw_features |= NETIF_F_NOCACHE_COPY;
-               if (dev->features & NETIF_F_ALL_CSUM) {
-                       dev->wanted_features |= NETIF_F_NOCACHE_COPY;
-                       dev->features |= NETIF_F_NOCACHE_COPY;
-               }
        }
 
        /* Make NETIF_F_HIGHDMA inheritable to VLAN devices.
index a666740051dc4d481f81714c3f59126c78db5df3..ea97361f0e9bfd7524f040b575456dc2ec2e2e9d 100644 (file)
@@ -1298,7 +1298,7 @@ int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
 
        if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
                            skb->len) < 0 &&
-           dev->header_ops->rebuild(skb))
+           dev_rebuild_header(skb))
                return 0;
 
        return dev_queue_xmit(skb);
index 1a7b7b1df0d197febe3fecadca653dbe6d2c8a5b..49843bf7e43e43986cbdf86d466cad8c3fbb4914 100644 (file)
@@ -1358,7 +1358,7 @@ void netdev_class_remove_file_ns(struct class_attribute *class_attr,
 }
 EXPORT_SYMBOL(netdev_class_remove_file_ns);
 
-int netdev_kobject_init(void)
+int __init netdev_kobject_init(void)
 {
        kobj_ns_type_register(&net_ns_type_operations);
        return class_register(&net_class);
index bd7751ec1c4d63d50163438958480a7261a234e7..2745a1b51e034a808ae586e29890e686f7ce7833 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __NET_SYSFS_H__
 #define __NET_SYSFS_H__
 
-int netdev_kobject_init(void);
+int __init netdev_kobject_init(void);
 int netdev_register_kobject(struct net_device *);
 void netdev_unregister_kobject(struct net_device *);
 int net_rx_queue_update_kobjects(struct net_device *, int old_num, int new_num);
diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c
new file mode 100644 (file)
index 0000000..719efd5
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * net/core/netclassid_cgroup.c        Classid Cgroupfs Handling
+ *
+ *             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.
+ *
+ * Authors:    Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/cgroup.h>
+#include <linux/fdtable.h>
+#include <net/cls_cgroup.h>
+#include <net/sock.h>
+
+static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css)
+{
+       return css ? container_of(css, struct cgroup_cls_state, css) : NULL;
+}
+
+struct cgroup_cls_state *task_cls_state(struct task_struct *p)
+{
+       return css_cls_state(task_css(p, net_cls_subsys_id));
+}
+EXPORT_SYMBOL_GPL(task_cls_state);
+
+static struct cgroup_subsys_state *
+cgrp_css_alloc(struct cgroup_subsys_state *parent_css)
+{
+       struct cgroup_cls_state *cs;
+
+       cs = kzalloc(sizeof(*cs), GFP_KERNEL);
+       if (!cs)
+               return ERR_PTR(-ENOMEM);
+
+       return &cs->css;
+}
+
+static int cgrp_css_online(struct cgroup_subsys_state *css)
+{
+       struct cgroup_cls_state *cs = css_cls_state(css);
+       struct cgroup_cls_state *parent = css_cls_state(css_parent(css));
+
+       if (parent)
+               cs->classid = parent->classid;
+
+       return 0;
+}
+
+static void cgrp_css_free(struct cgroup_subsys_state *css)
+{
+       kfree(css_cls_state(css));
+}
+
+static int update_classid(const void *v, struct file *file, unsigned n)
+{
+       int err;
+       struct socket *sock = sock_from_file(file, &err);
+
+       if (sock)
+               sock->sk->sk_classid = (u32)(unsigned long)v;
+
+       return 0;
+}
+
+static void cgrp_attach(struct cgroup_subsys_state *css,
+                       struct cgroup_taskset *tset)
+{
+       struct cgroup_cls_state *cs = css_cls_state(css);
+       void *v = (void *)(unsigned long)cs->classid;
+       struct task_struct *p;
+
+       cgroup_taskset_for_each(p, css, tset) {
+               task_lock(p);
+               iterate_fd(p->files, 0, update_classid, v);
+               task_unlock(p);
+       }
+}
+
+static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
+{
+       return css_cls_state(css)->classid;
+}
+
+static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
+                        u64 value)
+{
+       css_cls_state(css)->classid = (u32) value;
+
+       return 0;
+}
+
+static struct cftype ss_files[] = {
+       {
+               .name           = "classid",
+               .read_u64       = read_classid,
+               .write_u64      = write_classid,
+       },
+       { }     /* terminate */
+};
+
+struct cgroup_subsys net_cls_subsys = {
+       .name                   = "net_cls",
+       .css_alloc              = cgrp_css_alloc,
+       .css_online             = cgrp_css_online,
+       .css_free               = cgrp_css_free,
+       .attach                 = cgrp_attach,
+       .subsys_id              = net_cls_subsys_id,
+       .base_cftypes           = ss_files,
+       .module                 = THIS_MODULE,
+};
+
+static int __init init_netclassid_cgroup(void)
+{
+       return cgroup_load_subsys(&net_cls_subsys);
+}
+__initcall(init_netclassid_cgroup);
index 8f971990677cd48026f651b2dba01d01190bfff6..3030978746332246878598df7db62ce190607cbe 100644 (file)
@@ -386,8 +386,14 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                            !vlan_hw_offload_capable(netif_skb_features(skb),
                                                                     skb->vlan_proto)) {
                                                skb = __vlan_put_tag(skb, skb->vlan_proto, vlan_tx_tag_get(skb));
-                                               if (unlikely(!skb))
-                                                       break;
+                                               if (unlikely(!skb)) {
+                                                       /* This is actually a packet drop, but we
+                                                        * don't want the code at the end of this
+                                                        * function to try and re-queue a NULL skb.
+                                                        */
+                                                       status = NETDEV_TX_OK;
+                                                       goto unlock_txq;
+                                               }
                                                skb->vlan_tci = 0;
                                        }
 
@@ -395,6 +401,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                        if (status == NETDEV_TX_OK)
                                                txq_trans_update(txq);
                                }
+                       unlock_txq:
                                __netif_tx_unlock(txq);
 
                                if (status == NETDEV_TX_OK)
index cf67144d3e3c28f5fa2ab9965fba2884b03130d1..e6e7d582f90181632e0cfeb1941223f7f5daf017 100644 (file)
@@ -402,35 +402,17 @@ static const struct rtnl_af_ops *rtnl_af_lookup(const int family)
        return NULL;
 }
 
-/**
- * __rtnl_af_register - Register rtnl_af_ops with rtnetlink.
- * @ops: struct rtnl_af_ops * to register
- *
- * The caller must hold the rtnl_mutex.
- *
- * Returns 0 on success or a negative error code.
- */
-int __rtnl_af_register(struct rtnl_af_ops *ops)
-{
-       list_add_tail(&ops->list, &rtnl_af_ops);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(__rtnl_af_register);
-
 /**
  * rtnl_af_register - Register rtnl_af_ops with rtnetlink.
  * @ops: struct rtnl_af_ops * to register
  *
  * Returns 0 on success or a negative error code.
  */
-int rtnl_af_register(struct rtnl_af_ops *ops)
+void rtnl_af_register(struct rtnl_af_ops *ops)
 {
-       int err;
-
        rtnl_lock();
-       err = __rtnl_af_register(ops);
+       list_add_tail(&ops->list, &rtnl_af_ops);
        rtnl_unlock();
-       return err;
 }
 EXPORT_SYMBOL_GPL(rtnl_af_register);
 
index 2b6b863f51f28fa090eb09007d22c74f872821d8..1d641e781f85c51d650e94aa800e546f34024aaa 100644 (file)
@@ -2121,6 +2121,91 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
 }
 EXPORT_SYMBOL(skb_copy_and_csum_bits);
 
+ /**
+ *     skb_zerocopy_headlen - Calculate headroom needed for skb_zerocopy()
+ *     @from: source buffer
+ *
+ *     Calculates the amount of linear headroom needed in the 'to' skb passed
+ *     into skb_zerocopy().
+ */
+unsigned int
+skb_zerocopy_headlen(const struct sk_buff *from)
+{
+       unsigned int hlen = 0;
+
+       if (!from->head_frag ||
+           skb_headlen(from) < L1_CACHE_BYTES ||
+           skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS)
+               hlen = skb_headlen(from);
+
+       if (skb_has_frag_list(from))
+               hlen = from->len;
+
+       return hlen;
+}
+EXPORT_SYMBOL_GPL(skb_zerocopy_headlen);
+
+/**
+ *     skb_zerocopy - Zero copy skb to skb
+ *     @to: destination buffer
+ *     @source: source buffer
+ *     @len: number of bytes to copy from source buffer
+ *     @hlen: size of linear headroom in destination buffer
+ *
+ *     Copies up to `len` bytes from `from` to `to` by creating references
+ *     to the frags in the source buffer.
+ *
+ *     The `hlen` as calculated by skb_zerocopy_headlen() specifies the
+ *     headroom in the `to` buffer.
+ */
+void
+skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
+{
+       int i, j = 0;
+       int plen = 0; /* length of skb->head fragment */
+       struct page *page;
+       unsigned int offset;
+
+       BUG_ON(!from->head_frag && !hlen);
+
+       /* dont bother with small payloads */
+       if (len <= skb_tailroom(to)) {
+               skb_copy_bits(from, 0, skb_put(to, len), len);
+               return;
+       }
+
+       if (hlen) {
+               skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
+               len -= hlen;
+       } else {
+               plen = min_t(int, skb_headlen(from), len);
+               if (plen) {
+                       page = virt_to_head_page(from->head);
+                       offset = from->data - (unsigned char *)page_address(page);
+                       __skb_fill_page_desc(to, 0, page, offset, plen);
+                       get_page(page);
+                       j = 1;
+                       len -= plen;
+               }
+       }
+
+       to->truesize += len + plen;
+       to->len += len + plen;
+       to->data_len += len + plen;
+
+       for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
+               if (!len)
+                       break;
+               skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i];
+               skb_shinfo(to)->frags[j].size = min_t(int, skb_shinfo(to)->frags[j].size, len);
+               len -= skb_shinfo(to)->frags[j].size;
+               skb_frag_ref(to, j);
+               j++;
+       }
+       skb_shinfo(to)->nr_frags = j;
+}
+EXPORT_SYMBOL_GPL(skb_zerocopy);
+
 void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
 {
        __wsum csum;
@@ -2981,10 +3066,7 @@ perform_csum_check:
        return segs;
 
 err:
-       while ((skb = segs)) {
-               segs = skb->next;
-               kfree_skb(skb);
-       }
+       kfree_skb_list(segs);
        return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(skb_segment);
index 5393b4b719d71de2e3126664e3dcd5882c0c99d9..85ad6f0d389857da07347ddb18d0f9675936f0c4 100644 (file)
@@ -925,8 +925,8 @@ set_rcvbuf:
 EXPORT_SYMBOL(sock_setsockopt);
 
 
-void cred_to_ucred(struct pid *pid, const struct cred *cred,
-                  struct ucred *ucred)
+static void cred_to_ucred(struct pid *pid, const struct cred *cred,
+                         struct ucred *ucred)
 {
        ucred->pid = pid_vnr(pid);
        ucred->uid = ucred->gid = -1;
@@ -937,7 +937,6 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred,
                ucred->gid = from_kgid_munged(current_ns, cred->egid);
        }
 }
-EXPORT_SYMBOL_GPL(cred_to_ucred);
 
 int sock_getsockopt(struct socket *sock, int level, int optname,
                    char __user *optval, int __user *optlen)
@@ -1308,19 +1307,7 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
        module_put(owner);
 }
 
-#if IS_ENABLED(CONFIG_NET_CLS_CGROUP)
-void sock_update_classid(struct sock *sk)
-{
-       u32 classid;
-
-       classid = task_cls_classid(current);
-       if (classid != sk->sk_classid)
-               sk->sk_classid = classid;
-}
-EXPORT_SYMBOL(sock_update_classid);
-#endif
-
-#if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
+#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
 void sock_update_netprioidx(struct sock *sk)
 {
        if (in_interrupt())
@@ -1665,22 +1652,6 @@ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
 }
 EXPORT_SYMBOL(sock_wmalloc);
 
-/*
- * Allocate a skb from the socket's receive buffer.
- */
-struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force,
-                            gfp_t priority)
-{
-       if (force || atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf) {
-               struct sk_buff *skb = alloc_skb(size, priority);
-               if (skb) {
-                       skb_set_owner_r(skb, sk);
-                       return skb;
-               }
-       }
-       return NULL;
-}
-
 /*
  * Allocate a memory block from the socket's option memory buffer.
  */
index 62b5828acde0906b71fc39955c9f2b36582d395a..c073b81a1f3e74887783dbd6096b77629d12fbe0 100644 (file)
@@ -8,7 +8,7 @@
 #include "tfrc.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
-bool tfrc_debug;
+static bool tfrc_debug;
 module_param(tfrc_debug, bool, 0644);
 MODULE_PARM_DESC(tfrc_debug, "Enable TFRC debug messages");
 #endif
index 40ee7d62b6520d7daf2a1a8f3b54bda9cfbedfc2..a3d8f7c76ae091ba92704a3e6a70186c53b3b0f5 100644 (file)
@@ -21,7 +21,6 @@
 #include "packet_history.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
-extern bool tfrc_debug;
 #define tfrc_pr_debug(format, a...)    DCCP_PR_DEBUG(tfrc_debug, format, ##a)
 #else
 #define tfrc_pr_debug(format, a...)
index 30948784dd58ff0a35df38b075c3bebd53f90cbe..c67816647cce9d8b9fac7283179235ee1b642073 100644 (file)
@@ -479,7 +479,6 @@ void dccp_feat_list_purge(struct list_head *fn_list);
 
 int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
 int dccp_insert_options_rsk(struct dccp_request_sock *, struct sk_buff *);
-int dccp_insert_option_elapsed_time(struct sk_buff *skb, u32 elapsed);
 u32 dccp_timestamp(void);
 void dccp_timestamping_init(void);
 int dccp_insert_option(struct sk_buff *skb, unsigned char option,
index 88299c29101db7f8b52dba800ec19087b495f7dd..22b5d818b2001b177b765cbb67eb2551e87502ce 100644 (file)
@@ -989,6 +989,7 @@ static const struct net_protocol dccp_v4_protocol = {
        .err_handler    = dccp_v4_err,
        .no_policy      = 1,
        .netns_ok       = 1,
+       .icmp_strict_tag_validation = 1,
 };
 
 static const struct proto_ops inet_dccp_ops = {
index a58e0b6340506d1d2123bad650757acf36b7334d..9bce31886bda4e285d89e0f5d8d344956f01ce00 100644 (file)
@@ -343,38 +343,6 @@ static inline int dccp_elapsed_time_len(const u32 elapsed_time)
        return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
 }
 
-/* FIXME: This function is currently not used anywhere */
-int dccp_insert_option_elapsed_time(struct sk_buff *skb, u32 elapsed_time)
-{
-       const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
-       const int len = 2 + elapsed_time_len;
-       unsigned char *to;
-
-       if (elapsed_time_len == 0)
-               return 0;
-
-       if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
-               return -1;
-
-       DCCP_SKB_CB(skb)->dccpd_opt_len += len;
-
-       to    = skb_push(skb, len);
-       *to++ = DCCPO_ELAPSED_TIME;
-       *to++ = len;
-
-       if (elapsed_time_len == 2) {
-               const __be16 var16 = htons((u16)elapsed_time);
-               memcpy(to, &var16, 2);
-       } else {
-               const __be32 var32 = htonl(elapsed_time);
-               memcpy(to, &var32, 4);
-       }
-
-       return 0;
-}
-
-EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
-
 static int dccp_insert_option_timestamp(struct sk_buff *skb)
 {
        __be32 now = htonl(dccp_timestamp());
index 4c6bdf97a6577d190332b85654769a92ce553111..595ddf0459db79c724b8eab2c8b0f6a0a7d1df97 100644 (file)
@@ -152,17 +152,6 @@ static const struct file_operations dccpprobe_fops = {
        .llseek  = noop_llseek,
 };
 
-static __init int setup_jprobe(void)
-{
-       int ret = register_jprobe(&dccp_send_probe);
-
-       if (ret) {
-               request_module("dccp");
-               ret = register_jprobe(&dccp_send_probe);
-       }
-       return ret;
-}
-
 static __init int dccpprobe_init(void)
 {
        int ret = -ENOMEM;
@@ -174,7 +163,13 @@ static __init int dccpprobe_init(void)
        if (!proc_create(procname, S_IRUSR, init_net.proc_net, &dccpprobe_fops))
                goto err0;
 
-       ret = setup_jprobe();
+       ret = register_jprobe(&dccp_send_probe);
+       if (ret) {
+               ret = request_module("dccp");
+               if (!ret)
+                       ret = register_jprobe(&dccp_send_probe);
+       }
+
        if (ret)
                goto err1;
 
index 459e200c08a40e4e737798582524cd973064b143..48b25c0af4d082a5c3256f9844f62e12e1cc6f3c 100644 (file)
@@ -62,9 +62,6 @@
 
 #include "6lowpan.h"
 
-/* TTL uncompression values */
-static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
-
 static LIST_HEAD(lowpan_devices);
 
 /* private device info */
@@ -104,378 +101,14 @@ static inline void lowpan_address_flip(u8 *src, u8 *dest)
                (dest)[IEEE802154_ADDR_LEN - i - 1] = (src)[i];
 }
 
-/* list of all 6lowpan devices, uses for package delivering */
-/* print data in line */
-static inline void lowpan_raw_dump_inline(const char *caller, char *msg,
-                                  unsigned char *buf, int len)
-{
-#ifdef DEBUG
-       if (msg)
-               pr_debug("(%s) %s: ", caller, msg);
-       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE,
-                      16, 1, buf, len, false);
-#endif /* DEBUG */
-}
-
-/*
- * print data in a table format:
- *
- * addr: xx xx xx xx xx xx
- * addr: xx xx xx xx xx xx
- * ...
- */
-static inline void lowpan_raw_dump_table(const char *caller, char *msg,
-                                  unsigned char *buf, int len)
-{
-#ifdef DEBUG
-       if (msg)
-               pr_debug("(%s) %s:\n", caller, msg);
-       print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET,
-                      16, 1, buf, len, false);
-#endif /* DEBUG */
-}
-
-static u8
-lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr,
-                const unsigned char *lladdr)
-{
-       u8 val = 0;
-
-       if (is_addr_mac_addr_based(ipaddr, lladdr))
-               val = 3; /* 0-bits */
-       else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
-               /* compress IID to 16 bits xxxx::XXXX */
-               memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2);
-               *hc06_ptr += 2;
-               val = 2; /* 16-bits */
-       } else {
-               /* do not compress IID => xxxx::IID */
-               memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8);
-               *hc06_ptr += 8;
-               val = 1; /* 64-bits */
-       }
-
-       return rol8(val, shift);
-}
-
-/*
- * Uncompress address function for source and
- * destination address(non-multicast).
- *
- * address_mode is sam value or dam value.
- */
-static int
-lowpan_uncompress_addr(struct sk_buff *skb,
-               struct in6_addr *ipaddr,
-               const u8 address_mode,
-               const struct ieee802154_addr *lladdr)
-{
-       bool fail;
-
-       switch (address_mode) {
-       case LOWPAN_IPHC_ADDR_00:
-               /* for global link addresses */
-               fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
-               break;
-       case LOWPAN_IPHC_ADDR_01:
-               /* fe:80::XXXX:XXXX:XXXX:XXXX */
-               ipaddr->s6_addr[0] = 0xFE;
-               ipaddr->s6_addr[1] = 0x80;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
-               break;
-       case LOWPAN_IPHC_ADDR_02:
-               /* fe:80::ff:fe00:XXXX */
-               ipaddr->s6_addr[0] = 0xFE;
-               ipaddr->s6_addr[1] = 0x80;
-               ipaddr->s6_addr[11] = 0xFF;
-               ipaddr->s6_addr[12] = 0xFE;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
-               break;
-       case LOWPAN_IPHC_ADDR_03:
-               fail = false;
-               switch (lladdr->addr_type) {
-               case IEEE802154_ADDR_LONG:
-                       /* fe:80::XXXX:XXXX:XXXX:XXXX
-                        *        \_________________/
-                        *              hwaddr
-                        */
-                       ipaddr->s6_addr[0] = 0xFE;
-                       ipaddr->s6_addr[1] = 0x80;
-                       memcpy(&ipaddr->s6_addr[8], lladdr->hwaddr,
-                                       IEEE802154_ADDR_LEN);
-                       /* second bit-flip (Universe/Local)
-                        * is done according RFC2464
-                        */
-                       ipaddr->s6_addr[8] ^= 0x02;
-                       break;
-               case IEEE802154_ADDR_SHORT:
-                       /* fe:80::ff:fe00:XXXX
-                        *                \__/
-                        *             short_addr
-                        *
-                        * Universe/Local bit is zero.
-                        */
-                       ipaddr->s6_addr[0] = 0xFE;
-                       ipaddr->s6_addr[1] = 0x80;
-                       ipaddr->s6_addr[11] = 0xFF;
-                       ipaddr->s6_addr[12] = 0xFE;
-                       ipaddr->s6_addr16[7] = htons(lladdr->short_addr);
-                       break;
-               default:
-                       pr_debug("Invalid addr_type set\n");
-                       return -EINVAL;
-               }
-               break;
-       default:
-               pr_debug("Invalid address mode value: 0x%x\n", address_mode);
-               return -EINVAL;
-       }
-
-       if (fail) {
-               pr_debug("Failed to fetch skb data\n");
-               return -EIO;
-       }
-
-       lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 addr is:\n",
-                       ipaddr->s6_addr, 16);
-
-       return 0;
-}
-
-/* Uncompress address function for source context
- * based address(non-multicast).
- */
-static int
-lowpan_uncompress_context_based_src_addr(struct sk_buff *skb,
-               struct in6_addr *ipaddr,
-               const u8 sam)
-{
-       switch (sam) {
-       case LOWPAN_IPHC_ADDR_00:
-               /* unspec address ::
-                * Do nothing, address is already ::
-                */
-               break;
-       case LOWPAN_IPHC_ADDR_01:
-               /* TODO */
-       case LOWPAN_IPHC_ADDR_02:
-               /* TODO */
-       case LOWPAN_IPHC_ADDR_03:
-               /* TODO */
-               netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
-               return -EINVAL;
-       default:
-               pr_debug("Invalid sam value: 0x%x\n", sam);
-               return -EINVAL;
-       }
-
-       lowpan_raw_dump_inline(NULL,
-                       "Reconstructed context based ipv6 src addr is:\n",
-                       ipaddr->s6_addr, 16);
-
-       return 0;
-}
-
-/* Uncompress function for multicast destination address,
- * when M bit is set.
- */
-static int
-lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
-               struct in6_addr *ipaddr,
-               const u8 dam)
-{
-       bool fail;
-
-       switch (dam) {
-       case LOWPAN_IPHC_DAM_00:
-               /* 00:  128 bits.  The full address
-                * is carried in-line.
-                */
-               fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
-               break;
-       case LOWPAN_IPHC_DAM_01:
-               /* 01:  48 bits.  The address takes
-                * the form ffXX::00XX:XXXX:XXXX.
-                */
-               ipaddr->s6_addr[0] = 0xFF;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
-               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
-               break;
-       case LOWPAN_IPHC_DAM_10:
-               /* 10:  32 bits.  The address takes
-                * the form ffXX::00XX:XXXX.
-                */
-               ipaddr->s6_addr[0] = 0xFF;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
-               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
-               break;
-       case LOWPAN_IPHC_DAM_11:
-               /* 11:  8 bits.  The address takes
-                * the form ff02::00XX.
-                */
-               ipaddr->s6_addr[0] = 0xFF;
-               ipaddr->s6_addr[1] = 0x02;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
-               break;
-       default:
-               pr_debug("DAM value has a wrong value: 0x%x\n", dam);
-               return -EINVAL;
-       }
-
-       if (fail) {
-               pr_debug("Failed to fetch skb data\n");
-               return -EIO;
-       }
-
-       lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is:\n",
-                       ipaddr->s6_addr, 16);
-
-       return 0;
-}
-
-static void
-lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
-{
-       struct udphdr *uh = udp_hdr(skb);
-
-       if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) ==
-                               LOWPAN_NHC_UDP_4BIT_PORT) &&
-           ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) ==
-                               LOWPAN_NHC_UDP_4BIT_PORT)) {
-               pr_debug("UDP header: both ports compression to 4 bits\n");
-               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11;
-               **(hc06_ptr + 1) = /* subtraction is faster */
-                  (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) +
-                      ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
-               *hc06_ptr += 2;
-       } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) ==
-                       LOWPAN_NHC_UDP_8BIT_PORT) {
-               pr_debug("UDP header: remove 8 bits of dest\n");
-               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01;
-               memcpy(*hc06_ptr + 1, &uh->source, 2);
-               **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT);
-               *hc06_ptr += 4;
-       } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) ==
-                       LOWPAN_NHC_UDP_8BIT_PORT) {
-               pr_debug("UDP header: remove 8 bits of source\n");
-               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10;
-               memcpy(*hc06_ptr + 1, &uh->dest, 2);
-               **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT);
-               *hc06_ptr += 4;
-       } else {
-               pr_debug("UDP header: can't compress\n");
-               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00;
-               memcpy(*hc06_ptr + 1, &uh->source, 2);
-               memcpy(*hc06_ptr + 3, &uh->dest, 2);
-               *hc06_ptr += 5;
-       }
-
-       /* checksum is always inline */
-       memcpy(*hc06_ptr, &uh->check, 2);
-       *hc06_ptr += 2;
-
-       /* skip the UDP header */
-       skb_pull(skb, sizeof(struct udphdr));
-}
-
-static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
-{
-       if (unlikely(!pskb_may_pull(skb, 1)))
-               return -EINVAL;
-
-       *val = skb->data[0];
-       skb_pull(skb, 1);
-
-       return 0;
-}
-
-static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
-{
-       if (unlikely(!pskb_may_pull(skb, 2)))
-               return -EINVAL;
-
-       *val = (skb->data[0] << 8) | skb->data[1];
-       skb_pull(skb, 2);
-
-       return 0;
-}
-
-static int
-lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
-{
-       u8 tmp;
-
-       if (!uh)
-               goto err;
-
-       if (lowpan_fetch_skb_u8(skb, &tmp))
-               goto err;
-
-       if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
-               pr_debug("UDP header uncompression\n");
-               switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
-               case LOWPAN_NHC_UDP_CS_P_00:
-                       memcpy(&uh->source, &skb->data[0], 2);
-                       memcpy(&uh->dest, &skb->data[2], 2);
-                       skb_pull(skb, 4);
-                       break;
-               case LOWPAN_NHC_UDP_CS_P_01:
-                       memcpy(&uh->source, &skb->data[0], 2);
-                       uh->dest =
-                          skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT;
-                       skb_pull(skb, 3);
-                       break;
-               case LOWPAN_NHC_UDP_CS_P_10:
-                       uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT;
-                       memcpy(&uh->dest, &skb->data[1], 2);
-                       skb_pull(skb, 3);
-                       break;
-               case LOWPAN_NHC_UDP_CS_P_11:
-                       uh->source =
-                          LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4);
-                       uh->dest =
-                          LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f);
-                       skb_pull(skb, 1);
-                       break;
-               default:
-                       pr_debug("ERROR: unknown UDP format\n");
-                       goto err;
-               }
-
-               pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
-                        uh->source, uh->dest);
-
-               /* copy checksum */
-               memcpy(&uh->check, &skb->data[0], 2);
-               skb_pull(skb, 2);
-
-               /*
-                * UDP lenght needs to be infered from the lower layers
-                * here, we obtain the hint from the remaining size of the
-                * frame
-                */
-               uh->len = htons(skb->len + sizeof(struct udphdr));
-               pr_debug("uncompressed UDP length: src = %d", uh->len);
-       } else {
-               pr_debug("ERROR: unsupported NH format\n");
-               goto err;
-       }
-
-       return 0;
-err:
-       return -EINVAL;
-}
-
 static int lowpan_header_create(struct sk_buff *skb,
                           struct net_device *dev,
                           unsigned short type, const void *_daddr,
                           const void *_saddr, unsigned int len)
 {
-       u8 tmp, iphc0, iphc1, *hc06_ptr;
        struct ipv6hdr *hdr;
        const u8 *saddr = _saddr;
        const u8 *daddr = _daddr;
-       u8 head[100];
        struct ieee802154_addr sa, da;
 
        /* TODO:
@@ -485,181 +118,14 @@ static int lowpan_header_create(struct sk_buff *skb,
                return 0;
 
        hdr = ipv6_hdr(skb);
-       hc06_ptr = head + 2;
-
-       pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n"
-                "\tnexthdr = 0x%02x\n\thop_lim = %d\n", hdr->version,
-                ntohs(hdr->payload_len), hdr->nexthdr, hdr->hop_limit);
-
-       lowpan_raw_dump_table(__func__, "raw skb network header dump",
-               skb_network_header(skb), sizeof(struct ipv6hdr));
 
        if (!saddr)
                saddr = dev->dev_addr;
 
-       lowpan_raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8);
-
-       /*
-        * As we copy some bit-length fields, in the IPHC encoding bytes,
-        * we sometimes use |=
-        * If the field is 0, and the current bit value in memory is 1,
-        * this does not work. We therefore reset the IPHC encoding here
-        */
-       iphc0 = LOWPAN_DISPATCH_IPHC;
-       iphc1 = 0;
-
-       /* TODO: context lookup */
+       raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8);
+       raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8);
 
-       lowpan_raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8);
-
-       /*
-        * Traffic class, flow label
-        * If flow label is 0, compress it. If traffic class is 0, compress it
-        * We have to process both in the same time as the offset of traffic
-        * class depends on the presence of version and flow label
-        */
-
-       /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */
-       tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
-       tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
-
-       if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
-            (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
-               /* flow label can be compressed */
-               iphc0 |= LOWPAN_IPHC_FL_C;
-               if ((hdr->priority == 0) &&
-                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
-                       /* compress (elide) all */
-                       iphc0 |= LOWPAN_IPHC_TC_C;
-               } else {
-                       /* compress only the flow label */
-                       *hc06_ptr = tmp;
-                       hc06_ptr += 1;
-               }
-       } else {
-               /* Flow label cannot be compressed */
-               if ((hdr->priority == 0) &&
-                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
-                       /* compress only traffic class */
-                       iphc0 |= LOWPAN_IPHC_TC_C;
-                       *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
-                       memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2);
-                       hc06_ptr += 3;
-               } else {
-                       /* compress nothing */
-                       memcpy(hc06_ptr, &hdr, 4);
-                       /* replace the top byte with new ECN | DSCP format */
-                       *hc06_ptr = tmp;
-                       hc06_ptr += 4;
-               }
-       }
-
-       /* NOTE: payload length is always compressed */
-
-       /* Next Header is compress if UDP */
-       if (hdr->nexthdr == UIP_PROTO_UDP)
-               iphc0 |= LOWPAN_IPHC_NH_C;
-
-       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
-               *hc06_ptr = hdr->nexthdr;
-               hc06_ptr += 1;
-       }
-
-       /*
-        * Hop limit
-        * if 1:   compress, encoding is 01
-        * if 64:  compress, encoding is 10
-        * if 255: compress, encoding is 11
-        * else do not compress
-        */
-       switch (hdr->hop_limit) {
-       case 1:
-               iphc0 |= LOWPAN_IPHC_TTL_1;
-               break;
-       case 64:
-               iphc0 |= LOWPAN_IPHC_TTL_64;
-               break;
-       case 255:
-               iphc0 |= LOWPAN_IPHC_TTL_255;
-               break;
-       default:
-               *hc06_ptr = hdr->hop_limit;
-               hc06_ptr += 1;
-               break;
-       }
-
-       /* source address compression */
-       if (is_addr_unspecified(&hdr->saddr)) {
-               pr_debug("source address is unspecified, setting SAC\n");
-               iphc1 |= LOWPAN_IPHC_SAC;
-       /* TODO: context lookup */
-       } else if (is_addr_link_local(&hdr->saddr)) {
-               pr_debug("source address is link-local\n");
-               iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
-                               LOWPAN_IPHC_SAM_BIT, &hdr->saddr, saddr);
-       } else {
-               pr_debug("send the full source address\n");
-               memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16);
-               hc06_ptr += 16;
-       }
-
-       /* destination address compression */
-       if (is_addr_mcast(&hdr->daddr)) {
-               pr_debug("destination address is multicast: ");
-               iphc1 |= LOWPAN_IPHC_M;
-               if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
-                       pr_debug("compressed to 1 octet\n");
-                       iphc1 |= LOWPAN_IPHC_DAM_11;
-                       /* use last byte */
-                       *hc06_ptr = hdr->daddr.s6_addr[15];
-                       hc06_ptr += 1;
-               } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
-                       pr_debug("compressed to 4 octets\n");
-                       iphc1 |= LOWPAN_IPHC_DAM_10;
-                       /* second byte + the last three */
-                       *hc06_ptr = hdr->daddr.s6_addr[1];
-                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3);
-                       hc06_ptr += 4;
-               } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
-                       pr_debug("compressed to 6 octets\n");
-                       iphc1 |= LOWPAN_IPHC_DAM_01;
-                       /* second byte + the last five */
-                       *hc06_ptr = hdr->daddr.s6_addr[1];
-                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5);
-                       hc06_ptr += 6;
-               } else {
-                       pr_debug("using full address\n");
-                       iphc1 |= LOWPAN_IPHC_DAM_00;
-                       memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16);
-                       hc06_ptr += 16;
-               }
-       } else {
-               /* TODO: context lookup */
-               if (is_addr_link_local(&hdr->daddr)) {
-                       pr_debug("dest address is unicast and link-local\n");
-                       iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
-                               LOWPAN_IPHC_DAM_BIT, &hdr->daddr, daddr);
-               } else {
-                       pr_debug("dest address is unicast: using full one\n");
-                       memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16);
-                       hc06_ptr += 16;
-               }
-       }
-
-       /* UDP header compression */
-       if (hdr->nexthdr == UIP_PROTO_UDP)
-               lowpan_compress_udp_header(&hc06_ptr, skb);
-
-       head[0] = iphc0;
-       head[1] = iphc1;
-
-       skb_pull(skb, sizeof(struct ipv6hdr));
-       skb_reset_transport_header(skb);
-       memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
-       skb_reset_network_header(skb);
-
-       lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
-                               skb->len);
+       lowpan_header_compress(skb, dev, type, daddr, saddr, len);
 
        /*
         * NOTE1: I'm still unsure about the fact that compression and WPAN
@@ -671,39 +137,38 @@ static int lowpan_header_create(struct sk_buff *skb,
         * from MAC subif of the 'dev' and 'real_dev' network devices, but
         * this isn't implemented in mainline yet, so currently we assign 0xff
         */
-       {
-               mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
-               mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+       mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+       mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
 
-               /* prepare wpan address data */
-               sa.addr_type = IEEE802154_ADDR_LONG;
-               sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+       /* prepare wpan address data */
+       sa.addr_type = IEEE802154_ADDR_LONG;
+       sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
 
-               memcpy(&(sa.hwaddr), saddr, 8);
-               /* intra-PAN communications */
-               da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+       memcpy(&(sa.hwaddr), saddr, 8);
+       /* intra-PAN communications */
+       da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
 
-               /*
-                * if the destination address is the broadcast address, use the
-                * corresponding short address
-                */
-               if (lowpan_is_addr_broadcast(daddr)) {
-                       da.addr_type = IEEE802154_ADDR_SHORT;
-                       da.short_addr = IEEE802154_ADDR_BROADCAST;
-               } else {
-                       da.addr_type = IEEE802154_ADDR_LONG;
-                       memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN);
-
-                       /* request acknowledgment */
-                       mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
-               }
+       /*
+        * if the destination address is the broadcast address, use the
+        * corresponding short address
+        */
+       if (lowpan_is_addr_broadcast(daddr)) {
+               da.addr_type = IEEE802154_ADDR_SHORT;
+               da.short_addr = IEEE802154_ADDR_BROADCAST;
+       } else {
+               da.addr_type = IEEE802154_ADDR_LONG;
+               memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN);
 
-               return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
-                               type, (void *)&da, (void *)&sa, skb->len);
+               /* request acknowledgment */
+               mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
        }
+
+       return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
+                       type, (void *)&da, (void *)&sa, skb->len);
 }
 
-static int lowpan_give_skb_to_devices(struct sk_buff *skb)
+static int lowpan_give_skb_to_devices(struct sk_buff *skb,
+                                       struct net_device *dev)
 {
        struct lowpan_dev_record *entry;
        struct sk_buff *skb_cp;
@@ -726,31 +191,6 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb)
        return stat;
 }
 
-static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
-{
-       struct sk_buff *new;
-       int stat = NET_RX_SUCCESS;
-
-       new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
-                                                               GFP_ATOMIC);
-       kfree_skb(skb);
-
-       if (!new)
-               return -ENOMEM;
-
-       skb_push(new, sizeof(struct ipv6hdr));
-       skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
-
-       new->protocol = htons(ETH_P_IPV6);
-       new->pkt_type = PACKET_HOST;
-
-       stat = lowpan_give_skb_to_devices(new);
-
-       kfree_skb(new);
-
-       return stat;
-}
-
 static void lowpan_fragment_timer_expired(unsigned long entry_addr)
 {
        struct lowpan_fragment *entry = (struct lowpan_fragment *)entry_addr;
@@ -814,16 +254,12 @@ frame_err:
        return NULL;
 }
 
-static int
-lowpan_process_data(struct sk_buff *skb)
+static int process_data(struct sk_buff *skb)
 {
-       struct ipv6hdr hdr = {};
-       u8 tmp, iphc0, iphc1, num_context = 0;
+       u8 iphc0, iphc1;
        const struct ieee802154_addr *_saddr, *_daddr;
-       int err;
 
-       lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
-                               skb->len);
+       raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len);
        /* at least two bytes will be used for the encoding */
        if (skb->len < 2)
                goto drop;
@@ -925,162 +361,11 @@ lowpan_process_data(struct sk_buff *skb)
        _saddr = &mac_cb(skb)->sa;
        _daddr = &mac_cb(skb)->da;
 
-       pr_debug("iphc0 = %02x, iphc1 = %02x\n", iphc0, iphc1);
-
-       /* another if the CID flag is set */
-       if (iphc1 & LOWPAN_IPHC_CID) {
-               pr_debug("CID flag is set, increase header with one\n");
-               if (lowpan_fetch_skb_u8(skb, &num_context))
-                       goto drop;
-       }
-
-       hdr.version = 6;
-
-       /* Traffic Class and Flow Label */
-       switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
-       /*
-        * Traffic Class and FLow Label carried in-line
-        * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
-        */
-       case 0: /* 00b */
-               if (lowpan_fetch_skb_u8(skb, &tmp))
-                       goto drop;
-
-               memcpy(&hdr.flow_lbl, &skb->data[0], 3);
-               skb_pull(skb, 3);
-               hdr.priority = ((tmp >> 2) & 0x0f);
-               hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
-                                       (hdr.flow_lbl[0] & 0x0f);
-               break;
-       /*
-        * Traffic class carried in-line
-        * ECN + DSCP (1 byte), Flow Label is elided
-        */
-       case 2: /* 10b */
-               if (lowpan_fetch_skb_u8(skb, &tmp))
-                       goto drop;
-
-               hdr.priority = ((tmp >> 2) & 0x0f);
-               hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
-               break;
-       /*
-        * Flow Label carried in-line
-        * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
-        */
-       case 1: /* 01b */
-               if (lowpan_fetch_skb_u8(skb, &tmp))
-                       goto drop;
-
-               hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
-               memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
-               skb_pull(skb, 2);
-               break;
-       /* Traffic Class and Flow Label are elided */
-       case 3: /* 11b */
-               break;
-       default:
-               break;
-       }
-
-       /* Next Header */
-       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
-               /* Next header is carried inline */
-               if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr)))
-                       goto drop;
-
-               pr_debug("NH flag is set, next header carried inline: %02x\n",
-                        hdr.nexthdr);
-       }
-
-       /* Hop Limit */
-       if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I)
-               hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
-       else {
-               if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit)))
-                       goto drop;
-       }
-
-       /* Extract SAM to the tmp variable */
-       tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
-
-       if (iphc1 & LOWPAN_IPHC_SAC) {
-               /* Source address context based uncompression */
-               pr_debug("SAC bit is set. Handle context based source address.\n");
-               err = lowpan_uncompress_context_based_src_addr(
-                               skb, &hdr.saddr, tmp);
-       } else {
-               /* Source address uncompression */
-               pr_debug("source address stateless compression\n");
-               err = lowpan_uncompress_addr(skb, &hdr.saddr, tmp, _saddr);
-       }
-
-       /* Check on error of previous branch */
-       if (err)
-               goto drop;
-
-       /* Extract DAM to the tmp variable */
-       tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
-
-       /* check for Multicast Compression */
-       if (iphc1 & LOWPAN_IPHC_M) {
-               if (iphc1 & LOWPAN_IPHC_DAC) {
-                       pr_debug("dest: context-based mcast compression\n");
-                       /* TODO: implement this */
-               } else {
-                       err = lowpan_uncompress_multicast_daddr(
-                                       skb, &hdr.daddr, tmp);
-                       if (err)
-                               goto drop;
-               }
-       } else {
-               pr_debug("dest: stateless compression\n");
-               err = lowpan_uncompress_addr(skb, &hdr.daddr, tmp, _daddr);
-               if (err)
-                       goto drop;
-       }
-
-       /* UDP data uncompression */
-       if (iphc0 & LOWPAN_IPHC_NH_C) {
-               struct udphdr uh;
-               struct sk_buff *new;
-               if (lowpan_uncompress_udp_header(skb, &uh))
-                       goto drop;
-
-               /*
-                * replace the compressed UDP head by the uncompressed UDP
-                * header
-                */
-               new = skb_copy_expand(skb, sizeof(struct udphdr),
-                                     skb_tailroom(skb), GFP_ATOMIC);
-               kfree_skb(skb);
-
-               if (!new)
-                       return -ENOMEM;
-
-               skb = new;
-
-               skb_push(skb, sizeof(struct udphdr));
-               skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
-
-               lowpan_raw_dump_table(__func__, "raw UDP header dump",
-                                     (u8 *)&uh, sizeof(uh));
-
-               hdr.nexthdr = UIP_PROTO_UDP;
-       }
-
-       /* Not fragmented package */
-       hdr.payload_len = htons(skb->len);
-
-       pr_debug("skb headroom size = %d, data length = %d\n",
-                skb_headroom(skb), skb->len);
-
-       pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n\t"
-                "nexthdr = 0x%02x\n\thop_lim = %d\n", hdr.version,
-                ntohs(hdr.payload_len), hdr.nexthdr, hdr.hop_limit);
-
-       lowpan_raw_dump_table(__func__, "raw header dump", (u8 *)&hdr,
-                                                       sizeof(hdr));
-       return lowpan_skb_deliver(skb, &hdr);
+       return lowpan_process_data(skb, skb->dev, (u8 *)_saddr->hwaddr,
+                               _saddr->addr_type, IEEE802154_ADDR_LEN,
+                               (u8 *)_daddr->hwaddr, _daddr->addr_type,
+                               IEEE802154_ADDR_LEN, iphc0, iphc1,
+                               lowpan_give_skb_to_devices);
 
 unlock_and_drop:
        spin_unlock_bh(&flist_lock);
@@ -1112,7 +397,7 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
        hlen = (type == LOWPAN_DISPATCH_FRAG1) ?
                        LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE;
 
-       lowpan_raw_dump_inline(__func__, "6lowpan fragment header", head, hlen);
+       raw_dump_inline(__func__, "6lowpan fragment header", head, hlen);
 
        frag = netdev_alloc_skb(skb->dev,
                                hlen + mlen + plen + IEEE802154_MFR_SIZE);
@@ -1132,8 +417,7 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
        skb_copy_to_linear_data_offset(frag, mlen + hlen,
                                       skb_network_header(skb) + offset, plen);
 
-       lowpan_raw_dump_table(__func__, " raw fragment dump", frag->data,
-                                                               frag->len);
+       raw_dump_table(__func__, " raw fragment dump", frag->data, frag->len);
 
        return dev_queue_xmit(frag);
 }
@@ -1316,7 +600,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
                /* Pull off the 1-byte of 6lowpan header. */
                skb_pull(local_skb, 1);
 
-               lowpan_give_skb_to_devices(local_skb);
+               lowpan_give_skb_to_devices(local_skb, NULL);
 
                kfree_skb(local_skb);
                kfree_skb(skb);
@@ -1328,7 +612,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
                        local_skb = skb_clone(skb, GFP_ATOMIC);
                        if (!local_skb)
                                goto drop;
-                       lowpan_process_data(local_skb);
+                       process_data(local_skb);
 
                        kfree_skb(skb);
                        break;
index 2869c0526dad698b574ddd05f3f2175d5fb69455..2b835db3bda83477bc89e9212e18bf612e21b074 100644 (file)
 #define LOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline,
                                        dest = 16 bit inline */
 #define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
+#define LOWPAN_NHC_UDP_CS_C    0x04 /* checksum elided */
+
+#ifdef DEBUG
+/* print data in line */
+static inline void raw_dump_inline(const char *caller, char *msg,
+                                  unsigned char *buf, int len)
+{
+       if (msg)
+               pr_debug("%s():%s: ", caller, msg);
+
+       print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, buf, len, false);
+}
+
+/* print data in a table format:
+ *
+ * addr: xx xx xx xx xx xx
+ * addr: xx xx xx xx xx xx
+ * ...
+ */
+static inline void raw_dump_table(const char *caller, char *msg,
+                                 unsigned char *buf, int len)
+{
+       if (msg)
+               pr_debug("%s():%s:\n", caller, msg);
+
+       print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET, 16, 1, buf, len, false);
+}
+#else
+static inline void raw_dump_table(const char *caller, char *msg,
+                                 unsigned char *buf, int len) { }
+static inline void raw_dump_inline(const char *caller, char *msg,
+                                  unsigned char *buf, int len) { }
+#endif
+
+static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
+{
+       if (unlikely(!pskb_may_pull(skb, 1)))
+               return -EINVAL;
+
+       *val = skb->data[0];
+       skb_pull(skb, 1);
+
+       return 0;
+}
+
+static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
+{
+       if (unlikely(!pskb_may_pull(skb, 2)))
+               return -EINVAL;
+
+       *val = (skb->data[0] << 8) | skb->data[1];
+       skb_pull(skb, 2);
+
+       return 0;
+}
 
 static inline bool lowpan_fetch_skb(struct sk_buff *skb,
                void *data, const unsigned int len)
@@ -244,4 +299,21 @@ static inline bool lowpan_fetch_skb(struct sk_buff *skb,
        return false;
 }
 
+static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,
+                                      const size_t len)
+{
+       memcpy(*hc_ptr, data, len);
+       *hc_ptr += len;
+}
+
+typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
+
+int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
+               const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
+               const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
+               u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
+int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
+                       unsigned short type, const void *_daddr,
+                       const void *_saddr, unsigned int len);
+
 #endif /* __6LOWPAN_H__ */
diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c
new file mode 100644 (file)
index 0000000..11840f9
--- /dev/null
@@ -0,0 +1,799 @@
+/*
+ * Copyright 2011, Siemens AG
+ * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+/*
+ * Based on patches from Jon Smirl <jonsmirl@gmail.com>
+ * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Jon's code is based on 6lowpan implementation for Contiki which is:
+ * Copyright (c) 2008, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * 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 name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+#include <linux/bitops.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <net/ipv6.h>
+#include <net/af_ieee802154.h>
+
+#include "6lowpan.h"
+
+/*
+ * Uncompress address function for source and
+ * destination address(non-multicast).
+ *
+ * address_mode is sam value or dam value.
+ */
+static int uncompress_addr(struct sk_buff *skb,
+                               struct in6_addr *ipaddr, const u8 address_mode,
+                               const u8 *lladdr, const u8 addr_type,
+                               const u8 addr_len)
+{
+       bool fail;
+
+       switch (address_mode) {
+       case LOWPAN_IPHC_ADDR_00:
+               /* for global link addresses */
+               fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
+               break;
+       case LOWPAN_IPHC_ADDR_01:
+               /* fe:80::XXXX:XXXX:XXXX:XXXX */
+               ipaddr->s6_addr[0] = 0xFE;
+               ipaddr->s6_addr[1] = 0x80;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
+               break;
+       case LOWPAN_IPHC_ADDR_02:
+               /* fe:80::ff:fe00:XXXX */
+               ipaddr->s6_addr[0] = 0xFE;
+               ipaddr->s6_addr[1] = 0x80;
+               ipaddr->s6_addr[11] = 0xFF;
+               ipaddr->s6_addr[12] = 0xFE;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
+               break;
+       case LOWPAN_IPHC_ADDR_03:
+               fail = false;
+               switch (addr_type) {
+               case IEEE802154_ADDR_LONG:
+                       /* fe:80::XXXX:XXXX:XXXX:XXXX
+                        *        \_________________/
+                        *              hwaddr
+                        */
+                       ipaddr->s6_addr[0] = 0xFE;
+                       ipaddr->s6_addr[1] = 0x80;
+                       memcpy(&ipaddr->s6_addr[8], lladdr, addr_len);
+                       /* second bit-flip (Universe/Local)
+                        * is done according RFC2464
+                        */
+                       ipaddr->s6_addr[8] ^= 0x02;
+                       break;
+               case IEEE802154_ADDR_SHORT:
+                       /* fe:80::ff:fe00:XXXX
+                        *                \__/
+                        *             short_addr
+                        *
+                        * Universe/Local bit is zero.
+                        */
+                       ipaddr->s6_addr[0] = 0xFE;
+                       ipaddr->s6_addr[1] = 0x80;
+                       ipaddr->s6_addr[11] = 0xFF;
+                       ipaddr->s6_addr[12] = 0xFE;
+                       ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr));
+                       break;
+               default:
+                       pr_debug("Invalid addr_type set\n");
+                       return -EINVAL;
+               }
+               break;
+       default:
+               pr_debug("Invalid address mode value: 0x%x\n", address_mode);
+               return -EINVAL;
+       }
+
+       if (fail) {
+               pr_debug("Failed to fetch skb data\n");
+               return -EIO;
+       }
+
+       raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
+                       ipaddr->s6_addr, 16);
+
+       return 0;
+}
+
+/*
+ * Uncompress address function for source context
+ * based address(non-multicast).
+ */
+static int uncompress_context_based_src_addr(struct sk_buff *skb,
+                                               struct in6_addr *ipaddr,
+                                               const u8 sam)
+{
+       switch (sam) {
+       case LOWPAN_IPHC_ADDR_00:
+               /* unspec address ::
+                * Do nothing, address is already ::
+                */
+               break;
+       case LOWPAN_IPHC_ADDR_01:
+               /* TODO */
+       case LOWPAN_IPHC_ADDR_02:
+               /* TODO */
+       case LOWPAN_IPHC_ADDR_03:
+               /* TODO */
+               netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
+               return -EINVAL;
+       default:
+               pr_debug("Invalid sam value: 0x%x\n", sam);
+               return -EINVAL;
+       }
+
+       raw_dump_inline(NULL,
+                       "Reconstructed context based ipv6 src addr is",
+                       ipaddr->s6_addr, 16);
+
+       return 0;
+}
+
+static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
+               struct net_device *dev, skb_delivery_cb deliver_skb)
+{
+       struct sk_buff *new;
+       int stat;
+
+       new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
+                                                               GFP_ATOMIC);
+       kfree_skb(skb);
+
+       if (!new)
+               return -ENOMEM;
+
+       skb_push(new, sizeof(struct ipv6hdr));
+       skb_reset_network_header(new);
+       skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
+
+       new->protocol = htons(ETH_P_IPV6);
+       new->pkt_type = PACKET_HOST;
+       new->dev = dev;
+
+       raw_dump_table(__func__, "raw skb data dump before receiving",
+                       new->data, new->len);
+
+       stat = deliver_skb(new, dev);
+
+       kfree_skb(new);
+
+       return stat;
+}
+
+/* Uncompress function for multicast destination address,
+ * when M bit is set.
+ */
+static int
+lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
+               struct in6_addr *ipaddr,
+               const u8 dam)
+{
+       bool fail;
+
+       switch (dam) {
+       case LOWPAN_IPHC_DAM_00:
+               /* 00:  128 bits.  The full address
+                * is carried in-line.
+                */
+               fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
+               break;
+       case LOWPAN_IPHC_DAM_01:
+               /* 01:  48 bits.  The address takes
+                * the form ffXX::00XX:XXXX:XXXX.
+                */
+               ipaddr->s6_addr[0] = 0xFF;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
+               break;
+       case LOWPAN_IPHC_DAM_10:
+               /* 10:  32 bits.  The address takes
+                * the form ffXX::00XX:XXXX.
+                */
+               ipaddr->s6_addr[0] = 0xFF;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
+               break;
+       case LOWPAN_IPHC_DAM_11:
+               /* 11:  8 bits.  The address takes
+                * the form ff02::00XX.
+                */
+               ipaddr->s6_addr[0] = 0xFF;
+               ipaddr->s6_addr[1] = 0x02;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
+               break;
+       default:
+               pr_debug("DAM value has a wrong value: 0x%x\n", dam);
+               return -EINVAL;
+       }
+
+       if (fail) {
+               pr_debug("Failed to fetch skb data\n");
+               return -EIO;
+       }
+
+       raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
+                               ipaddr->s6_addr, 16);
+
+       return 0;
+}
+
+static int
+uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
+{
+       bool fail;
+       u8 tmp = 0, val = 0;
+
+       if (!uh)
+               goto err;
+
+       fail = lowpan_fetch_skb(skb, &tmp, 1);
+
+       if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
+               pr_debug("UDP header uncompression\n");
+               switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
+               case LOWPAN_NHC_UDP_CS_P_00:
+                       fail |= lowpan_fetch_skb(skb, &uh->source, 2);
+                       fail |= lowpan_fetch_skb(skb, &uh->dest, 2);
+                       break;
+               case LOWPAN_NHC_UDP_CS_P_01:
+                       fail |= lowpan_fetch_skb(skb, &uh->source, 2);
+                       fail |= lowpan_fetch_skb(skb, &val, 1);
+                       uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
+                       break;
+               case LOWPAN_NHC_UDP_CS_P_10:
+                       fail |= lowpan_fetch_skb(skb, &val, 1);
+                       uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
+                       fail |= lowpan_fetch_skb(skb, &uh->dest, 2);
+                       break;
+               case LOWPAN_NHC_UDP_CS_P_11:
+                       fail |= lowpan_fetch_skb(skb, &val, 1);
+                       uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT +
+                                          (val >> 4));
+                       uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT +
+                                        (val & 0x0f));
+                       break;
+               default:
+                       pr_debug("ERROR: unknown UDP format\n");
+                       goto err;
+                       break;
+               }
+
+               pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
+                        ntohs(uh->source), ntohs(uh->dest));
+
+               /* checksum */
+               if (tmp & LOWPAN_NHC_UDP_CS_C) {
+                       pr_debug_ratelimited("checksum elided currently not supported\n");
+                       goto err;
+               } else {
+                       fail |= lowpan_fetch_skb(skb, &uh->check, 2);
+               }
+
+               /*
+                * UDP lenght needs to be infered from the lower layers
+                * here, we obtain the hint from the remaining size of the
+                * frame
+                */
+               uh->len = htons(skb->len + sizeof(struct udphdr));
+               pr_debug("uncompressed UDP length: src = %d", ntohs(uh->len));
+       } else {
+               pr_debug("ERROR: unsupported NH format\n");
+               goto err;
+       }
+
+       if (fail)
+               goto err;
+
+       return 0;
+err:
+       return -EINVAL;
+}
+
+/* TTL uncompression values */
+static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
+
+int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
+               const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
+               const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
+               u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb)
+{
+       struct ipv6hdr hdr = {};
+       u8 tmp, num_context = 0;
+       int err;
+
+       raw_dump_table(__func__, "raw skb data dump uncompressed",
+                               skb->data, skb->len);
+
+       /* another if the CID flag is set */
+       if (iphc1 & LOWPAN_IPHC_CID) {
+               pr_debug("CID flag is set, increase header with one\n");
+               if (lowpan_fetch_skb_u8(skb, &num_context))
+                       goto drop;
+       }
+
+       hdr.version = 6;
+
+       /* Traffic Class and Flow Label */
+       switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
+       /*
+        * Traffic Class and FLow Label carried in-line
+        * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
+        */
+       case 0: /* 00b */
+               if (lowpan_fetch_skb_u8(skb, &tmp))
+                       goto drop;
+
+               memcpy(&hdr.flow_lbl, &skb->data[0], 3);
+               skb_pull(skb, 3);
+               hdr.priority = ((tmp >> 2) & 0x0f);
+               hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
+                                       (hdr.flow_lbl[0] & 0x0f);
+               break;
+       /*
+        * Traffic class carried in-line
+        * ECN + DSCP (1 byte), Flow Label is elided
+        */
+       case 2: /* 10b */
+               if (lowpan_fetch_skb_u8(skb, &tmp))
+                       goto drop;
+
+               hdr.priority = ((tmp >> 2) & 0x0f);
+               hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
+               break;
+       /*
+        * Flow Label carried in-line
+        * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
+        */
+       case 1: /* 01b */
+               if (lowpan_fetch_skb_u8(skb, &tmp))
+                       goto drop;
+
+               hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
+               memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
+               skb_pull(skb, 2);
+               break;
+       /* Traffic Class and Flow Label are elided */
+       case 3: /* 11b */
+               break;
+       default:
+               break;
+       }
+
+       /* Next Header */
+       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+               /* Next header is carried inline */
+               if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr)))
+                       goto drop;
+
+               pr_debug("NH flag is set, next header carried inline: %02x\n",
+                        hdr.nexthdr);
+       }
+
+       /* Hop Limit */
+       if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I)
+               hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
+       else {
+               if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit)))
+                       goto drop;
+       }
+
+       /* Extract SAM to the tmp variable */
+       tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
+
+       if (iphc1 & LOWPAN_IPHC_SAC) {
+               /* Source address context based uncompression */
+               pr_debug("SAC bit is set. Handle context based source address.\n");
+               err = uncompress_context_based_src_addr(
+                               skb, &hdr.saddr, tmp);
+       } else {
+               /* Source address uncompression */
+               pr_debug("source address stateless compression\n");
+               err = uncompress_addr(skb, &hdr.saddr, tmp, saddr,
+                                       saddr_type, saddr_len);
+       }
+
+       /* Check on error of previous branch */
+       if (err)
+               goto drop;
+
+       /* Extract DAM to the tmp variable */
+       tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
+
+       /* check for Multicast Compression */
+       if (iphc1 & LOWPAN_IPHC_M) {
+               if (iphc1 & LOWPAN_IPHC_DAC) {
+                       pr_debug("dest: context-based mcast compression\n");
+                       /* TODO: implement this */
+               } else {
+                       err = lowpan_uncompress_multicast_daddr(
+                                               skb, &hdr.daddr, tmp);
+                       if (err)
+                               goto drop;
+               }
+       } else {
+               err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
+                                       daddr_type, daddr_len);
+               pr_debug("dest: stateless compression mode %d dest %pI6c\n",
+                       tmp, &hdr.daddr);
+               if (err)
+                       goto drop;
+       }
+
+       /* UDP data uncompression */
+       if (iphc0 & LOWPAN_IPHC_NH_C) {
+               struct udphdr uh;
+               struct sk_buff *new;
+               if (uncompress_udp_header(skb, &uh))
+                       goto drop;
+
+               /*
+                * replace the compressed UDP head by the uncompressed UDP
+                * header
+                */
+               new = skb_copy_expand(skb, sizeof(struct udphdr),
+                                     skb_tailroom(skb), GFP_ATOMIC);
+               kfree_skb(skb);
+
+               if (!new)
+                       return -ENOMEM;
+
+               skb = new;
+
+               skb_push(skb, sizeof(struct udphdr));
+               skb_reset_transport_header(skb);
+               skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
+
+               raw_dump_table(__func__, "raw UDP header dump",
+                                     (u8 *)&uh, sizeof(uh));
+
+               hdr.nexthdr = UIP_PROTO_UDP;
+       }
+
+       hdr.payload_len = htons(skb->len);
+
+       pr_debug("skb headroom size = %d, data length = %d\n",
+                skb_headroom(skb), skb->len);
+
+       pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n\t"
+                "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
+               hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
+               hdr.hop_limit, &hdr.daddr);
+
+       raw_dump_table(__func__, "raw header dump", (u8 *)&hdr,
+                                                       sizeof(hdr));
+
+       return skb_deliver(skb, &hdr, dev, deliver_skb);
+
+drop:
+       kfree_skb(skb);
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(lowpan_process_data);
+
+static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift,
+                               const struct in6_addr *ipaddr,
+                               const unsigned char *lladdr)
+{
+       u8 val = 0;
+
+       if (is_addr_mac_addr_based(ipaddr, lladdr)) {
+               val = 3; /* 0-bits */
+               pr_debug("address compression 0 bits\n");
+       } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
+               /* compress IID to 16 bits xxxx::XXXX */
+               memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2);
+               *hc06_ptr += 2;
+               val = 2; /* 16-bits */
+               raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
+                       *hc06_ptr - 2, 2);
+       } else {
+               /* do not compress IID => xxxx::IID */
+               memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8);
+               *hc06_ptr += 8;
+               val = 1; /* 64-bits */
+               raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
+                       *hc06_ptr - 8, 8);
+       }
+
+       return rol8(val, shift);
+}
+
+static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
+{
+       struct udphdr *uh = udp_hdr(skb);
+       u8 tmp;
+
+       if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) ==
+            LOWPAN_NHC_UDP_4BIT_PORT) &&
+           ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) ==
+            LOWPAN_NHC_UDP_4BIT_PORT)) {
+               pr_debug("UDP header: both ports compression to 4 bits\n");
+               /* compression value */
+               tmp = LOWPAN_NHC_UDP_CS_P_11;
+               lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+               /* source and destination port */
+               tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT +
+                     ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4);
+               lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+       } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
+                       LOWPAN_NHC_UDP_8BIT_PORT) {
+               pr_debug("UDP header: remove 8 bits of dest\n");
+               /* compression value */
+               tmp = LOWPAN_NHC_UDP_CS_P_01;
+               lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+               /* source port */
+               lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source));
+               /* destination port */
+               tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT;
+               lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+       } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) ==
+                       LOWPAN_NHC_UDP_8BIT_PORT) {
+               pr_debug("UDP header: remove 8 bits of source\n");
+               /* compression value */
+               tmp = LOWPAN_NHC_UDP_CS_P_10;
+               lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+               /* source port */
+               tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT;
+               lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+               /* destination port */
+               lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest));
+       } else {
+               pr_debug("UDP header: can't compress\n");
+               /* compression value */
+               tmp = LOWPAN_NHC_UDP_CS_P_00;
+               lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+               /* source port */
+               lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source));
+               /* destination port */
+               lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest));
+       }
+
+       /* checksum is always inline */
+       lowpan_push_hc_data(hc06_ptr, &uh->check, sizeof(uh->check));
+
+       /* skip the UDP header */
+       skb_pull(skb, sizeof(struct udphdr));
+}
+
+int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
+                       unsigned short type, const void *_daddr,
+                       const void *_saddr, unsigned int len)
+{
+       u8 tmp, iphc0, iphc1, *hc06_ptr;
+       struct ipv6hdr *hdr;
+       u8 head[100] = {};
+
+       if (type != ETH_P_IPV6)
+               return -EINVAL;
+
+       hdr = ipv6_hdr(skb);
+       hc06_ptr = head + 2;
+
+       pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n"
+                "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
+               hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
+               hdr->hop_limit, &hdr->daddr);
+
+       raw_dump_table(__func__, "raw skb network header dump",
+               skb_network_header(skb), sizeof(struct ipv6hdr));
+
+       /*
+        * As we copy some bit-length fields, in the IPHC encoding bytes,
+        * we sometimes use |=
+        * If the field is 0, and the current bit value in memory is 1,
+        * this does not work. We therefore reset the IPHC encoding here
+        */
+       iphc0 = LOWPAN_DISPATCH_IPHC;
+       iphc1 = 0;
+
+       /* TODO: context lookup */
+
+       raw_dump_inline(__func__, "saddr",
+                       (unsigned char *)_saddr, IEEE802154_ADDR_LEN);
+       raw_dump_inline(__func__, "daddr",
+                       (unsigned char *)_daddr, IEEE802154_ADDR_LEN);
+
+       raw_dump_table(__func__,
+                       "sending raw skb network uncompressed packet",
+                       skb->data, skb->len);
+
+       /*
+        * Traffic class, flow label
+        * If flow label is 0, compress it. If traffic class is 0, compress it
+        * We have to process both in the same time as the offset of traffic
+        * class depends on the presence of version and flow label
+        */
+
+       /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */
+       tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
+       tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
+
+       if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
+            (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
+               /* flow label can be compressed */
+               iphc0 |= LOWPAN_IPHC_FL_C;
+               if ((hdr->priority == 0) &&
+                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+                       /* compress (elide) all */
+                       iphc0 |= LOWPAN_IPHC_TC_C;
+               } else {
+                       /* compress only the flow label */
+                       *hc06_ptr = tmp;
+                       hc06_ptr += 1;
+               }
+       } else {
+               /* Flow label cannot be compressed */
+               if ((hdr->priority == 0) &&
+                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+                       /* compress only traffic class */
+                       iphc0 |= LOWPAN_IPHC_TC_C;
+                       *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
+                       memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2);
+                       hc06_ptr += 3;
+               } else {
+                       /* compress nothing */
+                       memcpy(hc06_ptr, &hdr, 4);
+                       /* replace the top byte with new ECN | DSCP format */
+                       *hc06_ptr = tmp;
+                       hc06_ptr += 4;
+               }
+       }
+
+       /* NOTE: payload length is always compressed */
+
+       /* Next Header is compress if UDP */
+       if (hdr->nexthdr == UIP_PROTO_UDP)
+               iphc0 |= LOWPAN_IPHC_NH_C;
+
+       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+               *hc06_ptr = hdr->nexthdr;
+               hc06_ptr += 1;
+       }
+
+       /*
+        * Hop limit
+        * if 1:   compress, encoding is 01
+        * if 64:  compress, encoding is 10
+        * if 255: compress, encoding is 11
+        * else do not compress
+        */
+       switch (hdr->hop_limit) {
+       case 1:
+               iphc0 |= LOWPAN_IPHC_TTL_1;
+               break;
+       case 64:
+               iphc0 |= LOWPAN_IPHC_TTL_64;
+               break;
+       case 255:
+               iphc0 |= LOWPAN_IPHC_TTL_255;
+               break;
+       default:
+               *hc06_ptr = hdr->hop_limit;
+               hc06_ptr += 1;
+               break;
+       }
+
+       /* source address compression */
+       if (is_addr_unspecified(&hdr->saddr)) {
+               pr_debug("source address is unspecified, setting SAC\n");
+               iphc1 |= LOWPAN_IPHC_SAC;
+       /* TODO: context lookup */
+       } else if (is_addr_link_local(&hdr->saddr)) {
+               iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+                               LOWPAN_IPHC_SAM_BIT, &hdr->saddr, _saddr);
+               pr_debug("source address unicast link-local %pI6c "
+                       "iphc1 0x%02x\n", &hdr->saddr, iphc1);
+       } else {
+               pr_debug("send the full source address\n");
+               memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16);
+               hc06_ptr += 16;
+       }
+
+       /* destination address compression */
+       if (is_addr_mcast(&hdr->daddr)) {
+               pr_debug("destination address is multicast: ");
+               iphc1 |= LOWPAN_IPHC_M;
+               if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
+                       pr_debug("compressed to 1 octet\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_11;
+                       /* use last byte */
+                       *hc06_ptr = hdr->daddr.s6_addr[15];
+                       hc06_ptr += 1;
+               } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
+                       pr_debug("compressed to 4 octets\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_10;
+                       /* second byte + the last three */
+                       *hc06_ptr = hdr->daddr.s6_addr[1];
+                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3);
+                       hc06_ptr += 4;
+               } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
+                       pr_debug("compressed to 6 octets\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_01;
+                       /* second byte + the last five */
+                       *hc06_ptr = hdr->daddr.s6_addr[1];
+                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5);
+                       hc06_ptr += 6;
+               } else {
+                       pr_debug("using full address\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_00;
+                       memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16);
+                       hc06_ptr += 16;
+               }
+       } else {
+               /* TODO: context lookup */
+               if (is_addr_link_local(&hdr->daddr)) {
+                       iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+                               LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr);
+                       pr_debug("dest address unicast link-local %pI6c "
+                               "iphc1 0x%02x\n", &hdr->daddr, iphc1);
+               } else {
+                       pr_debug("dest address unicast %pI6c\n", &hdr->daddr);
+                       memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16);
+                       hc06_ptr += 16;
+               }
+       }
+
+       /* UDP header compression */
+       if (hdr->nexthdr == UIP_PROTO_UDP)
+               compress_udp_header(&hc06_ptr, skb);
+
+       head[0] = iphc0;
+       head[1] = iphc1;
+
+       skb_pull(skb, sizeof(struct ipv6hdr));
+       skb_reset_transport_header(skb);
+       memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
+       skb_reset_network_header(skb);
+
+       pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len);
+
+       raw_dump_table(__func__, "raw skb data dump compressed",
+                               skb->data, skb->len);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lowpan_header_compress);
index d7716d64c6bb2c38848695378d6634bfa958afd6..951a83ee8af4fb35c8dabc459c5c2d257f452eb7 100644 (file)
@@ -1,5 +1,5 @@
 obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o
-obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o
+obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o 6lowpan_iphc.o
 
 ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
 af_802154-y := af_ieee802154.o raw.o dgram.o
index ef56ab5b35fe759c446089b68cefdc585d21c175..4dd37615a749c6f1191d5ce35bec09ca9ac05e81 100644 (file)
@@ -46,7 +46,7 @@ MASTER_SHOW(current_channel, "%d");
 MASTER_SHOW(current_page, "%d");
 MASTER_SHOW_COMPLEX(transmit_power, "%d +- %d dB",
        ((signed char) (phy->transmit_power << 2)) >> 2,
-       (phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1 );
+       (phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1);
 MASTER_SHOW(cca_mode, "%d");
 
 static ssize_t channels_supported_show(struct device *dev,
index 4b81e91c80fe4ea21683a403af59330882904b1b..f8c49ce5b2839f96b5147185cfbb0402bba23da8 100644 (file)
@@ -11,7 +11,7 @@ obj-y     := route.o inetpeer.o protocol.o \
             tcp_offload.o datagram.o raw.o udp.o udplite.o \
             udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \
             fib_frontend.o fib_semantics.o fib_trie.o \
-            inet_fragment.o ping.o ip_tunnel_core.o
+            inet_fragment.o ping.o ip_tunnel_core.o gre_offload.o
 
 obj-$(CONFIG_NET_IP_TUNNEL) += ip_tunnel.o
 obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
@@ -19,7 +19,7 @@ obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
 obj-$(CONFIG_IP_MROUTE) += ipmr.o
 obj-$(CONFIG_NET_IPIP) += ipip.o
-gre-y := gre_demux.o gre_offload.o
+gre-y := gre_demux.o
 obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
 obj-$(CONFIG_NET_IPGRE) += ip_gre.o
 obj-$(CONFIG_NET_IPVTI) += ip_vti.o
index b8bc1a3d5cf1446dc57f0e57927c5224736b9f9c..ecd2c3f245ce2b2e0b79f17417c5e6ad8c70abf6 100644 (file)
@@ -1391,9 +1391,15 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
                NAPI_GRO_CB(p)->flush |=
                        (iph->ttl ^ iph2->ttl) |
                        (iph->tos ^ iph2->tos) |
-                       (__force int)((iph->frag_off ^ iph2->frag_off) & htons(IP_DF)) |
-                       ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id);
+                       ((iph->frag_off ^ iph2->frag_off) & htons(IP_DF));
 
+               /* Save the IP ID check to be included later when we get to
+                * the transport layer so only the inner most IP ID is checked.
+                * This is because some GSO/TSO implementations do not
+                * correctly increment the IP ID for the outer hdrs.
+                */
+               NAPI_GRO_CB(p)->flush_id =
+                           ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id);
                NAPI_GRO_CB(p)->flush |= flush;
        }
 
@@ -1539,6 +1545,7 @@ static const struct net_protocol tcp_protocol = {
        .err_handler    =       tcp_v4_err,
        .no_policy      =       1,
        .netns_ok       =       1,
+       .icmp_strict_tag_validation = 1,
 };
 
 static const struct net_protocol udp_protocol = {
index b67cf805910e1f962755cbc26f793be6a01a4c6a..1a9b99e04465a1eb7f8a197bdc7ca6f1bd6978f0 100644 (file)
@@ -732,6 +732,7 @@ static int arp_process(struct sk_buff *skb)
        int addr_type;
        struct neighbour *n;
        struct net *net = dev_net(dev);
+       bool is_garp = false;
 
        /* arp_rcv below verifies the ARP header and verifies the device
         * is ARP'able.
@@ -898,10 +899,12 @@ static int arp_process(struct sk_buff *skb)
                   It is possible, that this option should be enabled for some
                   devices (strip is candidate)
                 */
+               is_garp = arp->ar_op == htons(ARPOP_REQUEST) && tip == sip &&
+                         inet_addr_type(net, sip) == RTN_UNICAST;
+
                if (n == NULL &&
-                   (arp->ar_op == htons(ARPOP_REPLY) ||
-                    (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) &&
-                   inet_addr_type(net, sip) == RTN_UNICAST)
+                   ((arp->ar_op == htons(ARPOP_REPLY)  &&
+                     inet_addr_type(net, sip) == RTN_UNICAST) || is_garp))
                        n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
        }
 
@@ -914,8 +917,10 @@ static int arp_process(struct sk_buff *skb)
                   agents are active. Taking the first reply prevents
                   arp trashing and chooses the fastest router.
                 */
-               override = time_after(jiffies, n->updated +
-                                              NEIGH_VAR(n->parms, LOCKTIME));
+               override = time_after(jiffies,
+                                     n->updated +
+                                     NEIGH_VAR(n->parms, LOCKTIME)) ||
+                          is_garp;
 
                /* Broadcast replies and request packets
                   do not assert neighbour reachability.
@@ -1112,7 +1117,7 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev)
        return err;
 }
 
-int arp_invalidate(struct net_device *dev, __be32 ip)
+static int arp_invalidate(struct net_device *dev, __be32 ip)
 {
        struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev);
        int err = -ENXIO;
@@ -1127,7 +1132,6 @@ int arp_invalidate(struct net_device *dev, __be32 ip)
 
        return err;
 }
-EXPORT_SYMBOL(arp_invalidate);
 
 static int arp_req_delete_public(struct net *net, struct arpreq *r,
                struct net_device *dev)
index 4b59b6e488d3e61ec919a263a0e1c347d9335e43..69e77c8ff285c74a3743cd10b95cfd04a45bf687 100644 (file)
@@ -1335,8 +1335,7 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
 
        if (tag_len > 4) {
-               secattr->attr.mls.cat =
-                                      netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+               secattr->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
                if (secattr->attr.mls.cat == NULL)
                        return -ENOMEM;
 
@@ -1431,8 +1430,7 @@ static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
 
        if (tag_len > 4) {
-               secattr->attr.mls.cat =
-                                      netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+               secattr->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
                if (secattr->attr.mls.cat == NULL)
                        return -ENOMEM;
 
@@ -1526,8 +1524,7 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
 
        if (tag_len > 4) {
-               secattr->attr.mls.cat =
-                                      netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+               secattr->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
                if (secattr->attr.mls.cat == NULL)
                        return -ENOMEM;
 
index de03fe7002d049b9726a2329231f7dee8903c5f5..9809f7b69728cb335e0963c92ea4c9522842849f 100644 (file)
@@ -1385,6 +1385,8 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
                                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
                                set_ifa_lifetime(ifa, INFINITY_LIFE_TIME,
                                                 INFINITY_LIFE_TIME);
+                               ipv4_devconf_setall(in_dev);
+                               neigh_parms_data_state_setall(in_dev->arp_parms);
                                inet_insert_ifa(ifa);
                        }
                }
@@ -1696,7 +1698,7 @@ static int inet_netconf_msgsize_devconf(int type)
                size += nla_total_size(4);
        if (type == -1 || type == NETCONFA_MC_FORWARDING)
                size += nla_total_size(4);
-       if (type == -1 || type == NETCONFA_PROXY_ARP)
+       if (type == -1 || type == NETCONFA_PROXY_NEIGH)
                size += nla_total_size(4);
 
        return size;
@@ -1734,8 +1736,8 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
            nla_put_s32(skb, NETCONFA_MC_FORWARDING,
                        IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0)
                goto nla_put_failure;
-       if ((type == -1 || type == NETCONFA_PROXY_ARP) &&
-           nla_put_s32(skb, NETCONFA_PROXY_ARP,
+       if ((type == -1 || type == NETCONFA_PROXY_NEIGH) &&
+           nla_put_s32(skb, NETCONFA_PROXY_NEIGH,
                        IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0)
                goto nla_put_failure;
 
@@ -1775,7 +1777,7 @@ static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = {
        [NETCONFA_IFINDEX]      = { .len = sizeof(int) },
        [NETCONFA_FORWARDING]   = { .len = sizeof(int) },
        [NETCONFA_RP_FILTER]    = { .len = sizeof(int) },
-       [NETCONFA_PROXY_ARP]    = { .len = sizeof(int) },
+       [NETCONFA_PROXY_NEIGH]  = { .len = sizeof(int) },
 };
 
 static int inet_netconf_get_devconf(struct sk_buff *in_skb,
@@ -2002,7 +2004,7 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write,
                if (i == IPV4_DEVCONF_PROXY_ARP - 1 &&
                    new_value != old_value) {
                        ifindex = devinet_conf_ifindex(net, cnf);
-                       inet_netconf_notify_devconf(net, NETCONFA_PROXY_ARP,
+                       inet_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
                                                    ifindex, cnf);
                }
        }
index 388d113fd289b9134cf34e930a26c6c99b7ea721..1e4f6600b31d4929cce729dcb38a3227b0de0a48 100644 (file)
@@ -33,8 +33,6 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, u32 tb_id,
 void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, int dst_len,
               u32 tb_id, const struct nl_info *info, unsigned int nlm_flags);
 struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio);
-int fib_detect_death(struct fib_info *fi, int order,
-                    struct fib_info **last_resort, int *last_idx, int dflt);
 
 static inline void fib_result_assign(struct fib_result *res,
                                     struct fib_info *fi)
index e63f47a4e651f2c5587723f7796e2fd9ec43b4f8..b53f0bf84dcaba3fd2767dd734add99d05db9fa6 100644 (file)
@@ -426,8 +426,9 @@ struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio)
        return NULL;
 }
 
-int fib_detect_death(struct fib_info *fi, int order,
-                    struct fib_info **last_resort, int *last_idx, int dflt)
+static int fib_detect_death(struct fib_info *fi, int order,
+                           struct fib_info **last_resort, int *last_idx,
+                           int dflt)
 {
        struct neighbour *n;
        int state = NUD_NONE;
index 5893e99e82990ae75f4221249e3e5fcbceb819c4..1863422fb7d553340151b1402ee30d4be1fcde29 100644 (file)
@@ -355,14 +355,7 @@ static int __init gre_init(void)
                goto err_gre;
        }
 
-       if (gre_offload_init()) {
-               pr_err("can't add protocol offload\n");
-               goto err_gso;
-       }
-
        return 0;
-err_gso:
-       gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
 err_gre:
        inet_del_protocol(&net_gre_protocol, IPPROTO_GRE);
 err:
@@ -371,8 +364,6 @@ err:
 
 static void __exit gre_exit(void)
 {
-       gre_offload_exit();
-
        gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
        inet_del_protocol(&net_gre_protocol, IPPROTO_GRE);
 }
index e5d436188464eba55eca773f4fb88fd0f0634e97..29512e3e7e7c6f598854d4d3eafd4e4047fc6440 100644 (file)
@@ -26,8 +26,9 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        netdev_features_t enc_features;
-       int ghl = GRE_HEADER_SECTION;
+       int ghl;
        struct gre_base_hdr *greh;
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        __be16 protocol = skb->protocol;
        int tnl_hlen;
@@ -48,23 +49,19 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 
        greh = (struct gre_base_hdr *)skb_transport_header(skb);
 
-       if (greh->flags & GRE_KEY)
-               ghl += GRE_HEADER_SECTION;
-       if (greh->flags & GRE_SEQ)
-               ghl += GRE_HEADER_SECTION;
-       if (greh->flags & GRE_CSUM) {
-               ghl += GRE_HEADER_SECTION;
-               csum = true;
-       } else
-               csum = false;
+       ghl = skb_inner_network_header(skb) - skb_transport_header(skb);
+       if (unlikely(ghl < sizeof(*greh)))
+               goto out;
 
-       /* setup inner skb. */
-       skb->protocol = greh->protocol;
-       skb->encapsulation = 0;
+       csum = !!(greh->flags & GRE_CSUM);
 
        if (unlikely(!pskb_may_pull(skb, ghl)))
                goto out;
 
+       /* setup inner skb. */
+       skb->protocol = greh->protocol;
+       skb->encapsulation = 0;
+
        __skb_pull(skb, ghl);
        skb_reset_mac_header(skb);
        skb_set_network_header(skb, skb_inner_network_offset(skb));
@@ -73,8 +70,10 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len);
                goto out;
+       }
 
        skb = segs;
        tnl_hlen = skb_tnl_header_len(skb);
@@ -113,19 +112,182 @@ out:
        return segs;
 }
 
+/* Compute the whole skb csum in s/w and store it, then verify GRO csum
+ * starting from gro_offset.
+ */
+static __sum16 gro_skb_checksum(struct sk_buff *skb)
+{
+       __sum16 sum;
+
+       skb->csum = skb_checksum(skb, 0, skb->len, 0);
+       NAPI_GRO_CB(skb)->csum = csum_sub(skb->csum,
+               csum_partial(skb->data, skb_gro_offset(skb), 0));
+       sum = csum_fold(NAPI_GRO_CB(skb)->csum);
+       if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) {
+               if (unlikely(!sum))
+                       netdev_rx_csum_fault(skb->dev);
+       } else
+               skb->ip_summed = CHECKSUM_COMPLETE;
+
+       return sum;
+}
+
+static struct sk_buff **gre_gro_receive(struct sk_buff **head,
+                                       struct sk_buff *skb)
+{
+       struct sk_buff **pp = NULL;
+       struct sk_buff *p;
+       const struct gre_base_hdr *greh;
+       unsigned int hlen, grehlen;
+       unsigned int off;
+       int flush = 1;
+       struct packet_offload *ptype;
+       __be16 type;
+
+       off = skb_gro_offset(skb);
+       hlen = off + sizeof(*greh);
+       greh = skb_gro_header_fast(skb, off);
+       if (skb_gro_header_hard(skb, hlen)) {
+               greh = skb_gro_header_slow(skb, hlen, off);
+               if (unlikely(!greh))
+                       goto out;
+       }
+
+       /* Only support version 0 and K (key), C (csum) flags. Note that
+        * although the support for the S (seq#) flag can be added easily
+        * for GRO, this is problematic for GSO hence can not be enabled
+        * here because a GRO pkt may end up in the forwarding path, thus
+        * requiring GSO support to break it up correctly.
+        */
+       if ((greh->flags & ~(GRE_KEY|GRE_CSUM)) != 0)
+               goto out;
+
+       type = greh->protocol;
+
+       rcu_read_lock();
+       ptype = gro_find_receive_by_type(type);
+       if (ptype == NULL)
+               goto out_unlock;
+
+       grehlen = GRE_HEADER_SECTION;
+
+       if (greh->flags & GRE_KEY)
+               grehlen += GRE_HEADER_SECTION;
+
+       if (greh->flags & GRE_CSUM)
+               grehlen += GRE_HEADER_SECTION;
+
+       hlen = off + grehlen;
+       if (skb_gro_header_hard(skb, hlen)) {
+               greh = skb_gro_header_slow(skb, hlen, off);
+               if (unlikely(!greh))
+                       goto out_unlock;
+       }
+       if (greh->flags & GRE_CSUM) { /* Need to verify GRE csum first */
+               __sum16 csum = 0;
+
+               if (skb->ip_summed == CHECKSUM_COMPLETE)
+                       csum = csum_fold(NAPI_GRO_CB(skb)->csum);
+               /* Don't trust csum error calculated/reported by h/w */
+               if (skb->ip_summed == CHECKSUM_NONE || csum != 0)
+                       csum = gro_skb_checksum(skb);
+
+               /* GRE CSUM is the 1's complement of the 1's complement sum
+                * of the GRE hdr plus payload so it should add up to 0xffff
+                * (and 0 after csum_fold()) just like the IPv4 hdr csum.
+                */
+               if (csum)
+                       goto out_unlock;
+       }
+       flush = 0;
+
+       for (p = *head; p; p = p->next) {
+               const struct gre_base_hdr *greh2;
+
+               if (!NAPI_GRO_CB(p)->same_flow)
+                       continue;
+
+               /* The following checks are needed to ensure only pkts
+                * from the same tunnel are considered for aggregation.
+                * The criteria for "the same tunnel" includes:
+                * 1) same version (we only support version 0 here)
+                * 2) same protocol (we only support ETH_P_IP for now)
+                * 3) same set of flags
+                * 4) same key if the key field is present.
+                */
+               greh2 = (struct gre_base_hdr *)(p->data + off);
+
+               if (greh2->flags != greh->flags ||
+                   greh2->protocol != greh->protocol) {
+                       NAPI_GRO_CB(p)->same_flow = 0;
+                       continue;
+               }
+               if (greh->flags & GRE_KEY) {
+                       /* compare keys */
+                       if (*(__be32 *)(greh2+1) != *(__be32 *)(greh+1)) {
+                               NAPI_GRO_CB(p)->same_flow = 0;
+                               continue;
+                       }
+               }
+       }
+
+       skb_gro_pull(skb, grehlen);
+
+       /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/
+       skb_gro_postpull_rcsum(skb, greh, grehlen);
+
+       pp = ptype->callbacks.gro_receive(head, skb);
+
+out_unlock:
+       rcu_read_unlock();
+out:
+       NAPI_GRO_CB(skb)->flush |= flush;
+
+       return pp;
+}
+
+static int gre_gro_complete(struct sk_buff *skb, int nhoff)
+{
+       struct gre_base_hdr *greh = (struct gre_base_hdr *)(skb->data + nhoff);
+       struct packet_offload *ptype;
+       unsigned int grehlen = sizeof(*greh);
+       int err = -ENOENT;
+       __be16 type;
+
+       type = greh->protocol;
+       if (greh->flags & GRE_KEY)
+               grehlen += GRE_HEADER_SECTION;
+
+       if (greh->flags & GRE_CSUM)
+               grehlen += GRE_HEADER_SECTION;
+
+       rcu_read_lock();
+       ptype = gro_find_complete_by_type(type);
+       if (ptype != NULL)
+               err = ptype->callbacks.gro_complete(skb, nhoff + grehlen);
+
+       rcu_read_unlock();
+       return err;
+}
+
 static const struct net_offload gre_offload = {
        .callbacks = {
                .gso_send_check = gre_gso_send_check,
                .gso_segment = gre_gso_segment,
+               .gro_receive = gre_gro_receive,
+               .gro_complete = gre_gro_complete,
        },
 };
 
-int __init gre_offload_init(void)
+static int __init gre_offload_init(void)
 {
        return inet_add_offload(&gre_offload, IPPROTO_GRE);
 }
 
-void __exit gre_offload_exit(void)
+static void __exit gre_offload_exit(void)
 {
        inet_del_offload(&gre_offload, IPPROTO_GRE);
 }
+
+module_init(gre_offload_init);
+module_exit(gre_offload_exit);
index fb3c5637199dbfacd7b7b5c40ae14b1b2880d178..0134663fdbce86f6da39d8f6c9d27ce6c404687c 100644 (file)
@@ -668,6 +668,16 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
        rcu_read_unlock();
 }
 
+static bool icmp_tag_validation(int proto)
+{
+       bool ok;
+
+       rcu_read_lock();
+       ok = rcu_dereference(inet_protos[proto])->icmp_strict_tag_validation;
+       rcu_read_unlock();
+       return ok;
+}
+
 /*
  *     Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, ICMP_QUENCH, and
  *     ICMP_PARAMETERPROB.
@@ -705,12 +715,22 @@ static void icmp_unreach(struct sk_buff *skb)
                case ICMP_PORT_UNREACH:
                        break;
                case ICMP_FRAG_NEEDED:
-                       if (net->ipv4.sysctl_ip_no_pmtu_disc == 2) {
-                               goto out;
-                       } else if (net->ipv4.sysctl_ip_no_pmtu_disc) {
+                       /* for documentation of the ip_no_pmtu_disc
+                        * values please see
+                        * Documentation/networking/ip-sysctl.txt
+                        */
+                       switch (net->ipv4.sysctl_ip_no_pmtu_disc) {
+                       default:
                                LIMIT_NETDEBUG(KERN_INFO pr_fmt("%pI4: fragmentation needed and DF set\n"),
                                               &iph->daddr);
-                       } else {
+                               break;
+                       case 2:
+                               goto out;
+                       case 3:
+                               if (!icmp_tag_validation(iph->protocol))
+                                       goto out;
+                               /* fall through */
+                       case 0:
                                info = ntohs(icmph->un.frag.mtu);
                                if (!info)
                                        goto out;
index 7defdc9ba16744fd263c539c37f125fc31422c87..84c4329cbd30f59b2642b60a4c90473b9ba8d0b6 100644 (file)
@@ -310,7 +310,7 @@ igmp_scount(struct ip_mc_list *pmc, int type, int gdeleted, int sdeleted)
        struct ip_sf_list *psf;
        int scount = 0;
 
-       for (psf=pmc->sources; psf; psf=psf->sf_next) {
+       for (psf = pmc->sources; psf; psf = psf->sf_next) {
                if (!is_in(pmc, psf, type, gdeleted, sdeleted))
                        continue;
                scount++;
@@ -463,7 +463,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
        }
        first = 1;
        psf_prev = NULL;
-       for (psf=*psf_list; psf; psf=psf_next) {
+       for (psf = *psf_list; psf; psf = psf_next) {
                __be32 *psrc;
 
                psf_next = psf->sf_next;
@@ -520,7 +520,7 @@ empty_source:
                        return skb;
                if (pmc->crcount || isquery) {
                        /* make sure we have room for group header */
-                       if (skb && AVAILABLE(skb)<sizeof(struct igmpv3_grec)) {
+                       if (skb && AVAILABLE(skb) < sizeof(struct igmpv3_grec)) {
                                igmpv3_sendpack(skb);
                                skb = NULL; /* add_grhead will get a new one */
                        }
@@ -576,7 +576,7 @@ static void igmpv3_clear_zeros(struct ip_sf_list **ppsf)
        struct ip_sf_list *psf_prev, *psf_next, *psf;
 
        psf_prev = NULL;
-       for (psf=*ppsf; psf; psf = psf_next) {
+       for (psf = *ppsf; psf; psf = psf_next) {
                psf_next = psf->sf_next;
                if (psf->sf_crcount == 0) {
                        if (psf_prev)
@@ -600,7 +600,7 @@ static void igmpv3_send_cr(struct in_device *in_dev)
 
        /* deleted MCA's */
        pmc_prev = NULL;
-       for (pmc=in_dev->mc_tomb; pmc; pmc=pmc_next) {
+       for (pmc = in_dev->mc_tomb; pmc; pmc = pmc_next) {
                pmc_next = pmc->next;
                if (pmc->sfmode == MCAST_INCLUDE) {
                        type = IGMPV3_BLOCK_OLD_SOURCES;
@@ -764,7 +764,7 @@ static void igmp_ifc_event(struct in_device *in_dev)
 
 static void igmp_timer_expire(unsigned long data)
 {
-       struct ip_mc_list *im=(struct ip_mc_list *)data;
+       struct ip_mc_list *im = (struct ip_mc_list *)data;
        struct in_device *in_dev = im->interface;
 
        spin_lock(&im->lock);
@@ -794,10 +794,10 @@ static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
        int i, scount;
 
        scount = 0;
-       for (psf=pmc->sources; psf; psf=psf->sf_next) {
+       for (psf = pmc->sources; psf; psf = psf->sf_next) {
                if (scount == nsrcs)
                        break;
-               for (i=0; i<nsrcs; i++) {
+               for (i = 0; i < nsrcs; i++) {
                        /* skip inactive filters */
                        if (psf->sf_count[MCAST_INCLUDE] ||
                            pmc->sfcount[MCAST_EXCLUDE] !=
@@ -825,10 +825,10 @@ static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
 
        /* mark INCLUDE-mode sources */
        scount = 0;
-       for (psf=pmc->sources; psf; psf=psf->sf_next) {
+       for (psf = pmc->sources; psf; psf = psf->sf_next) {
                if (scount == nsrcs)
                        break;
-               for (i=0; i<nsrcs; i++)
+               for (i = 0; i < nsrcs; i++)
                        if (srcs[i] == psf->sf_inaddr) {
                                psf->sf_gsresp = 1;
                                scount++;
@@ -1103,7 +1103,7 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im)
                pmc->tomb = im->tomb;
                pmc->sources = im->sources;
                im->tomb = im->sources = NULL;
-               for (psf=pmc->sources; psf; psf=psf->sf_next)
+               for (psf = pmc->sources; psf; psf = psf->sf_next)
                        psf->sf_crcount = pmc->crcount;
        }
        spin_unlock_bh(&im->lock);
@@ -1121,7 +1121,7 @@ static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr)
 
        spin_lock_bh(&in_dev->mc_tomb_lock);
        pmc_prev = NULL;
-       for (pmc=in_dev->mc_tomb; pmc; pmc=pmc->next) {
+       for (pmc = in_dev->mc_tomb; pmc; pmc = pmc->next) {
                if (pmc->multiaddr == multiaddr)
                        break;
                pmc_prev = pmc;
@@ -1134,7 +1134,7 @@ static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr)
        }
        spin_unlock_bh(&in_dev->mc_tomb_lock);
        if (pmc) {
-               for (psf=pmc->tomb; psf; psf=psf_next) {
+               for (psf = pmc->tomb; psf; psf = psf_next) {
                        psf_next = psf->sf_next;
                        kfree(psf);
                }
@@ -1167,7 +1167,7 @@ static void igmpv3_clear_delrec(struct in_device *in_dev)
                psf = pmc->tomb;
                pmc->tomb = NULL;
                spin_unlock_bh(&pmc->lock);
-               for (; psf; psf=psf_next) {
+               for (; psf; psf = psf_next) {
                        psf_next = psf->sf_next;
                        kfree(psf);
                }
@@ -1557,7 +1557,7 @@ static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
        int rv = 0;
 
        psf_prev = NULL;
-       for (psf=pmc->sources; psf; psf=psf->sf_next) {
+       for (psf = pmc->sources; psf; psf = psf->sf_next) {
                if (psf->sf_inaddr == *psfsrc)
                        break;
                psf_prev = psf;
@@ -1630,7 +1630,7 @@ static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
                pmc->sfcount[sfmode]--;
        }
        err = 0;
-       for (i=0; i<sfcount; i++) {
+       for (i = 0; i < sfcount; i++) {
                int rv = ip_mc_del1_src(pmc, sfmode, &psfsrc[i]);
 
                changerec |= rv > 0;
@@ -1650,7 +1650,7 @@ static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
                pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
                        IGMP_Unsolicited_Report_Count;
                in_dev->mr_ifc_count = pmc->crcount;
-               for (psf=pmc->sources; psf; psf = psf->sf_next)
+               for (psf = pmc->sources; psf; psf = psf->sf_next)
                        psf->sf_crcount = 0;
                igmp_ifc_event(pmc->interface);
        } else if (sf_setstate(pmc) || changerec) {
@@ -1671,7 +1671,7 @@ static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode,
        struct ip_sf_list *psf, *psf_prev;
 
        psf_prev = NULL;
-       for (psf=pmc->sources; psf; psf=psf->sf_next) {
+       for (psf = pmc->sources; psf; psf = psf->sf_next) {
                if (psf->sf_inaddr == *psfsrc)
                        break;
                psf_prev = psf;
@@ -1699,7 +1699,7 @@ static void sf_markstate(struct ip_mc_list *pmc)
        struct ip_sf_list *psf;
        int mca_xcount = pmc->sfcount[MCAST_EXCLUDE];
 
-       for (psf=pmc->sources; psf; psf=psf->sf_next)
+       for (psf = pmc->sources; psf; psf = psf->sf_next)
                if (pmc->sfcount[MCAST_EXCLUDE]) {
                        psf->sf_oldin = mca_xcount ==
                                psf->sf_count[MCAST_EXCLUDE] &&
@@ -1716,7 +1716,7 @@ static int sf_setstate(struct ip_mc_list *pmc)
        int new_in, rv;
 
        rv = 0;
-       for (psf=pmc->sources; psf; psf=psf->sf_next) {
+       for (psf = pmc->sources; psf; psf = psf->sf_next) {
                if (pmc->sfcount[MCAST_EXCLUDE]) {
                        new_in = mca_xcount == psf->sf_count[MCAST_EXCLUDE] &&
                                !psf->sf_count[MCAST_INCLUDE];
@@ -1726,7 +1726,7 @@ static int sf_setstate(struct ip_mc_list *pmc)
                        if (!psf->sf_oldin) {
                                struct ip_sf_list *prev = NULL;
 
-                               for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next) {
+                               for (dpsf = pmc->tomb; dpsf; dpsf = dpsf->sf_next) {
                                        if (dpsf->sf_inaddr == psf->sf_inaddr)
                                                break;
                                        prev = dpsf;
@@ -1748,7 +1748,7 @@ static int sf_setstate(struct ip_mc_list *pmc)
                         * add or update "delete" records if an active filter
                         * is now inactive
                         */
-                       for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next)
+                       for (dpsf = pmc->tomb; dpsf; dpsf = dpsf->sf_next)
                                if (dpsf->sf_inaddr == psf->sf_inaddr)
                                        break;
                        if (!dpsf) {
@@ -1800,7 +1800,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
        if (!delta)
                pmc->sfcount[sfmode]++;
        err = 0;
-       for (i=0; i<sfcount; i++) {
+       for (i = 0; i < sfcount; i++) {
                err = ip_mc_add1_src(pmc, sfmode, &psfsrc[i]);
                if (err)
                        break;
@@ -1810,7 +1810,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
 
                if (!delta)
                        pmc->sfcount[sfmode]--;
-               for (j=0; j<i; j++)
+               for (j = 0; j < i; j++)
                        (void) ip_mc_del1_src(pmc, sfmode, &psfsrc[j]);
        } else if (isexclude != (pmc->sfcount[MCAST_EXCLUDE] != 0)) {
 #ifdef CONFIG_IP_MULTICAST
@@ -1829,7 +1829,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
                pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
                        IGMP_Unsolicited_Report_Count;
                in_dev->mr_ifc_count = pmc->crcount;
-               for (psf=pmc->sources; psf; psf = psf->sf_next)
+               for (psf = pmc->sources; psf; psf = psf->sf_next)
                        psf->sf_crcount = 0;
                igmp_ifc_event(in_dev);
        } else if (sf_setstate(pmc)) {
@@ -1844,12 +1844,12 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc)
 {
        struct ip_sf_list *psf, *nextpsf;
 
-       for (psf=pmc->tomb; psf; psf=nextpsf) {
+       for (psf = pmc->tomb; psf; psf = nextpsf) {
                nextpsf = psf->sf_next;
                kfree(psf);
        }
        pmc->tomb = NULL;
-       for (psf=pmc->sources; psf; psf=nextpsf) {
+       for (psf = pmc->sources; psf; psf = nextpsf) {
                nextpsf = psf->sf_next;
                kfree(psf);
        }
@@ -2043,7 +2043,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                if (!psl)
                        goto done;      /* err = -EADDRNOTAVAIL */
                rv = !0;
-               for (i=0; i<psl->sl_count; i++) {
+               for (i = 0; i < psl->sl_count; i++) {
                        rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
                                sizeof(__be32));
                        if (rv == 0)
@@ -2062,7 +2062,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
                        &mreqs->imr_sourceaddr, 1);
 
-               for (j=i+1; j<psl->sl_count; j++)
+               for (j = i+1; j < psl->sl_count; j++)
                        psl->sl_addr[j-1] = psl->sl_addr[j];
                psl->sl_count--;
                err = 0;
@@ -2088,7 +2088,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                newpsl->sl_max = count;
                newpsl->sl_count = count - IP_SFBLOCK;
                if (psl) {
-                       for (i=0; i<psl->sl_count; i++)
+                       for (i = 0; i < psl->sl_count; i++)
                                newpsl->sl_addr[i] = psl->sl_addr[i];
                        /* decrease mem now to avoid the memleak warning */
                        atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
@@ -2098,7 +2098,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                psl = newpsl;
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
-       for (i=0; i<psl->sl_count; i++) {
+       for (i = 0; i < psl->sl_count; i++) {
                rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
                        sizeof(__be32));
                if (rv == 0)
@@ -2106,7 +2106,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
        }
        if (rv == 0)            /* address already there is an error */
                goto done;
-       for (j=psl->sl_count-1; j>=i; j--)
+       for (j = psl->sl_count-1; j >= i; j--)
                psl->sl_addr[j+1] = psl->sl_addr[j];
        psl->sl_addr[i] = mreqs->imr_sourceaddr;
        psl->sl_count++;
@@ -2305,7 +2305,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
            copy_to_user(optval, gsf, GROUP_FILTER_SIZE(0))) {
                return -EFAULT;
        }
-       for (i=0; i<copycount; i++) {
+       for (i = 0; i < copycount; i++) {
                struct sockaddr_storage ss;
 
                psin = (struct sockaddr_in *)&ss;
@@ -2350,7 +2350,7 @@ int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
        if (!psl)
                goto unlock;
 
-       for (i=0; i<psl->sl_count; i++) {
+       for (i = 0; i < psl->sl_count; i++) {
                if (psl->sl_addr[i] == rmt_addr)
                        break;
        }
@@ -2423,7 +2423,7 @@ int ip_check_mc_rcu(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u
                rv = 1;
        } else if (im) {
                if (src_addr) {
-                       for (psf=im->sources; psf; psf=psf->sf_next) {
+                       for (psf = im->sources; psf; psf = psf->sf_next) {
                                if (psf->sf_inaddr == src_addr)
                                        break;
                        }
index 56a964a553d2c739a03b880acd7158a4c9714b66..a0f52dac8940de45ffaa53291c82950b2e6c4c99 100644 (file)
@@ -106,6 +106,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = inet->inet_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = inet->inet_rcv_saddr;
        r->id.idiag_dst[0] = inet->inet_daddr;
 
@@ -240,12 +244,19 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 
        r->idiag_family       = tw->tw_family;
        r->idiag_retrans      = 0;
+
        r->id.idiag_if        = tw->tw_bound_dev_if;
        sock_diag_save_cookie(tw, r->id.idiag_cookie);
+
        r->id.idiag_sport     = tw->tw_sport;
        r->id.idiag_dport     = tw->tw_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0]    = tw->tw_rcv_saddr;
        r->id.idiag_dst[0]    = tw->tw_daddr;
+
        r->idiag_state        = tw->tw_substate;
        r->idiag_timer        = 3;
        r->idiag_expires      = jiffies_to_msecs(tmo);
@@ -726,8 +737,13 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = ireq->ir_rmt_port;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = ireq->ir_loc_addr;
        r->id.idiag_dst[0] = ireq->ir_rmt_addr;
+
        r->idiag_expires = jiffies_to_msecs(tmo);
        r->idiag_rqueue = 0;
        r->idiag_wqueue = 0;
index 1975f52933c59309eac11ece4a6938a1fb3b435d..f17ea49b28fb48100968a92e9cade456527e9cb4 100644 (file)
@@ -230,29 +230,6 @@ static void lro_add_packet(struct net_lro_desc *lro_desc, struct sk_buff *skb,
        lro_desc->last_skb = skb;
 }
 
-static void lro_add_frags(struct net_lro_desc *lro_desc,
-                         int len, int hlen, int truesize,
-                         struct skb_frag_struct *skb_frags,
-                         struct iphdr *iph, struct tcphdr *tcph)
-{
-       struct sk_buff *skb = lro_desc->parent;
-       int tcp_data_len = TCP_PAYLOAD_LENGTH(iph, tcph);
-
-       lro_add_common(lro_desc, iph, tcph, tcp_data_len);
-
-       skb->truesize += truesize;
-
-       skb_frags[0].page_offset += hlen;
-       skb_frag_size_sub(&skb_frags[0], hlen);
-
-       while (tcp_data_len > 0) {
-               *(lro_desc->next_frag) = *skb_frags;
-               tcp_data_len -= skb_frag_size(skb_frags);
-               lro_desc->next_frag++;
-               skb_frags++;
-               skb_shinfo(skb)->nr_frags++;
-       }
-}
 
 static int lro_check_tcp_conn(struct net_lro_desc *lro_desc,
                              struct iphdr *iph,
@@ -371,128 +348,6 @@ out:
        return 1;
 }
 
-
-static struct sk_buff *lro_gen_skb(struct net_lro_mgr *lro_mgr,
-                                  struct skb_frag_struct *frags,
-                                  int len, int true_size,
-                                  void *mac_hdr,
-                                  int hlen, __wsum sum,
-                                  u32 ip_summed)
-{
-       struct sk_buff *skb;
-       struct skb_frag_struct *skb_frags;
-       int data_len = len;
-       int hdr_len = min(len, hlen);
-
-       skb = netdev_alloc_skb(lro_mgr->dev, hlen + lro_mgr->frag_align_pad);
-       if (!skb)
-               return NULL;
-
-       skb_reserve(skb, lro_mgr->frag_align_pad);
-       skb->len = len;
-       skb->data_len = len - hdr_len;
-       skb->truesize += true_size;
-       skb->tail += hdr_len;
-
-       memcpy(skb->data, mac_hdr, hdr_len);
-
-       skb_frags = skb_shinfo(skb)->frags;
-       while (data_len > 0) {
-               *skb_frags = *frags;
-               data_len -= skb_frag_size(frags);
-               skb_frags++;
-               frags++;
-               skb_shinfo(skb)->nr_frags++;
-       }
-
-       skb_shinfo(skb)->frags[0].page_offset += hdr_len;
-       skb_frag_size_sub(&skb_shinfo(skb)->frags[0], hdr_len);
-
-       skb->ip_summed = ip_summed;
-       skb->csum = sum;
-       skb->protocol = eth_type_trans(skb, lro_mgr->dev);
-       return skb;
-}
-
-static struct sk_buff *__lro_proc_segment(struct net_lro_mgr *lro_mgr,
-                                         struct skb_frag_struct *frags,
-                                         int len, int true_size,
-                                         void *priv, __wsum sum)
-{
-       struct net_lro_desc *lro_desc;
-       struct iphdr *iph;
-       struct tcphdr *tcph;
-       struct sk_buff *skb;
-       u64 flags;
-       void *mac_hdr;
-       int mac_hdr_len;
-       int hdr_len = LRO_MAX_PG_HLEN;
-       int vlan_hdr_len = 0;
-
-       if (!lro_mgr->get_frag_header ||
-           lro_mgr->get_frag_header(frags, (void *)&mac_hdr, (void *)&iph,
-                                    (void *)&tcph, &flags, priv)) {
-               mac_hdr = skb_frag_address(frags);
-               goto out1;
-       }
-
-       if (!(flags & LRO_IPV4) || !(flags & LRO_TCP))
-               goto out1;
-
-       hdr_len = (int)((void *)(tcph) + TCP_HDR_LEN(tcph) - mac_hdr);
-       mac_hdr_len = (int)((void *)(iph) - mac_hdr);
-
-       lro_desc = lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph);
-       if (!lro_desc)
-               goto out1;
-
-       if (!lro_desc->active) { /* start new lro session */
-               if (lro_tcp_ip_check(iph, tcph, len - mac_hdr_len, NULL))
-                       goto out1;
-
-               skb = lro_gen_skb(lro_mgr, frags, len, true_size, mac_hdr,
-                                 hdr_len, 0, lro_mgr->ip_summed_aggr);
-               if (!skb)
-                       goto out;
-
-               if ((skb->protocol == htons(ETH_P_8021Q)) &&
-                   !(lro_mgr->features & LRO_F_EXTRACT_VLAN_ID))
-                       vlan_hdr_len = VLAN_HLEN;
-
-               iph = (void *)(skb->data + vlan_hdr_len);
-               tcph = (void *)((u8 *)skb->data + vlan_hdr_len
-                               + IP_HDR_LEN(iph));
-
-               lro_init_desc(lro_desc, skb, iph, tcph);
-               LRO_INC_STATS(lro_mgr, aggregated);
-               return NULL;
-       }
-
-       if (lro_desc->tcp_next_seq != ntohl(tcph->seq))
-               goto out2;
-
-       if (lro_tcp_ip_check(iph, tcph, len - mac_hdr_len, lro_desc))
-               goto out2;
-
-       lro_add_frags(lro_desc, len, hdr_len, true_size, frags, iph, tcph);
-       LRO_INC_STATS(lro_mgr, aggregated);
-
-       if ((skb_shinfo(lro_desc->parent)->nr_frags >= lro_mgr->max_aggr) ||
-           lro_desc->parent->len > (0xFFFF - lro_mgr->dev->mtu))
-               lro_flush(lro_mgr, lro_desc);
-
-       return NULL;
-
-out2: /* send aggregated packets to the stack */
-       lro_flush(lro_mgr, lro_desc);
-
-out1:  /* Original packet has to be posted to the stack */
-       skb = lro_gen_skb(lro_mgr, frags, len, true_size, mac_hdr,
-                         hdr_len, sum, lro_mgr->ip_summed);
-out:
-       return skb;
-}
-
 void lro_receive_skb(struct net_lro_mgr *lro_mgr,
                     struct sk_buff *skb,
                     void *priv)
@@ -506,23 +361,6 @@ void lro_receive_skb(struct net_lro_mgr *lro_mgr,
 }
 EXPORT_SYMBOL(lro_receive_skb);
 
-void lro_receive_frags(struct net_lro_mgr *lro_mgr,
-                      struct skb_frag_struct *frags,
-                      int len, int true_size, void *priv, __wsum sum)
-{
-       struct sk_buff *skb;
-
-       skb = __lro_proc_segment(lro_mgr, frags, len, true_size, priv, sum);
-       if (!skb)
-               return;
-
-       if (lro_mgr->features & LRO_F_NAPI)
-               netif_receive_skb(skb);
-       else
-               netif_rx(skb);
-}
-EXPORT_SYMBOL(lro_receive_frags);
-
 void lro_flush_all(struct net_lro_mgr *lro_mgr)
 {
        int i;
@@ -534,14 +372,3 @@ void lro_flush_all(struct net_lro_mgr *lro_mgr)
        }
 }
 EXPORT_SYMBOL(lro_flush_all);
-
-void lro_flush_pkt(struct net_lro_mgr *lro_mgr,
-                 struct iphdr *iph, struct tcphdr *tcph)
-{
-       struct net_lro_desc *lro_desc;
-
-       lro_desc = lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph);
-       if (lro_desc->active)
-               lro_flush(lro_mgr, lro_desc);
-}
-EXPORT_SYMBOL(lro_flush_pkt);
index 33d5537881ed7b39e33199dfe978bbe5b912d706..48f4244651125fb4ef7bcfda155137f287b07c77 100644 (file)
@@ -109,13 +109,6 @@ static inline void flush_check(struct inet_peer_base *base, int family)
        }
 }
 
-void inetpeer_invalidate_family(int family)
-{
-       atomic_t *fp = inetpeer_seq_ptr(family);
-
-       atomic_inc(fp);
-}
-
 #define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */
 
 /* Exported for sysctl_net_ipv4.  */
@@ -227,7 +220,7 @@ static int addr_compare(const struct inetpeer_addr *a,
        stackptr = _stack;                                      \
        *stackptr++ = &_base->root;                             \
        for (u = rcu_deref_locked(_base->root, _base);          \
-            u != peer_avl_empty; ) {                           \
+            u != peer_avl_empty;) {                            \
                int cmp = addr_compare(_daddr, &u->daddr);      \
                if (cmp == 0)                                   \
                        break;                                  \
@@ -282,7 +275,7 @@ static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
        *stackptr++ = &start->avl_left;                         \
        v = &start->avl_left;                                   \
        for (u = rcu_deref_locked(*v, base);                    \
-            u->avl_right != peer_avl_empty_rcu; ) {            \
+            u->avl_right != peer_avl_empty_rcu;) {             \
                v = &u->avl_right;                              \
                *stackptr++ = v;                                \
                u = rcu_deref_locked(*v, base);                 \
index 694de3b7aebfede6073433201e1200cf72008997..e9f1217a8afdaf2559ce3fd7d134489994faf440 100644 (file)
@@ -54,6 +54,7 @@ static int ip_forward_finish(struct sk_buff *skb)
 
 int ip_forward(struct sk_buff *skb)
 {
+       u32 mtu;
        struct iphdr *iph;      /* Our header */
        struct rtable *rt;      /* Route we use */
        struct ip_options *opt  = &(IPCB(skb)->opt);
@@ -88,11 +89,13 @@ int ip_forward(struct sk_buff *skb)
        if (opt->is_strictroute && rt->rt_uses_gateway)
                goto sr_failed;
 
-       if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
+       IPCB(skb)->flags |= IPSKB_FORWARDED;
+       mtu = ip_dst_mtu_maybe_forward(&rt->dst, true);
+       if (unlikely(skb->len > mtu && !skb_is_gso(skb) &&
                     (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
                IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS);
                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
-                         htonl(dst_mtu(&rt->dst)));
+                         htonl(mtu));
                goto drop;
        }
 
index d7aea4c5b9400efec37d15db3c5a896769d0da68..e560ef34cf4bd2efe9f1f7a64424441117a4502a 100644 (file)
@@ -217,6 +217,7 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
                                  iph->saddr, iph->daddr, tpi->key);
 
        if (tunnel) {
+               skb_pop_mac_header(skb);
                ip_tunnel_rcv(tunnel, skb, tpi, log_ecn_error);
                return PACKET_RCVD;
        }
index ec7264514a82e0a130bf15ee01a9030596880921..f4ab72e19af923536656e734996f4b9201684b58 100644 (file)
@@ -167,7 +167,7 @@ int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb)
                soffset -= 4;
                if (soffset > 3) {
                        memcpy(&faddr, &start[soffset-1], 4);
-                       for (soffset-=4, doffset=4; soffset > 3; soffset-=4, doffset+=4)
+                       for (soffset -= 4, doffset = 4; soffset > 3; soffset -= 4, doffset += 4)
                                memcpy(&dptr[doffset-1], &start[soffset-1], 4);
                        /*
                         * RFC1812 requires to fix illegal source routes.
@@ -227,7 +227,7 @@ void ip_options_fragment(struct sk_buff *skb)
                        continue;
                }
                optlen = optptr[1];
-               if (optlen<2 || optlen>l)
+               if (optlen < 2 || optlen > l)
                  return;
                if (!IPOPT_COPIED(*optptr))
                        memset(optptr, IPOPT_NOOP, optlen);
@@ -275,27 +275,27 @@ int ip_options_compile(struct net *net,
 
        for (l = opt->optlen; l > 0; ) {
                switch (*optptr) {
-                     case IPOPT_END:
-                       for (optptr++, l--; l>0; optptr++, l--) {
+               case IPOPT_END:
+                       for (optptr++, l--; l > 0; optptr++, l--) {
                                if (*optptr != IPOPT_END) {
                                        *optptr = IPOPT_END;
                                        opt->is_changed = 1;
                                }
                        }
                        goto eol;
-                     case IPOPT_NOOP:
+               case IPOPT_NOOP:
                        l--;
                        optptr++;
                        continue;
                }
                optlen = optptr[1];
-               if (optlen<2 || optlen>l) {
+               if (optlen < 2 || optlen > l) {
                        pp_ptr = optptr;
                        goto error;
                }
                switch (*optptr) {
-                     case IPOPT_SSRR:
-                     case IPOPT_LSRR:
+               case IPOPT_SSRR:
+               case IPOPT_LSRR:
                        if (optlen < 3) {
                                pp_ptr = optptr + 1;
                                goto error;
@@ -321,7 +321,7 @@ int ip_options_compile(struct net *net,
                        opt->is_strictroute = (optptr[0] == IPOPT_SSRR);
                        opt->srr = optptr - iph;
                        break;
-                     case IPOPT_RR:
+               case IPOPT_RR:
                        if (opt->rr) {
                                pp_ptr = optptr;
                                goto error;
@@ -349,7 +349,7 @@ int ip_options_compile(struct net *net,
                        }
                        opt->rr = optptr - iph;
                        break;
-                     case IPOPT_TIMESTAMP:
+               case IPOPT_TIMESTAMP:
                        if (opt->ts) {
                                pp_ptr = optptr;
                                goto error;
@@ -369,13 +369,13 @@ int ip_options_compile(struct net *net,
                                        goto error;
                                }
                                switch (optptr[3]&0xF) {
-                                     case IPOPT_TS_TSONLY:
+                               case IPOPT_TS_TSONLY:
                                        if (skb)
                                                timeptr = &optptr[optptr[2]-1];
                                        opt->ts_needtime = 1;
                                        optptr[2] += 4;
                                        break;
-                                     case IPOPT_TS_TSANDADDR:
+                               case IPOPT_TS_TSANDADDR:
                                        if (optptr[2]+7 > optptr[1]) {
                                                pp_ptr = optptr + 2;
                                                goto error;
@@ -389,7 +389,7 @@ int ip_options_compile(struct net *net,
                                        opt->ts_needtime = 1;
                                        optptr[2] += 8;
                                        break;
-                                     case IPOPT_TS_PRESPEC:
+                               case IPOPT_TS_PRESPEC:
                                        if (optptr[2]+7 > optptr[1]) {
                                                pp_ptr = optptr + 2;
                                                goto error;
@@ -405,7 +405,7 @@ int ip_options_compile(struct net *net,
                                        opt->ts_needtime = 1;
                                        optptr[2] += 8;
                                        break;
-                                     default:
+                               default:
                                        if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
                                                pp_ptr = optptr + 3;
                                                goto error;
@@ -433,7 +433,7 @@ int ip_options_compile(struct net *net,
                        }
                        opt->ts = optptr - iph;
                        break;
-                     case IPOPT_RA:
+               case IPOPT_RA:
                        if (optlen < 4) {
                                pp_ptr = optptr + 1;
                                goto error;
@@ -441,7 +441,7 @@ int ip_options_compile(struct net *net,
                        if (optptr[2] == 0 && optptr[3] == 0)
                                opt->router_alert = optptr - iph;
                        break;
-                     case IPOPT_CIPSO:
+               case IPOPT_CIPSO:
                        if ((!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) || opt->cipso) {
                                pp_ptr = optptr;
                                goto error;
@@ -452,9 +452,9 @@ int ip_options_compile(struct net *net,
                                goto error;
                        }
                        break;
-                     case IPOPT_SEC:
-                     case IPOPT_SID:
-                     default:
+               case IPOPT_SEC:
+               case IPOPT_SID:
+               default:
                        if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
                                pp_ptr = optptr;
                                goto error;
@@ -572,7 +572,7 @@ void ip_forward_options(struct sk_buff *skb)
 
                optptr = raw + opt->srr;
 
-               for ( srrptr=optptr[2], srrspace = optptr[1];
+               for ( srrptr = optptr[2], srrspace = optptr[1];
                     srrptr <= srrspace;
                     srrptr += 4
                     ) {
@@ -628,7 +628,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
        if (rt->rt_type != RTN_LOCAL)
                return -EINVAL;
 
-       for (srrptr=optptr[2], srrspace = optptr[1]; srrptr <= srrspace; srrptr += 4) {
+       for (srrptr = optptr[2], srrspace = optptr[1]; srrptr <= srrspace; srrptr += 4) {
                if (srrptr + 3 > srrspace) {
                        icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((opt->srr+2)<<24));
                        return -EINVAL;
index 912402752f2ffce701d697de1bb7a32b05c3b482..9a78804cfe9c457a94c3b4c5f2e7d8fe0eb604dd 100644 (file)
@@ -449,6 +449,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
        __be16 not_last_frag;
        struct rtable *rt = skb_rtable(skb);
        int err = 0;
+       bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
 
        dev = rt->dst.dev;
 
@@ -458,12 +459,13 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
        iph = ip_hdr(skb);
 
+       mtu = ip_dst_mtu_maybe_forward(&rt->dst, forwarding);
        if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->local_df) ||
                     (IPCB(skb)->frag_max_size &&
-                     IPCB(skb)->frag_max_size > dst_mtu(&rt->dst)))) {
+                     IPCB(skb)->frag_max_size > mtu))) {
                IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
-                         htonl(ip_skb_dst_mtu(skb)));
+                         htonl(mtu));
                kfree_skb(skb);
                return -EMSGSIZE;
        }
@@ -473,7 +475,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
         */
 
        hlen = iph->ihl * 4;
-       mtu = dst_mtu(&rt->dst) - hlen; /* Size of data space */
+       mtu = mtu - hlen;       /* Size of data space */
 #ifdef CONFIG_BRIDGE_NETFILTER
        if (skb->nf_bridge)
                mtu -= nf_bridge_mtu_reduction(skb);
@@ -828,7 +830,7 @@ static int __ip_append_data(struct sock *sk,
 
        if (cork->length + length > maxnonfragsize - fragheaderlen) {
                ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
-                              mtu-exthdrlen);
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
@@ -1151,7 +1153,8 @@ ssize_t   ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
                         mtu : 0xFFFF;
 
        if (cork->length + size > maxnonfragsize - fragheaderlen) {
-               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu);
+               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
index 90ff9570d7d4def935f3224514312fc217812d9c..d3929a69f0082df71c8885c1ed52994f9983a6dd 100644 (file)
@@ -68,6 +68,63 @@ static unsigned int ip_tunnel_hash(struct ip_tunnel_net *itn,
                         IP_TNL_HASH_BITS);
 }
 
+static inline void __tunnel_dst_set(struct ip_tunnel_dst *idst,
+                                   struct dst_entry *dst)
+{
+       struct dst_entry *old_dst;
+
+       if (dst && (dst->flags & DST_NOCACHE))
+               dst = NULL;
+
+       spin_lock_bh(&idst->lock);
+       old_dst = rcu_dereference(idst->dst);
+       rcu_assign_pointer(idst->dst, dst);
+       dst_release(old_dst);
+       spin_unlock_bh(&idst->lock);
+}
+
+static inline void tunnel_dst_set(struct ip_tunnel *t, struct dst_entry *dst)
+{
+       __tunnel_dst_set(this_cpu_ptr(t->dst_cache), dst);
+}
+
+static inline void tunnel_dst_reset(struct ip_tunnel *t)
+{
+       tunnel_dst_set(t, NULL);
+}
+
+static void tunnel_dst_reset_all(struct ip_tunnel *t)
+{
+       int i;
+
+       for_each_possible_cpu(i)
+               __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL);
+}
+
+static inline struct dst_entry *tunnel_dst_get(struct ip_tunnel *t)
+{
+       struct dst_entry *dst;
+
+       rcu_read_lock();
+       dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst);
+       if (dst)
+               dst_hold(dst);
+       rcu_read_unlock();
+       return dst;
+}
+
+static struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie)
+{
+       struct dst_entry *dst = tunnel_dst_get(t);
+
+       if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+               tunnel_dst_reset(t);
+               return NULL;
+       }
+
+       return dst;
+}
+
 /* Often modified stats are per cpu, other are shared (netdev->stats) */
 struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
                                                struct rtnl_link_stats64 *tot)
@@ -75,7 +132,8 @@ struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
        int i;
 
        for_each_possible_cpu(i) {
-               const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
+               const struct pcpu_sw_netstats *tstats =
+                                                  per_cpu_ptr(dev->tstats, i);
                u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
                unsigned int start;
 
@@ -318,11 +376,10 @@ failed:
        return ERR_PTR(err);
 }
 
-static inline struct rtable *ip_route_output_tunnel(struct net *net,
-                                                   struct flowi4 *fl4,
-                                                   int proto,
-                                                   __be32 daddr, __be32 saddr,
-                                                   __be32 key, __u8 tos, int oif)
+static inline void init_tunnel_flow(struct flowi4 *fl4,
+                                   int proto,
+                                   __be32 daddr, __be32 saddr,
+                                   __be32 key, __u8 tos, int oif)
 {
        memset(fl4, 0, sizeof(*fl4));
        fl4->flowi4_oif = oif;
@@ -331,7 +388,6 @@ static inline struct rtable *ip_route_output_tunnel(struct net *net,
        fl4->flowi4_tos = tos;
        fl4->flowi4_proto = proto;
        fl4->fl4_gre_key = key;
-       return ip_route_output_key(net, fl4);
 }
 
 static int ip_tunnel_bind_dev(struct net_device *dev)
@@ -350,14 +406,14 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
                struct flowi4 fl4;
                struct rtable *rt;
 
-               rt = ip_route_output_tunnel(tunnel->net, &fl4,
-                                           tunnel->parms.iph.protocol,
-                                           iph->daddr, iph->saddr,
-                                           tunnel->parms.o_key,
-                                           RT_TOS(iph->tos),
-                                           tunnel->parms.link);
+               init_tunnel_flow(&fl4, iph->protocol, iph->daddr,
+                                iph->saddr, tunnel->parms.o_key,
+                                RT_TOS(iph->tos), tunnel->parms.link);
+               rt = ip_route_output_key(tunnel->net, &fl4);
+
                if (!IS_ERR(rt)) {
                        tdev = rt->dst.dev;
+                       tunnel_dst_set(tunnel, dst_clone(&rt->dst));
                        ip_rt_put(rt);
                }
                if (dev->type != ARPHRD_ETHER)
@@ -405,7 +461,7 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net,
 int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
                  const struct tnl_ptk_info *tpi, bool log_ecn_error)
 {
-       struct pcpu_tstats *tstats;
+       struct pcpu_sw_netstats *tstats;
        const struct iphdr *iph = ip_hdr(skb);
        int err;
 
@@ -528,10 +584,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        struct flowi4 fl4;
        u8     tos, ttl;
        __be16 df;
-       struct rtable *rt;              /* Route to the other host */
+       struct rtable *rt = NULL;       /* Route to the other host */
        unsigned int max_headroom;      /* The extra header space needed */
        __be32 dst;
        int err;
+       bool connected = true;
 
        inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
 
@@ -581,27 +638,39 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 #endif
                else
                        goto tx_error;
+
+               connected = false;
        }
 
        tos = tnl_params->tos;
        if (tos & 0x1) {
                tos &= ~0x1;
-               if (skb->protocol == htons(ETH_P_IP))
+               if (skb->protocol == htons(ETH_P_IP)) {
                        tos = inner_iph->tos;
-               else if (skb->protocol == htons(ETH_P_IPV6))
+                       connected = false;
+               } else if (skb->protocol == htons(ETH_P_IPV6)) {
                        tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
+                       connected = false;
+               }
        }
 
-       rt = ip_route_output_tunnel(tunnel->net, &fl4,
-                                   protocol,
-                                   dst, tnl_params->saddr,
-                                   tunnel->parms.o_key,
-                                   RT_TOS(tos),
-                                   tunnel->parms.link);
-       if (IS_ERR(rt)) {
-               dev->stats.tx_carrier_errors++;
-               goto tx_error;
+       init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
+                        tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link);
+
+       if (connected)
+               rt = (struct rtable *)tunnel_dst_check(tunnel, 0);
+
+       if (!rt) {
+               rt = ip_route_output_key(tunnel->net, &fl4);
+
+               if (IS_ERR(rt)) {
+                       dev->stats.tx_carrier_errors++;
+                       goto tx_error;
+               }
+               if (connected)
+                       tunnel_dst_set(tunnel, dst_clone(&rt->dst));
        }
+
        if (rt->dst.dev == dev) {
                ip_rt_put(rt);
                dev->stats.collisions++;
@@ -696,6 +765,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn,
                if (set_mtu)
                        dev->mtu = mtu;
        }
+       tunnel_dst_reset_all(t);
        netdev_state_change(dev);
 }
 
@@ -811,6 +881,7 @@ static void ip_tunnel_dev_free(struct net_device *dev)
        struct ip_tunnel *tunnel = netdev_priv(dev);
 
        gro_cells_destroy(&tunnel->gro_cells);
+       free_percpu(tunnel->dst_cache);
        free_percpu(dev->tstats);
        free_netdev(dev);
 }
@@ -979,18 +1050,31 @@ int ip_tunnel_init(struct net_device *dev)
        int i, err;
 
        dev->destructor = ip_tunnel_dev_free;
-       dev->tstats = alloc_percpu(struct pcpu_tstats);
+       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
        for_each_possible_cpu(i) {
-               struct pcpu_tstats *ipt_stats;
+               struct pcpu_sw_netstats *ipt_stats;
                ipt_stats = per_cpu_ptr(dev->tstats, i);
                u64_stats_init(&ipt_stats->syncp);
        }
 
+       tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
+       if (!tunnel->dst_cache) {
+               free_percpu(dev->tstats);
+               return -ENOMEM;
+       }
+
+       for_each_possible_cpu(i) {
+               struct ip_tunnel_dst *idst = per_cpu_ptr(tunnel->dst_cache, i);
+               idst-> dst = NULL;
+               spin_lock_init(&idst->lock);
+       }
+
        err = gro_cells_init(&tunnel->gro_cells, dev);
        if (err) {
+               free_percpu(tunnel->dst_cache);
                free_percpu(dev->tstats);
                return err;
        }
@@ -1015,6 +1099,8 @@ void ip_tunnel_uninit(struct net_device *dev)
        /* fb_tunnel_dev will be unregisted in net-exit call. */
        if (itn->fb_tunnel_dev != dev)
                ip_tunnel_del(netdev_priv(dev));
+
+       tunnel_dst_reset_all(tunnel);
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
 
index 52b802a0cd8cbda18579dd1811bce3405ecbdfdc..0783200ad8d22af4ede97d3dcb6c0a2f184ee6ca 100644 (file)
@@ -60,7 +60,7 @@ static int vti_rcv(struct sk_buff *skb)
        tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
                                  iph->saddr, iph->daddr, 0);
        if (tunnel != NULL) {
-               struct pcpu_tstats *tstats;
+               struct pcpu_sw_netstats *tstats;
                u32 oldmark = skb->mark;
                int ret;
 
index 40d56073cd19d3b3c27372b7dca255469d7e0068..81c6910cfa925b315c8efda5e3d79af817c82c88 100644 (file)
@@ -39,23 +39,33 @@ config NF_CONNTRACK_PROC_COMPAT
 config NF_TABLES_IPV4
        depends on NF_TABLES
        tristate "IPv4 nf_tables support"
-
-config NFT_REJECT_IPV4
-       depends on NF_TABLES_IPV4
-       tristate "nf_tables IPv4 reject support"
+       help
+         This option enables the IPv4 support for nf_tables.
 
 config NFT_CHAIN_ROUTE_IPV4
        depends on NF_TABLES_IPV4
        tristate "IPv4 nf_tables route chain support"
+       help
+         This option enables the "route" chain for IPv4 in nf_tables. This
+         chain type is used to force packet re-routing after mangling header
+         fields such as the source, destination, type of service and
+         the packet mark.
 
 config NFT_CHAIN_NAT_IPV4
        depends on NF_TABLES_IPV4
        depends on NF_NAT_IPV4 && NFT_NAT
        tristate "IPv4 nf_tables nat chain support"
+       help
+         This option enables the "nat" chain for IPv4 in nf_tables. This
+         chain type is used to perform Network Address Translation (NAT)
+         packet transformations such as the source, destination address and
+         source and destination ports.
 
 config NF_TABLES_ARP
        depends on NF_TABLES
        tristate "ARP nf_tables support"
+       help
+         This option enables the ARP support for nf_tables.
 
 config IP_NF_IPTABLES
        tristate "IP tables support (required for filtering/masq/NAT)"
index 19df72b7ba8810e698bf6d50e8eee5c23033b34a..c16be9d58420dad15b4218ec119b34d184a7ea7e 100644 (file)
@@ -28,7 +28,6 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
 obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
 
 obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
-obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
 obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
index b969131ad1c198c6983b07fb1903abd2498f1374..5b6e0df4ccffcbd712b15757a9557b3cefbbabbd 100644 (file)
 #include <linux/udp.h>
 #include <linux/icmp.h>
 #include <net/icmp.h>
-#include <net/ip.h>
-#include <net/tcp.h>
-#include <net/route.h>
-#include <net/dst.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_REJECT.h>
 #include <linux/netfilter_bridge.h>
 #endif
 
+#include <net/netfilter/ipv4/nf_reject.h>
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4");
 
-/* Send RST reply */
-static void send_reset(struct sk_buff *oldskb, int hook)
-{
-       struct sk_buff *nskb;
-       const struct iphdr *oiph;
-       struct iphdr *niph;
-       const struct tcphdr *oth;
-       struct tcphdr _otcph, *tcph;
-
-       /* IP header checks: fragment. */
-       if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
-               return;
-
-       oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
-                                sizeof(_otcph), &_otcph);
-       if (oth == NULL)
-               return;
-
-       /* No RST for RST. */
-       if (oth->rst)
-               return;
-
-       if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
-               return;
-
-       /* Check checksum */
-       if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
-               return;
-       oiph = ip_hdr(oldskb);
-
-       nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
-                        LL_MAX_HEADER, GFP_ATOMIC);
-       if (!nskb)
-               return;
-
-       skb_reserve(nskb, LL_MAX_HEADER);
-
-       skb_reset_network_header(nskb);
-       niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
-       niph->version   = 4;
-       niph->ihl       = sizeof(struct iphdr) / 4;
-       niph->tos       = 0;
-       niph->id        = 0;
-       niph->frag_off  = htons(IP_DF);
-       niph->protocol  = IPPROTO_TCP;
-       niph->check     = 0;
-       niph->saddr     = oiph->daddr;
-       niph->daddr     = oiph->saddr;
-
-       skb_reset_transport_header(nskb);
-       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
-       memset(tcph, 0, sizeof(*tcph));
-       tcph->source    = oth->dest;
-       tcph->dest      = oth->source;
-       tcph->doff      = sizeof(struct tcphdr) / 4;
-
-       if (oth->ack)
-               tcph->seq = oth->ack_seq;
-       else {
-               tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
-                                     oldskb->len - ip_hdrlen(oldskb) -
-                                     (oth->doff << 2));
-               tcph->ack = 1;
-       }
-
-       tcph->rst       = 1;
-       tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
-                                   niph->daddr, 0);
-       nskb->ip_summed = CHECKSUM_PARTIAL;
-       nskb->csum_start = (unsigned char *)tcph - nskb->head;
-       nskb->csum_offset = offsetof(struct tcphdr, check);
-
-       /* ip_route_me_harder expects skb->dst to be set */
-       skb_dst_set_noref(nskb, skb_dst(oldskb));
-
-       nskb->protocol = htons(ETH_P_IP);
-       if (ip_route_me_harder(nskb, RTN_UNSPEC))
-               goto free_nskb;
-
-       niph->ttl       = ip4_dst_hoplimit(skb_dst(nskb));
-
-       /* "Never happens" */
-       if (nskb->len > dst_mtu(skb_dst(nskb)))
-               goto free_nskb;
-
-       nf_ct_attach(nskb, oldskb);
-
-#ifdef CONFIG_BRIDGE_NETFILTER
-       /* If we use ip_local_out for bridged traffic, the MAC source on
-        * the RST will be ours, instead of the destination's.  This confuses
-        * some routers/firewalls, and they drop the packet.  So we need to
-        * build the eth header using the original destination's MAC as the
-        * source, and send the RST packet directly.
-        */
-       if (oldskb->nf_bridge) {
-               struct ethhdr *oeth = eth_hdr(oldskb);
-               nskb->dev = oldskb->nf_bridge->physindev;
-               niph->tot_len = htons(nskb->len);
-               ip_send_check(niph);
-               if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
-                                   oeth->h_source, oeth->h_dest, nskb->len) < 0)
-                       goto free_nskb;
-               dev_queue_xmit(nskb);
-       } else
-#endif
-               ip_local_out(nskb);
-
-       return;
-
- free_nskb:
-       kfree_skb(nskb);
-}
-
-static inline void send_unreach(struct sk_buff *skb_in, int code)
-{
-       icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
-}
-
 static unsigned int
 reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
@@ -157,28 +37,28 @@ reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
 
        switch (reject->with) {
        case IPT_ICMP_NET_UNREACHABLE:
-               send_unreach(skb, ICMP_NET_UNREACH);
+               nf_send_unreach(skb, ICMP_NET_UNREACH);
                break;
        case IPT_ICMP_HOST_UNREACHABLE:
-               send_unreach(skb, ICMP_HOST_UNREACH);
+               nf_send_unreach(skb, ICMP_HOST_UNREACH);
                break;
        case IPT_ICMP_PROT_UNREACHABLE:
-               send_unreach(skb, ICMP_PROT_UNREACH);
+               nf_send_unreach(skb, ICMP_PROT_UNREACH);
                break;
        case IPT_ICMP_PORT_UNREACHABLE:
-               send_unreach(skb, ICMP_PORT_UNREACH);
+               nf_send_unreach(skb, ICMP_PORT_UNREACH);
                break;
        case IPT_ICMP_NET_PROHIBITED:
-               send_unreach(skb, ICMP_NET_ANO);
+               nf_send_unreach(skb, ICMP_NET_ANO);
                break;
        case IPT_ICMP_HOST_PROHIBITED:
-               send_unreach(skb, ICMP_HOST_ANO);
+               nf_send_unreach(skb, ICMP_HOST_ANO);
                break;
        case IPT_ICMP_ADMIN_PROHIBITED:
-               send_unreach(skb, ICMP_PKT_FILTERED);
+               nf_send_unreach(skb, ICMP_PKT_FILTERED);
                break;
        case IPT_TCP_RESET:
-               send_reset(skb, par->hooknum);
+               nf_send_reset(skb, par->hooknum);
        case IPT_ICMP_ECHOREPLY:
                /* Doesn't happen. */
                break;
index ecd8bec411c9719c5ef083d9781e90d0377b88e9..8127dc802865c2e992de63ae5d63837f3fd73fd6 100644 (file)
@@ -548,9 +548,3 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void)
 
 module_init(nf_conntrack_l3proto_ipv4_init);
 module_exit(nf_conntrack_l3proto_ipv4_fini);
-
-void need_ipv4_conntrack(void)
-{
-       return;
-}
-EXPORT_SYMBOL_GPL(need_ipv4_conntrack);
index 61a942265e8abd963e169cb990d7a3e008b06e04..d551e31b416e02e728a433293d25317e9c930dcb 100644 (file)
@@ -461,14 +461,14 @@ static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
        }
 
        if (subid < 40) {
-               optr [0] = 0;
-               optr [1] = subid;
+               optr[0] = 0;
+               optr[1] = subid;
        } else if (subid < 80) {
-               optr [0] = 1;
-               optr [1] = subid - 40;
+               optr[0] = 1;
+               optr[1] = subid - 40;
        } else {
-               optr [0] = 2;
-               optr [1] = subid - 80;
+               optr[0] = 2;
+               optr[1] = subid - 80;
        }
 
        *len = 2;
index 3e67ef1c676f6a311242b834f8092cbd152040e8..19412a4063fbe27de956f4d7c380b8e774d61aae 100644 (file)
 #include <linux/netfilter_arp.h>
 #include <net/netfilter/nf_tables.h>
 
+static unsigned int
+nft_do_chain_arp(const struct nf_hook_ops *ops,
+                 struct sk_buff *skb,
+                 const struct net_device *in,
+                 const struct net_device *out,
+                 int (*okfn)(struct sk_buff *))
+{
+       struct nft_pktinfo pkt;
+
+       nft_set_pktinfo(&pkt, ops, skb, in, out);
+
+       return nft_do_chain(&pkt, ops);
+}
+
 static struct nft_af_info nft_af_arp __read_mostly = {
        .family         = NFPROTO_ARP,
        .nhooks         = NF_ARP_NUMHOOKS,
        .owner          = THIS_MODULE,
+       .nops           = 1,
+       .hooks          = {
+               [NF_ARP_IN]             = nft_do_chain_arp,
+               [NF_ARP_OUT]            = nft_do_chain_arp,
+               [NF_ARP_FORWARD]        = nft_do_chain_arp,
+       },
 };
 
 static int nf_tables_arp_init_net(struct net *net)
@@ -48,32 +68,14 @@ static struct pernet_operations nf_tables_arp_net_ops = {
        .exit   = nf_tables_arp_exit_net,
 };
 
-static unsigned int
-nft_do_chain_arp(const struct nf_hook_ops *ops,
-                 struct sk_buff *skb,
-                 const struct net_device *in,
-                 const struct net_device *out,
-                 int (*okfn)(struct sk_buff *))
-{
-       struct nft_pktinfo pkt;
-
-       nft_set_pktinfo(&pkt, ops, skb, in, out);
-
-       return nft_do_chain_pktinfo(&pkt, ops);
-}
-
-static struct nf_chain_type filter_arp = {
-       .family         = NFPROTO_ARP,
+static const struct nf_chain_type filter_arp = {
        .name           = "filter",
        .type           = NFT_CHAIN_T_DEFAULT,
+       .family         = NFPROTO_ARP,
+       .owner          = THIS_MODULE,
        .hook_mask      = (1 << NF_ARP_IN) |
                          (1 << NF_ARP_OUT) |
                          (1 << NF_ARP_FORWARD),
-       .fn             = {
-               [NF_ARP_IN]             = nft_do_chain_arp,
-               [NF_ARP_OUT]            = nft_do_chain_arp,
-               [NF_ARP_FORWARD]        = nft_do_chain_arp,
-       },
 };
 
 static int __init nf_tables_arp_init(void)
index 0f4cbfeb19bd07042aa8bc7f50ec9af15a2c1b2a..6820c8c40842170039cfad8645ca72d88508daa1 100644 (file)
 #include <net/ip.h>
 #include <net/netfilter/nf_tables_ipv4.h>
 
+static unsigned int nft_do_chain_ipv4(const struct nf_hook_ops *ops,
+                                     struct sk_buff *skb,
+                                     const struct net_device *in,
+                                     const struct net_device *out,
+                                     int (*okfn)(struct sk_buff *))
+{
+       struct nft_pktinfo pkt;
+
+       nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
+
+       return nft_do_chain(&pkt, ops);
+}
+
 static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
                                    const struct net_device *in,
                                    const struct net_device *out,
                                    int (*okfn)(struct sk_buff *))
 {
-       struct nft_pktinfo pkt;
-
        if (unlikely(skb->len < sizeof(struct iphdr) ||
                     ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) {
                if (net_ratelimit())
@@ -33,19 +44,24 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
                                "packet\n");
                return NF_ACCEPT;
        }
-       nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
 
-       return nft_do_chain_pktinfo(&pkt, ops);
+       return nft_do_chain_ipv4(ops, skb, in, out, okfn);
 }
 
-static struct nft_af_info nft_af_ipv4 __read_mostly = {
+struct nft_af_info nft_af_ipv4 __read_mostly = {
        .family         = NFPROTO_IPV4,
        .nhooks         = NF_INET_NUMHOOKS,
        .owner          = THIS_MODULE,
+       .nops           = 1,
        .hooks          = {
+               [NF_INET_LOCAL_IN]      = nft_do_chain_ipv4,
                [NF_INET_LOCAL_OUT]     = nft_ipv4_output,
+               [NF_INET_FORWARD]       = nft_do_chain_ipv4,
+               [NF_INET_PRE_ROUTING]   = nft_do_chain_ipv4,
+               [NF_INET_POST_ROUTING]  = nft_do_chain_ipv4,
        },
 };
+EXPORT_SYMBOL_GPL(nft_af_ipv4);
 
 static int nf_tables_ipv4_init_net(struct net *net)
 {
@@ -75,42 +91,28 @@ static struct pernet_operations nf_tables_ipv4_net_ops = {
        .exit   = nf_tables_ipv4_exit_net,
 };
 
-static unsigned int
-nft_do_chain_ipv4(const struct nf_hook_ops *ops,
-                 struct sk_buff *skb,
-                 const struct net_device *in,
-                 const struct net_device *out,
-                 int (*okfn)(struct sk_buff *))
-{
-       struct nft_pktinfo pkt;
-
-       nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
-
-       return nft_do_chain_pktinfo(&pkt, ops);
-}
-
-static struct nf_chain_type filter_ipv4 = {
-       .family         = NFPROTO_IPV4,
+static const struct nf_chain_type filter_ipv4 = {
        .name           = "filter",
        .type           = NFT_CHAIN_T_DEFAULT,
+       .family         = NFPROTO_IPV4,
+       .owner          = THIS_MODULE,
        .hook_mask      = (1 << NF_INET_LOCAL_IN) |
                          (1 << NF_INET_LOCAL_OUT) |
                          (1 << NF_INET_FORWARD) |
                          (1 << NF_INET_PRE_ROUTING) |
                          (1 << NF_INET_POST_ROUTING),
-       .fn             = {
-               [NF_INET_LOCAL_IN]      = nft_do_chain_ipv4,
-               [NF_INET_LOCAL_OUT]     = nft_ipv4_output,
-               [NF_INET_FORWARD]       = nft_do_chain_ipv4,
-               [NF_INET_PRE_ROUTING]   = nft_do_chain_ipv4,
-               [NF_INET_POST_ROUTING]  = nft_do_chain_ipv4,
-       },
 };
 
 static int __init nf_tables_ipv4_init(void)
 {
+       int ret;
+
        nft_register_chain_type(&filter_ipv4);
-       return register_pernet_subsys(&nf_tables_ipv4_net_ops);
+       ret = register_pernet_subsys(&nf_tables_ipv4_net_ops);
+       if (ret < 0)
+               nft_unregister_chain_type(&filter_ipv4);
+
+       return ret;
 }
 
 static void __exit nf_tables_ipv4_exit(void)
index cf2c792cd971cc757fb3986c0956c0841922d385..b5b256d45e67b7f2dd288017b9f728edf72d32c3 100644 (file)
@@ -75,7 +75,7 @@ static unsigned int nf_nat_fn(const struct nf_hook_ops *ops,
 
                nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
 
-               ret = nft_do_chain_pktinfo(&pkt, ops);
+               ret = nft_do_chain(&pkt, ops);
                if (ret != NF_ACCEPT)
                        return ret;
                if (!nf_nat_initialized(ct, maniptype)) {
@@ -164,21 +164,21 @@ static unsigned int nf_nat_output(const struct nf_hook_ops *ops,
        return ret;
 }
 
-static struct nf_chain_type nft_chain_nat_ipv4 = {
-       .family         = NFPROTO_IPV4,
+static const struct nf_chain_type nft_chain_nat_ipv4 = {
        .name           = "nat",
        .type           = NFT_CHAIN_T_NAT,
+       .family         = NFPROTO_IPV4,
+       .owner          = THIS_MODULE,
        .hook_mask      = (1 << NF_INET_PRE_ROUTING) |
                          (1 << NF_INET_POST_ROUTING) |
                          (1 << NF_INET_LOCAL_OUT) |
                          (1 << NF_INET_LOCAL_IN),
-       .fn             = {
+       .hooks          = {
                [NF_INET_PRE_ROUTING]   = nf_nat_prerouting,
                [NF_INET_POST_ROUTING]  = nf_nat_postrouting,
                [NF_INET_LOCAL_OUT]     = nf_nat_output,
                [NF_INET_LOCAL_IN]      = nf_nat_fn,
        },
-       .me             = THIS_MODULE,
 };
 
 static int __init nft_chain_nat_init(void)
index 4e6bf9a3d7aa21a603f6c93f5a3136a623f5ec7f..125b66766c0a8799f0137b12352ab2448a0f9979 100644 (file)
@@ -47,7 +47,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
        daddr = iph->daddr;
        tos = iph->tos;
 
-       ret = nft_do_chain_pktinfo(&pkt, ops);
+       ret = nft_do_chain(&pkt, ops);
        if (ret != NF_DROP && ret != NF_QUEUE) {
                iph = ip_hdr(skb);
 
@@ -61,15 +61,15 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
        return ret;
 }
 
-static struct nf_chain_type nft_chain_route_ipv4 = {
-       .family         = NFPROTO_IPV4,
+static const struct nf_chain_type nft_chain_route_ipv4 = {
        .name           = "route",
        .type           = NFT_CHAIN_T_ROUTE,
+       .family         = NFPROTO_IPV4,
+       .owner          = THIS_MODULE,
        .hook_mask      = (1 << NF_INET_LOCAL_OUT),
-       .fn             = {
+       .hooks          = {
                [NF_INET_LOCAL_OUT]     = nf_route_table_hook,
        },
-       .me             = THIS_MODULE,
 };
 
 static int __init nft_chain_route_init(void)
index 242e7f4ed6f44ff5765966388618152e2721fa87..cae5262a337c3071a2c59dd210fd87aa4bb915db 100644 (file)
 #include <net/transp_v6.h>
 #endif
 
+struct ping_table {
+       struct hlist_nulls_head hash[PING_HTABLE_SIZE];
+       rwlock_t                lock;
+};
 
-struct ping_table ping_table;
+static struct ping_table ping_table;
 struct pingv6_ops pingv6_ops;
 EXPORT_SYMBOL_GPL(pingv6_ops);
 
@@ -668,8 +672,8 @@ int ping_common_sendmsg(int family, struct msghdr *msg, size_t len,
 }
 EXPORT_SYMBOL_GPL(ping_common_sendmsg);
 
-int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
-                   size_t len)
+static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+                          size_t len)
 {
        struct net *net = sock_net(sk);
        struct flowi4 fl4;
index 8ecd7ad959b4c9a1e29d6cf68501c7ba26f0bdf1..a6c8a80ec9d67299e39008f18a3adb0dcfae1389 100644 (file)
@@ -333,22 +333,22 @@ static void icmp_put(struct seq_file *seq)
        atomic_long_t *ptr = net->mib.icmpmsg_statistics->mibs;
 
        seq_puts(seq, "\nIcmp: InMsgs InErrors InCsumErrors");
-       for (i=0; icmpmibmap[i].name != NULL; i++)
+       for (i = 0; icmpmibmap[i].name != NULL; i++)
                seq_printf(seq, " In%s", icmpmibmap[i].name);
        seq_printf(seq, " OutMsgs OutErrors");
-       for (i=0; icmpmibmap[i].name != NULL; i++)
+       for (i = 0; icmpmibmap[i].name != NULL; i++)
                seq_printf(seq, " Out%s", icmpmibmap[i].name);
        seq_printf(seq, "\nIcmp: %lu %lu %lu",
                snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INMSGS),
                snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INERRORS),
                snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_CSUMERRORS));
-       for (i=0; icmpmibmap[i].name != NULL; i++)
+       for (i = 0; icmpmibmap[i].name != NULL; i++)
                seq_printf(seq, " %lu",
                           atomic_long_read(ptr + icmpmibmap[i].index));
        seq_printf(seq, " %lu %lu",
                snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_OUTMSGS),
                snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_OUTERRORS));
-       for (i=0; icmpmibmap[i].name != NULL; i++)
+       for (i = 0; icmpmibmap[i].name != NULL; i++)
                seq_printf(seq, " %lu",
                           atomic_long_read(ptr + (icmpmibmap[i].index | 0x100)));
 }
index f8da28278014ee2c99b2e530a694151d329bc5c2..25071b48921cebc4788a1f4b0b5fa118832f5910 100644 (file)
 #define RT_FL_TOS(oldflp4) \
        ((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))
 
-/* IPv4 datagram length is stored into 16bit field (tot_len) */
-#define IP_MAX_MTU     0xFFFF
-
 #define RT_GC_TIMEOUT (300*HZ)
 
 static int ip_rt_max_size;
index b95331e6c077cea0ff215702087fa14acd00abaf..f2ed13c2125f7d34820c9e92a3080678f30f46fd 100644 (file)
@@ -121,7 +121,7 @@ static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
        cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
 
        /* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
-       diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS);
+       diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS);
        if (diff >= MAX_SYNCOOKIE_AGE)
                return (__u32)-1;
 
index d7b63a61445427e56654b6ee340f2904695f1d73..44eba052b43d3ab49ba7630bcd82e73e5b094472 100644 (file)
@@ -700,7 +700,7 @@ static struct ctl_table ipv4_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
-        {
+       {
                .procname       = "tcp_thin_dupack",
                .data           = &sysctl_tcp_thin_dupack,
                .maxlen         = sizeof(int),
@@ -831,6 +831,13 @@ static struct ctl_table ipv4_net_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
+       {
+               .procname       = "ip_forward_use_pmtu",
+               .data           = &init_net.ipv4.sysctl_ip_fwd_use_pmtu,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
        { }
 };
 
index 0ca87547becbe939c19e93c6f68983c40087da86..e2a40515e66593660e1002cf20f6fc0d3969af14 100644 (file)
@@ -381,7 +381,7 @@ void tcp_init_sock(struct sock *sk)
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
 
-       skb_queue_head_init(&tp->out_of_order_queue);
+       __skb_queue_head_init(&tp->out_of_order_queue);
        tcp_init_xmit_timers(sk);
        tcp_prequeue_init(tp);
        INIT_LIST_HEAD(&tp->tsq_node);
@@ -622,19 +622,21 @@ static inline void tcp_mark_urg(struct tcp_sock *tp, int flags)
 }
 
 /* If a not yet filled skb is pushed, do not send it if
- * we have packets in Qdisc or NIC queues :
+ * we have data packets in Qdisc or NIC queues :
  * Because TX completion will happen shortly, it gives a chance
  * to coalesce future sendmsg() payload into this skb, without
  * need for a timer, and with no latency trade off.
  * As packets containing data payload have a bigger truesize
- * than pure acks (dataless) packets, the last check prevents
- * autocorking if we only have an ACK in Qdisc/NIC queues.
+ * than pure acks (dataless) packets, the last checks prevent
+ * autocorking if we only have an ACK in Qdisc/NIC queues,
+ * or if TX completion was delayed after we processed ACK packet.
  */
 static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb,
                                int size_goal)
 {
        return skb->len < size_goal &&
               sysctl_tcp_autocorking &&
+              skb != tcp_write_queue_head(sk) &&
               atomic_read(&sk->sk_wmem_alloc) > skb->truesize;
 }
 
@@ -660,7 +662,11 @@ static void tcp_push(struct sock *sk, int flags, int mss_now,
                        NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTOCORKING);
                        set_bit(TSQ_THROTTLED, &tp->tsq_flags);
                }
-               return;
+               /* It is possible TX completion already happened
+                * before we set TSQ_THROTTLED.
+                */
+               if (atomic_read(&sk->sk_wmem_alloc) > skb->truesize)
+                       return;
        }
 
        if (flags & MSG_MORE)
index c53b7f35c51dbd6f778455760e8d77733403ddd1..65cf90e063d5adcc98f15b044e35b20e1668352a 100644 (file)
@@ -766,7 +766,7 @@ static void tcp_update_pacing_rate(struct sock *sk)
 /* Calculate rto without backoff.  This is the second half of Van Jacobson's
  * routine referred to above.
  */
-void tcp_set_rto(struct sock *sk)
+static void tcp_set_rto(struct sock *sk)
 {
        const struct tcp_sock *tp = tcp_sk(sk);
        /* Old crap is replaced with new one. 8)
@@ -3686,7 +3686,7 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th)
                int opcode = *ptr++;
                int opsize;
 
-               switch(opcode) {
+               switch (opcode) {
                case TCPOPT_EOL:
                        return NULL;
                case TCPOPT_NOP:
@@ -4046,7 +4046,7 @@ static void tcp_sack_remove(struct tcp_sock *tp)
                        WARN_ON(before(tp->rcv_nxt, sp->end_seq));
 
                        /* Zap this SACK, by moving forward any other SACKS. */
-                       for (i=this_sack+1; i < num_sacks; i++)
+                       for (i = this_sack+1; i < num_sacks; i++)
                                tp->selective_acks[i-1] = tp->selective_acks[i];
                        num_sacks--;
                        continue;
index bbaf8cb45eb2ef60f3ad57cb5af6b04a8edf96bf..7297b56c28c7a150b8b89f536698e16b7aaba084 100644 (file)
@@ -827,7 +827,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
        const struct inet_request_sock *ireq = inet_rsk(req);
        struct flowi4 fl4;
        int err = -1;
-       struct sk_buff * skb;
+       struct sk_buff *skb;
 
        /* First, grab a route. */
        if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
index 06493736fbc826842876180a24510d9e348cb7f3..699a42faab9ceebaf638f96d60670df689f3e677 100644 (file)
@@ -31,7 +31,8 @@ struct tcp_fastopen_metrics {
 
 struct tcp_metrics_block {
        struct tcp_metrics_block __rcu  *tcpm_next;
-       struct inetpeer_addr            tcpm_addr;
+       struct inetpeer_addr            tcpm_saddr;
+       struct inetpeer_addr            tcpm_daddr;
        unsigned long                   tcpm_stamp;
        u32                             tcpm_ts;
        u32                             tcpm_ts_stamp;
@@ -131,7 +132,8 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst,
 }
 
 static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
-                                         struct inetpeer_addr *addr,
+                                         struct inetpeer_addr *saddr,
+                                         struct inetpeer_addr *daddr,
                                          unsigned int hash,
                                          bool reclaim)
 {
@@ -155,7 +157,8 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
                if (!tm)
                        goto out_unlock;
        }
-       tm->tcpm_addr = *addr;
+       tm->tcpm_saddr = *saddr;
+       tm->tcpm_daddr = *daddr;
 
        tcpm_suck_dst(tm, dst, true);
 
@@ -189,7 +192,8 @@ static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, in
        return NULL;
 }
 
-static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr,
+static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *saddr,
+                                                  const struct inetpeer_addr *daddr,
                                                   struct net *net, unsigned int hash)
 {
        struct tcp_metrics_block *tm;
@@ -197,7 +201,8 @@ static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *a
 
        for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
             tm = rcu_dereference(tm->tcpm_next)) {
-               if (addr_same(&tm->tcpm_addr, addr))
+               if (addr_same(&tm->tcpm_saddr, saddr) &&
+                   addr_same(&tm->tcpm_daddr, daddr))
                        break;
                depth++;
        }
@@ -208,19 +213,22 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req,
                                                       struct dst_entry *dst)
 {
        struct tcp_metrics_block *tm;
-       struct inetpeer_addr addr;
+       struct inetpeer_addr saddr, daddr;
        unsigned int hash;
        struct net *net;
 
-       addr.family = req->rsk_ops->family;
-       switch (addr.family) {
+       saddr.family = req->rsk_ops->family;
+       daddr.family = req->rsk_ops->family;
+       switch (daddr.family) {
        case AF_INET:
-               addr.addr.a4 = inet_rsk(req)->ir_rmt_addr;
-               hash = (__force unsigned int) addr.addr.a4;
+               saddr.addr.a4 = inet_rsk(req)->ir_loc_addr;
+               daddr.addr.a4 = inet_rsk(req)->ir_rmt_addr;
+               hash = (__force unsigned int) daddr.addr.a4;
                break;
 #if IS_ENABLED(CONFIG_IPV6)
        case AF_INET6:
-               *(struct in6_addr *)addr.addr.a6 = inet_rsk(req)->ir_v6_rmt_addr;
+               *(struct in6_addr *)saddr.addr.a6 = inet_rsk(req)->ir_v6_loc_addr;
+               *(struct in6_addr *)daddr.addr.a6 = inet_rsk(req)->ir_v6_rmt_addr;
                hash = ipv6_addr_hash(&inet_rsk(req)->ir_v6_rmt_addr);
                break;
 #endif
@@ -233,7 +241,8 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req,
 
        for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
             tm = rcu_dereference(tm->tcpm_next)) {
-               if (addr_same(&tm->tcpm_addr, &addr))
+               if (addr_same(&tm->tcpm_saddr, &saddr) &&
+                   addr_same(&tm->tcpm_daddr, &daddr))
                        break;
        }
        tcpm_check_stamp(tm, dst);
@@ -243,19 +252,22 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req,
 static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock *tw)
 {
        struct tcp_metrics_block *tm;
-       struct inetpeer_addr addr;
+       struct inetpeer_addr saddr, daddr;
        unsigned int hash;
        struct net *net;
 
-       addr.family = tw->tw_family;
-       switch (addr.family) {
+       saddr.family = tw->tw_family;
+       daddr.family = tw->tw_family;
+       switch (daddr.family) {
        case AF_INET:
-               addr.addr.a4 = tw->tw_daddr;
-               hash = (__force unsigned int) addr.addr.a4;
+               saddr.addr.a4 = tw->tw_rcv_saddr;
+               daddr.addr.a4 = tw->tw_daddr;
+               hash = (__force unsigned int) daddr.addr.a4;
                break;
 #if IS_ENABLED(CONFIG_IPV6)
        case AF_INET6:
-               *(struct in6_addr *)addr.addr.a6 = tw->tw_v6_daddr;
+               *(struct in6_addr *)saddr.addr.a6 = tw->tw_v6_rcv_saddr;
+               *(struct in6_addr *)daddr.addr.a6 = tw->tw_v6_daddr;
                hash = ipv6_addr_hash(&tw->tw_v6_daddr);
                break;
 #endif
@@ -268,7 +280,8 @@ static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock
 
        for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
             tm = rcu_dereference(tm->tcpm_next)) {
-               if (addr_same(&tm->tcpm_addr, &addr))
+               if (addr_same(&tm->tcpm_saddr, &saddr) &&
+                   addr_same(&tm->tcpm_daddr, &daddr))
                        break;
        }
        return tm;
@@ -279,20 +292,23 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
                                                 bool create)
 {
        struct tcp_metrics_block *tm;
-       struct inetpeer_addr addr;
+       struct inetpeer_addr saddr, daddr;
        unsigned int hash;
        struct net *net;
        bool reclaim;
 
-       addr.family = sk->sk_family;
-       switch (addr.family) {
+       saddr.family = sk->sk_family;
+       daddr.family = sk->sk_family;
+       switch (daddr.family) {
        case AF_INET:
-               addr.addr.a4 = inet_sk(sk)->inet_daddr;
-               hash = (__force unsigned int) addr.addr.a4;
+               saddr.addr.a4 = inet_sk(sk)->inet_saddr;
+               daddr.addr.a4 = inet_sk(sk)->inet_daddr;
+               hash = (__force unsigned int) daddr.addr.a4;
                break;
 #if IS_ENABLED(CONFIG_IPV6)
        case AF_INET6:
-               *(struct in6_addr *)addr.addr.a6 = sk->sk_v6_daddr;
+               *(struct in6_addr *)saddr.addr.a6 = sk->sk_v6_rcv_saddr;
+               *(struct in6_addr *)daddr.addr.a6 = sk->sk_v6_daddr;
                hash = ipv6_addr_hash(&sk->sk_v6_daddr);
                break;
 #endif
@@ -303,14 +319,14 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
        net = dev_net(dst->dev);
        hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
 
-       tm = __tcp_get_metrics(&addr, net, hash);
+       tm = __tcp_get_metrics(&saddr, &daddr, net, hash);
        reclaim = false;
        if (tm == TCP_METRICS_RECLAIM_PTR) {
                reclaim = true;
                tm = NULL;
        }
        if (!tm && create)
-               tm = tcpm_new(dst, &addr, hash, reclaim);
+               tm = tcpm_new(dst, &saddr, &daddr, hash, reclaim);
        else
                tcpm_check_stamp(tm, dst);
 
@@ -724,15 +740,21 @@ static int tcp_metrics_fill_info(struct sk_buff *msg,
        struct nlattr *nest;
        int i;
 
-       switch (tm->tcpm_addr.family) {
+       switch (tm->tcpm_daddr.family) {
        case AF_INET:
                if (nla_put_be32(msg, TCP_METRICS_ATTR_ADDR_IPV4,
-                               tm->tcpm_addr.addr.a4) < 0)
+                               tm->tcpm_daddr.addr.a4) < 0)
+                       goto nla_put_failure;
+               if (nla_put_be32(msg, TCP_METRICS_ATTR_SADDR_IPV4,
+                               tm->tcpm_saddr.addr.a4) < 0)
                        goto nla_put_failure;
                break;
        case AF_INET6:
                if (nla_put(msg, TCP_METRICS_ATTR_ADDR_IPV6, 16,
-                           tm->tcpm_addr.addr.a6) < 0)
+                           tm->tcpm_daddr.addr.a6) < 0)
+                       goto nla_put_failure;
+               if (nla_put(msg, TCP_METRICS_ATTR_SADDR_IPV6, 16,
+                           tm->tcpm_saddr.addr.a6) < 0)
                        goto nla_put_failure;
                break;
        default:
@@ -855,44 +877,66 @@ done:
        return skb->len;
 }
 
-static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
-                        unsigned int *hash, int optional)
+static int __parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
+                          unsigned int *hash, int optional, int v4, int v6)
 {
        struct nlattr *a;
 
-       a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV4];
+       a = info->attrs[v4];
        if (a) {
                addr->family = AF_INET;
                addr->addr.a4 = nla_get_be32(a);
-               *hash = (__force unsigned int) addr->addr.a4;
+               if (hash)
+                       *hash = (__force unsigned int) addr->addr.a4;
                return 0;
        }
-       a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];
+       a = info->attrs[v6];
        if (a) {
                if (nla_len(a) != sizeof(struct in6_addr))
                        return -EINVAL;
                addr->family = AF_INET6;
                memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6));
-               *hash = ipv6_addr_hash((struct in6_addr *) addr->addr.a6);
+               if (hash)
+                       *hash = ipv6_addr_hash((struct in6_addr *) addr->addr.a6);
                return 0;
        }
        return optional ? 1 : -EAFNOSUPPORT;
 }
 
+static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
+                        unsigned int *hash, int optional)
+{
+       return __parse_nl_addr(info, addr, hash, optional,
+                              TCP_METRICS_ATTR_ADDR_IPV4,
+                              TCP_METRICS_ATTR_ADDR_IPV6);
+}
+
+static int parse_nl_saddr(struct genl_info *info, struct inetpeer_addr *addr)
+{
+       return __parse_nl_addr(info, addr, NULL, 0,
+                              TCP_METRICS_ATTR_SADDR_IPV4,
+                              TCP_METRICS_ATTR_SADDR_IPV6);
+}
+
 static int tcp_metrics_nl_cmd_get(struct sk_buff *skb, struct genl_info *info)
 {
        struct tcp_metrics_block *tm;
-       struct inetpeer_addr addr;
+       struct inetpeer_addr saddr, daddr;
        unsigned int hash;
        struct sk_buff *msg;
        struct net *net = genl_info_net(info);
        void *reply;
        int ret;
+       bool src = true;
 
-       ret = parse_nl_addr(info, &addr, &hash, 0);
+       ret = parse_nl_addr(info, &daddr, &hash, 0);
        if (ret < 0)
                return ret;
 
+       ret = parse_nl_saddr(info, &saddr);
+       if (ret < 0)
+               src = false;
+
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!msg)
                return -ENOMEM;
@@ -907,7 +951,8 @@ static int tcp_metrics_nl_cmd_get(struct sk_buff *skb, struct genl_info *info)
        rcu_read_lock();
        for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
             tm = rcu_dereference(tm->tcpm_next)) {
-               if (addr_same(&tm->tcpm_addr, &addr)) {
+               if (addr_same(&tm->tcpm_daddr, &daddr) &&
+                   (!src || addr_same(&tm->tcpm_saddr, &saddr))) {
                        ret = tcp_metrics_fill_info(msg, tm);
                        break;
                }
@@ -960,34 +1005,44 @@ static int tcp_metrics_flush_all(struct net *net)
 static int tcp_metrics_nl_cmd_del(struct sk_buff *skb, struct genl_info *info)
 {
        struct tcpm_hash_bucket *hb;
-       struct tcp_metrics_block *tm;
+       struct tcp_metrics_block *tm, *tmlist = NULL;
        struct tcp_metrics_block __rcu **pp;
-       struct inetpeer_addr addr;
+       struct inetpeer_addr saddr, daddr;
        unsigned int hash;
        struct net *net = genl_info_net(info);
        int ret;
+       bool src = true;
 
-       ret = parse_nl_addr(info, &addr, &hash, 1);
+       ret = parse_nl_addr(info, &daddr, &hash, 1);
        if (ret < 0)
                return ret;
        if (ret > 0)
                return tcp_metrics_flush_all(net);
+       ret = parse_nl_saddr(info, &saddr);
+       if (ret < 0)
+               src = false;
 
        hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
        hb = net->ipv4.tcp_metrics_hash + hash;
        pp = &hb->chain;
        spin_lock_bh(&tcp_metrics_lock);
-       for (tm = deref_locked_genl(*pp); tm;
-            pp = &tm->tcpm_next, tm = deref_locked_genl(*pp)) {
-               if (addr_same(&tm->tcpm_addr, &addr)) {
+       for (tm = deref_locked_genl(*pp); tm; tm = deref_locked_genl(*pp)) {
+               if (addr_same(&tm->tcpm_daddr, &daddr) &&
+                   (!src || addr_same(&tm->tcpm_saddr, &saddr))) {
                        *pp = tm->tcpm_next;
-                       break;
+                       tm->tcpm_next = tmlist;
+                       tmlist = tm;
+               } else {
+                       pp = &tm->tcpm_next;
                }
        }
        spin_unlock_bh(&tcp_metrics_lock);
-       if (!tm)
+       if (!tmlist)
                return -ESRCH;
-       kfree_rcu(tm, rcu_head);
+       for (tm = tmlist; tm; tm = tmlist) {
+               tmlist = tm->tcpm_next;
+               kfree_rcu(tm, rcu_head);
+       }
        return 0;
 }
 
index 97b684159861bc451219bf66359afa288049a63e..3aa9e32479917fe4fb8a62efa97a758cf322680e 100644 (file)
@@ -425,7 +425,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 
                tcp_set_ca_state(newsk, TCP_CA_Open);
                tcp_init_xmit_timers(newsk);
-               skb_queue_head_init(&newtp->out_of_order_queue);
+               __skb_queue_head_init(&newtp->out_of_order_queue);
                newtp->write_seq = newtp->pushed_seq = treq->snt_isn + 1;
 
                newtp->rx_opt.saw_tstamp = 0;
index 2658a27f540dc19f3ce6d7a77a3118eae8c91200..771a3950d87a0ba28a65eb072e16b703eb8f2d83 100644 (file)
@@ -197,7 +197,8 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        goto out_check_final;
 
 found:
-       flush = NAPI_GRO_CB(p)->flush;
+       /* Include the IP ID check below from the inner most IP hdr */
+       flush = NAPI_GRO_CB(p)->flush | NAPI_GRO_CB(p)->flush_id;
        flush |= (__force int)(flags & TCP_FLAG_CWR);
        flush |= (__force int)((flags ^ tcp_flag_word(th2)) &
                  ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH));
@@ -230,7 +231,7 @@ out_check_final:
                pp = head;
 
 out:
-       NAPI_GRO_CB(skb)->flush |= flush;
+       NAPI_GRO_CB(skb)->flush |= (flush != 0);
 
        return pp;
 }
@@ -280,7 +281,7 @@ static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *
        if (NAPI_GRO_CB(skb)->flush)
                goto skip_csum;
 
-       wsum = skb->csum;
+       wsum = NAPI_GRO_CB(skb)->csum;
 
        switch (skb->ip_summed) {
        case CHECKSUM_NONE:
index 9e7aec7ee67e9d760e7875cab3f8ab6326580cff..03d26b85eab8520c552040f527d37323be91bd68 100644 (file)
@@ -2777,7 +2777,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 EXPORT_SYMBOL(tcp_make_synack);
 
 /* Do all connect socket setups that can be done AF independent. */
-void tcp_connect_init(struct sock *sk)
+static void tcp_connect_init(struct sock *sk)
 {
        const struct dst_entry *dst = __sk_dst_get(sk);
        struct tcp_sock *tp = tcp_sk(sk);
index 8b97d71e193b97cf18e424f01be911e34a614b32..1f2d37613c9e068058171abd53efa8709d63657e 100644 (file)
@@ -38,7 +38,7 @@ MODULE_DESCRIPTION("TCP cwnd snooper");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("1.1");
 
-static int port __read_mostly = 0;
+static int port __read_mostly;
 MODULE_PARM_DESC(port, "Port to match (0=all)");
 module_param(port, int, 0);
 
@@ -46,7 +46,7 @@ static unsigned int bufsize __read_mostly = 4096;
 MODULE_PARM_DESC(bufsize, "Log buffer size in packets (4096)");
 module_param(bufsize, uint, 0);
 
-static unsigned int fwmark __read_mostly = 0;
+static unsigned int fwmark __read_mostly;
 MODULE_PARM_DESC(fwmark, "skb mark to match (0=no mark)");
 module_param(fwmark, uint, 0);
 
index a347a078ee073fc31991ecd581b8f5bca7a5305b..1a8d271f994da4f5e5ad765b342c82e1efe198fa 100644 (file)
@@ -3,7 +3,7 @@
  *   YeAH TCP
  *
  * For further details look at:
- *    http://wil.cs.caltech.edu/pfldnet2007/paper/YeAH_TCP.pdf
+ *   https://web.archive.org/web/20080316215752/http://wil.cs.caltech.edu/pfldnet2007/paper/YeAH_TCP.pdf
  *
  */
 #include <linux/mm.h>
 
 #include "tcp_vegas.h"
 
-#define TCP_YEAH_ALPHA       80 //lin number of packets queued at the bottleneck
-#define TCP_YEAH_GAMMA        1 //lin fraction of queue to be removed per rtt
-#define TCP_YEAH_DELTA        3 //log minimum fraction of cwnd to be removed on loss
-#define TCP_YEAH_EPSILON      1 //log maximum fraction to be removed on early decongestion
-#define TCP_YEAH_PHY          8 //lin maximum delta from base
-#define TCP_YEAH_RHO         16 //lin minimum number of consecutive rtt to consider competition on loss
-#define TCP_YEAH_ZETA        50 //lin minimum number of state switchs to reset reno_count
+#define TCP_YEAH_ALPHA       80 /* number of packets queued at the bottleneck */
+#define TCP_YEAH_GAMMA        1 /* fraction of queue to be removed per rtt */
+#define TCP_YEAH_DELTA        3 /* log minimum fraction of cwnd to be removed on loss */
+#define TCP_YEAH_EPSILON      1 /* log maximum fraction to be removed on early decongestion */
+#define TCP_YEAH_PHY          8 /* maximum delta from base */
+#define TCP_YEAH_RHO         16 /* minimum number of consecutive rtt to consider competition on loss */
+#define TCP_YEAH_ZETA        50 /* minimum number of state switches to reset reno_count */
 
 #define TCP_SCALABLE_AI_CNT     100U
 
@@ -214,9 +214,9 @@ static u32 tcp_yeah_ssthresh(struct sock *sk) {
        if (yeah->doing_reno_now < TCP_YEAH_RHO) {
                reduction = yeah->lastQ;
 
-               reduction = min( reduction, max(tp->snd_cwnd>>1, 2U) );
+               reduction = min(reduction, max(tp->snd_cwnd>>1, 2U));
 
-               reduction = max( reduction, tp->snd_cwnd >> TCP_YEAH_DELTA);
+               reduction = max(reduction, tp->snd_cwnd >> TCP_YEAH_DELTA);
        } else
                reduction = max(tp->snd_cwnd>>1, 2U);
 
index d5d24ecde6a56476c55f47d5e11341275078b8c5..80f649fbee63885d59d845c32206f59b21d98fe2 100644 (file)
@@ -2478,6 +2478,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
                                       netdev_features_t features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
        __be16 protocol = skb->protocol;
@@ -2497,8 +2498,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset,
+                                    mac_len);
                goto out;
+       }
 
        outer_hlen = skb_tnl_header_len(skb);
        skb = segs;
index 83206de2bc7679dc20e4fdcf34f8b1f5cd7831ef..79c62bdcd3c549b7dc07c74449d30b77296134eb 100644 (file)
@@ -41,6 +41,14 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        unsigned int mss;
+       int offset;
+       __wsum csum;
+
+       if (skb->encapsulation &&
+           skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) {
+               segs = skb_udp_tunnel_segment(skb, features);
+               goto out;
+       }
 
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
@@ -63,27 +71,20 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
                goto out;
        }
 
+       /* Do software UFO. Complete and fill in the UDP checksum as
+        * HW cannot do checksum of UDP packets sent as multiple
+        * IP fragments.
+        */
+       offset = skb_checksum_start_offset(skb);
+       csum = skb_checksum(skb, offset, skb->len - offset, 0);
+       offset += skb->csum_offset;
+       *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+       skb->ip_summed = CHECKSUM_NONE;
+
        /* Fragment the skb. IP headers of the fragments are updated in
         * inet_gso_segment()
         */
-       if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
-               segs = skb_udp_tunnel_segment(skb, features);
-       else {
-               int offset;
-               __wsum csum;
-
-               /* Do software UFO. Complete and fill in the UDP checksum as
-                * HW cannot do checksum of UDP packets sent as multiple
-                * IP fragments.
-                */
-               offset = skb_checksum_start_offset(skb);
-               csum = skb_checksum(skb, offset, skb->len - offset, 0);
-               offset += skb->csum_offset;
-               *(__sum16 *)(skb->data + offset) = csum_fold(csum);
-               skb->ip_summed = CHECKSUM_NONE;
-
-               segs = skb_segment(skb, features);
-       }
+       segs = skb_segment(skb, features);
 out:
        return segs;
 }
index e3db3f9151146a6d393293e4e75daa63c988df1a..71acd0014f2dac6e598bf34a29fc67bf98dee8e9 100644 (file)
@@ -48,7 +48,7 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
                hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
 
        skb_set_network_header(skb, -x->props.header_len -
-                                   hdrlen + (XFRM_MODE_SKB_CB(skb)->ihl - sizeof(*top_iph)));
+                                   hdrlen + (XFRM_MODE_SKB_CB(skb)->ihl - sizeof(*top_iph)));
        if (x->sel.family != AF_INET6)
                skb->network_header += IPV4_BEET_PHMAXLEN;
        skb->mac_header = skb->network_header +
index 3c3425ee6a2b4d03a951a5630ca3aaba9c471cfe..a9fa6c1feed5db4c4ee3946d163ddc92ae0288de 100644 (file)
@@ -442,6 +442,8 @@ static int inet6_netconf_msgsize_devconf(int type)
        if (type == -1 || type == NETCONFA_MC_FORWARDING)
                size += nla_total_size(4);
 #endif
+       if (type == -1 || type == NETCONFA_PROXY_NEIGH)
+               size += nla_total_size(4);
 
        return size;
 }
@@ -475,6 +477,10 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
                        devconf->mc_forwarding) < 0)
                goto nla_put_failure;
 #endif
+       if ((type == -1 || type == NETCONFA_PROXY_NEIGH) &&
+           nla_put_s32(skb, NETCONFA_PROXY_NEIGH, devconf->proxy_ndp) < 0)
+               goto nla_put_failure;
+
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
@@ -509,6 +515,7 @@ errout:
 static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
        [NETCONFA_IFINDEX]      = { .len = sizeof(int) },
        [NETCONFA_FORWARDING]   = { .len = sizeof(int) },
+       [NETCONFA_PROXY_NEIGH]  = { .len = sizeof(int) },
 };
 
 static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
@@ -988,12 +995,9 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
         * --yoshfuji
         */
        if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
-               struct in6_addr prefix;
                struct rt6_info *rt;
 
-               ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
-
-               rt = addrconf_get_prefix_route(&prefix,
+               rt = addrconf_get_prefix_route(&ifp->addr,
                                               ifp->prefix_len,
                                               ifp->idev->dev,
                                               0, RTF_GATEWAY | RTF_DEFAULT);
@@ -1673,7 +1677,7 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -1684,7 +1688,7 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -1818,6 +1822,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
                return addrconf_ifid_sit(eui, dev);
        case ARPHRD_IPGRE:
                return addrconf_ifid_gre(eui, dev);
+       case ARPHRD_6LOWPAN:
        case ARPHRD_IEEE802154:
                return addrconf_ifid_eui64(eui, dev);
        case ARPHRD_IEEE1394:
@@ -2673,7 +2678,8 @@ static void addrconf_dev_config(struct net_device *dev)
            (dev->type != ARPHRD_INFINIBAND) &&
            (dev->type != ARPHRD_IEEE802154) &&
            (dev->type != ARPHRD_IEEE1394) &&
-           (dev->type != ARPHRD_TUNNEL6)) {
+           (dev->type != ARPHRD_TUNNEL6) &&
+           (dev->type != ARPHRD_6LOWPAN)) {
                /* Alas, we support only Ethernet autoconfiguration. */
                return;
        }
@@ -3472,7 +3478,12 @@ restart:
                                         &inet6_addr_lst[i], addr_lst) {
                        unsigned long age;
 
-                       if (ifp->flags & IFA_F_PERMANENT)
+                       /* When setting preferred_lft to a value not zero or
+                        * infinity, while valid_lft is infinity
+                        * IFA_F_PERMANENT has a non-infinity life time.
+                        */
+                       if ((ifp->flags & IFA_F_PERMANENT) &&
+                           (ifp->prefered_lft == INFINITY_LIFE_TIME))
                                continue;
 
                        spin_lock(&ifp->lock);
@@ -3497,7 +3508,8 @@ restart:
                                        ifp->flags |= IFA_F_DEPRECATED;
                                }
 
-                               if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))
+                               if ((ifp->valid_lft != INFINITY_LIFE_TIME) &&
+                                   (time_before(ifp->tstamp + ifp->valid_lft * HZ, next)))
                                        next = ifp->tstamp + ifp->valid_lft * HZ;
 
                                spin_unlock(&ifp->lock);
@@ -3797,7 +3809,8 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
        put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
                      ifa->idev->dev->ifindex);
 
-       if (!(ifa->flags&IFA_F_PERMANENT)) {
+       if (!((ifa->flags&IFA_F_PERMANENT) &&
+             (ifa->prefered_lft == INFINITY_LIFE_TIME))) {
                preferred = ifa->prefered_lft;
                valid = ifa->valid_lft;
                if (preferred != INFINITY_LIFE_TIME) {
@@ -4728,6 +4741,46 @@ int addrconf_sysctl_disable(struct ctl_table *ctl, int write,
        return ret;
 }
 
+static
+int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
+                             void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int *valp = ctl->data;
+       int ret;
+       int old, new;
+
+       old = *valp;
+       ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+       new = *valp;
+
+       if (write && old != new) {
+               struct net *net = ctl->extra2;
+
+               if (!rtnl_trylock())
+                       return restart_syscall();
+
+               if (valp == &net->ipv6.devconf_dflt->proxy_ndp)
+                       inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
+                                                    NETCONFA_IFINDEX_DEFAULT,
+                                                    net->ipv6.devconf_dflt);
+               else if (valp == &net->ipv6.devconf_all->proxy_ndp)
+                       inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
+                                                    NETCONFA_IFINDEX_ALL,
+                                                    net->ipv6.devconf_all);
+               else {
+                       struct inet6_dev *idev = ctl->extra1;
+
+                       inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
+                                                    idev->dev->ifindex,
+                                                    &idev->cnf);
+               }
+               rtnl_unlock();
+       }
+
+       return ret;
+}
+
+
 static struct addrconf_sysctl_table
 {
        struct ctl_table_header *sysctl_header;
@@ -4914,7 +4967,7 @@ static struct addrconf_sysctl_table
                        .data           = &ipv6_devconf.proxy_ndp,
                        .maxlen         = sizeof(int),
                        .mode           = 0644,
-                       .proc_handler   = proc_dointvec,
+                       .proc_handler   = addrconf_sysctl_proxy_ndp,
                },
                {
                        .procname       = "accept_source_route",
@@ -5163,9 +5216,7 @@ int __init addrconf_init(void)
 
        addrconf_verify(0);
 
-       err = rtnl_af_register(&inet6_ops);
-       if (err < 0)
-               goto errout_af;
+       rtnl_af_register(&inet6_ops);
 
        err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo,
                              NULL);
@@ -5189,7 +5240,6 @@ int __init addrconf_init(void)
        return 0;
 errout:
        rtnl_af_unregister(&inet6_ops);
-errout_af:
        unregister_netdevice_notifier(&ipv6_dev_notf);
 errlo:
        unregister_pernet_subsys(&addrconf_ops);
index eef8d945b362cf698c9ee407acec38f40e69977d..9a809a4b3d862444ff858f92a4d87ad6662e3d15 100644 (file)
@@ -315,8 +315,10 @@ static void mip6_addr_swap(struct sk_buff *skb)
 static inline void mip6_addr_swap(struct sk_buff *skb) {}
 #endif
 
-struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
-                                     struct sock *sk, struct flowi6 *fl6)
+static struct dst_entry *icmpv6_route_lookup(struct net *net,
+                                            struct sk_buff *skb,
+                                            struct sock *sk,
+                                            struct flowi6 *fl6)
 {
        struct dst_entry *dst, *dst2;
        struct flowi6 fl2;
@@ -554,7 +556,9 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 
        saddr = &ipv6_hdr(skb)->daddr;
 
-       if (!ipv6_unicast_destination(skb))
+       if (!ipv6_unicast_destination(skb) &&
+           !(net->ipv6.anycast_src_echo_reply &&
+             ipv6_anycast_destination(skb)))
                saddr = NULL;
 
        memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
@@ -984,7 +988,7 @@ int icmpv6_err_convert(u8 type, u8 code, int *err)
 EXPORT_SYMBOL(icmpv6_err_convert);
 
 #ifdef CONFIG_SYSCTL
-struct ctl_table ipv6_icmp_table_template[] = {
+static struct ctl_table ipv6_icmp_table_template[] = {
        {
                .procname       = "ratelimit",
                .data           = &init_net.ipv6.sysctl.icmpv6_time,
index 5550a8113a6dc5f202c0ccda2c7166e98e81a7e9..075602fc6b6a915f15a7039cf1daaa640e02ce82 100644 (file)
@@ -1530,7 +1530,7 @@ static void fib6_clean_tree(struct net *net, struct fib6_node *root,
 }
 
 void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
-                   int prune, void *arg)
+                   void *arg)
 {
        struct fib6_table *table;
        struct hlist_head *head;
@@ -1542,7 +1542,7 @@ void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
                hlist_for_each_entry_rcu(table, head, tb6_hlist) {
                        write_lock_bh(&table->tb6_lock);
                        fib6_clean_tree(net, &table->tb6_root,
-                                       func, prune, arg);
+                                       func, 0, arg);
                        write_unlock_bh(&table->tb6_lock);
                }
        }
@@ -1636,7 +1636,7 @@ void fib6_run_gc(unsigned long expires, struct net *net, bool force)
 
        gc_args.more = icmp6_dst_gc();
 
-       fib6_clean_all(net, fib6_age, 0, NULL);
+       fib6_clean_all(net, fib6_age, NULL);
        now = jiffies;
        net->ipv6.ip6_rt_last_gc = now;
 
index e27fb78c61f21e37bd46ca9739ef3d27200d5b62..e7a440dd5c0d75405a5faf083c8f634583d7eb16 100644 (file)
@@ -498,7 +498,7 @@ static int ip6gre_rcv(struct sk_buff *skb)
                                          &ipv6h->saddr, &ipv6h->daddr, key,
                                          gre_proto);
        if (tunnel) {
-               struct pcpu_tstats *tstats;
+               struct pcpu_sw_netstats *tstats;
 
                if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
                        goto drop;
@@ -1265,12 +1265,12 @@ static int ip6gre_tunnel_init(struct net_device *dev)
        if (ipv6_addr_any(&tunnel->parms.raddr))
                dev->header_ops = &ip6gre_header_ops;
 
-       dev->tstats = alloc_percpu(struct pcpu_tstats);
+       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
        for_each_possible_cpu(i) {
-               struct pcpu_tstats *ip6gre_tunnel_stats;
+               struct pcpu_sw_netstats *ip6gre_tunnel_stats;
                ip6gre_tunnel_stats = per_cpu_ptr(dev->tstats, i);
                u64_stats_init(&ip6gre_tunnel_stats->syncp);
        }
@@ -1466,12 +1466,12 @@ static int ip6gre_tap_init(struct net_device *dev)
 
        ip6gre_tnl_link_config(tunnel, 1);
 
-       dev->tstats = alloc_percpu(struct pcpu_tstats);
+       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
        for_each_possible_cpu(i) {
-               struct pcpu_tstats *ip6gre_tap_stats;
+               struct pcpu_sw_netstats *ip6gre_tap_stats;
                ip6gre_tap_stats = per_cpu_ptr(dev->tstats, i);
                u64_stats_init(&ip6gre_tap_stats->syncp);
        }
index 6fb4162fa78572411ccac31ac833c4eabe523fdc..1e8683b135bb7b503d9ab97d5c3c165af2453fa1 100644 (file)
@@ -190,7 +190,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
        unsigned int nlen;
        unsigned int hlen;
        unsigned int off;
-       int flush = 1;
+       u16 flush = 1;
        int proto;
        __wsum csum;
 
index 788c01a5359305ca352bcc2dedc77a99b2bc73d1..ef02b26ccf812e57e794e9b151746600bcb9a8f0 100644 (file)
@@ -321,6 +321,27 @@ static inline int ip6_forward_finish(struct sk_buff *skb)
        return dst_output(skb);
 }
 
+static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
+{
+       unsigned int mtu;
+       struct inet6_dev *idev;
+
+       if (dst_metric_locked(dst, RTAX_MTU)) {
+               mtu = dst_metric_raw(dst, RTAX_MTU);
+               if (mtu)
+                       return mtu;
+       }
+
+       mtu = IPV6_MIN_MTU;
+       rcu_read_lock();
+       idev = __in6_dev_get(dst->dev);
+       if (idev)
+               mtu = idev->cnf.mtu6;
+       rcu_read_unlock();
+
+       return mtu;
+}
+
 int ip6_forward(struct sk_buff *skb)
 {
        struct dst_entry *dst = skb_dst(skb);
@@ -441,7 +462,7 @@ int ip6_forward(struct sk_buff *skb)
                }
        }
 
-       mtu = dst_mtu(dst);
+       mtu = ip6_dst_mtu_forward(dst);
        if (mtu < IPV6_MIN_MTU)
                mtu = IPV6_MIN_MTU;
 
@@ -1188,11 +1209,35 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 
        fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
                        (opt ? opt->opt_nflen : 0);
-       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
+       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen -
+                    sizeof(struct frag_hdr);
 
        if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
-               if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) {
-                       ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen);
+               unsigned int maxnonfragsize, headersize;
+
+               headersize = sizeof(struct ipv6hdr) +
+                            (opt ? opt->tot_len : 0) +
+                            (dst_allfrag(&rt->dst) ?
+                             sizeof(struct frag_hdr) : 0) +
+                            rt->rt6i_nfheader_len;
+
+               maxnonfragsize = (np->pmtudisc >= IPV6_PMTUDISC_DO) ?
+                                mtu : sizeof(struct ipv6hdr) + IPV6_MAXPLEN;
+
+               /* dontfrag active */
+               if ((cork->length + length > mtu - headersize) && dontfrag &&
+                   (sk->sk_protocol == IPPROTO_UDP ||
+                    sk->sk_protocol == IPPROTO_RAW)) {
+                       ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
+                                                  sizeof(struct ipv6hdr));
+                       goto emsgsize;
+               }
+
+               if (cork->length + length > maxnonfragsize - headersize) {
+emsgsize:
+                       ipv6_local_error(sk, EMSGSIZE, fl6,
+                                        mtu - headersize +
+                                        sizeof(struct ipv6hdr));
                        return -EMSGSIZE;
                }
        }
@@ -1217,12 +1262,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
         * --yoshfuji
         */
 
-       if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP ||
-                                          sk->sk_protocol == IPPROTO_RAW)) {
-               ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
-               return -EMSGSIZE;
-       }
-
        skb = skb_peek_tail(&sk->sk_write_queue);
        cork->length += length;
        if (((length > mtu) ||
index 8d7c9867a44599c590127b9faa73527fb198c8f5..1e5e2404f1af51c4d230ac91817bb5805f62b856 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/if.h>
 #include <linux/in.h>
 #include <linux/ip.h>
-#include <linux/if_tunnel.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -102,16 +101,26 @@ struct ip6_tnl_net {
 
 static struct net_device_stats *ip6_get_stats(struct net_device *dev)
 {
-       struct pcpu_tstats sum = { 0 };
+       struct pcpu_sw_netstats tmp, sum = { 0 };
        int i;
 
        for_each_possible_cpu(i) {
-               const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
+               unsigned int start;
+               const struct pcpu_sw_netstats *tstats =
+                                                  per_cpu_ptr(dev->tstats, i);
+
+               do {
+                       start = u64_stats_fetch_begin_bh(&tstats->syncp);
+                       tmp.rx_packets = tstats->rx_packets;
+                       tmp.rx_bytes = tstats->rx_bytes;
+                       tmp.tx_packets = tstats->tx_packets;
+                       tmp.tx_bytes =  tstats->tx_bytes;
+               } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+               sum.rx_packets += tmp.rx_packets;
+               sum.rx_bytes   += tmp.rx_bytes;
+               sum.tx_packets += tmp.tx_packets;
+               sum.tx_bytes   += tmp.tx_bytes;
        }
        dev->stats.rx_packets = sum.rx_packets;
        dev->stats.rx_bytes   = sum.rx_bytes;
@@ -784,7 +793,7 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
 
        if ((t = ip6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr,
                                        &ipv6h->daddr)) != NULL) {
-               struct pcpu_tstats *tstats;
+               struct pcpu_sw_netstats *tstats;
 
                if (t->parms.proto != ipproto && t->parms.proto != 0) {
                        rcu_read_unlock();
@@ -823,8 +832,10 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
@@ -1497,12 +1508,12 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
 
        t->dev = dev;
        t->net = dev_net(dev);
-       dev->tstats = alloc_percpu(struct pcpu_tstats);
+       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
        for_each_possible_cpu(i) {
-               struct pcpu_tstats *ip6_tnl_stats;
+               struct pcpu_sw_netstats *ip6_tnl_stats;
                ip6_tnl_stats = per_cpu_ptr(dev->tstats, i);
                u64_stats_init(&ip6_tnl_stats->syncp);
        }
index ed94ba61dda0ec1c3e2b170fe74eb2334b752700..b50acd5e75d25349001ea0eb475ba5bce7e628bb 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/if.h>
 #include <linux/in.h>
 #include <linux/ip.h>
-#include <linux/if_tunnel.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -75,26 +74,6 @@ struct vti6_net {
        struct ip6_tnl __rcu **tnls[2];
 };
 
-static struct net_device_stats *vti6_get_stats(struct net_device *dev)
-{
-       struct pcpu_tstats sum = { 0 };
-       int i;
-
-       for_each_possible_cpu(i) {
-               const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
-       }
-       dev->stats.rx_packets = sum.rx_packets;
-       dev->stats.rx_bytes   = sum.rx_bytes;
-       dev->stats.tx_packets = sum.tx_packets;
-       dev->stats.tx_bytes   = sum.tx_bytes;
-       return &dev->stats;
-}
-
 #define for_each_vti6_tunnel_rcu(start) \
        for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
 
@@ -312,7 +291,7 @@ static int vti6_rcv(struct sk_buff *skb)
 
        if ((t = vti6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr,
                                 &ipv6h->daddr)) != NULL) {
-               struct pcpu_tstats *tstats;
+               struct pcpu_sw_netstats *tstats;
 
                if (t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) {
                        rcu_read_unlock();
@@ -331,8 +310,10 @@ static int vti6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                skb->mark = 0;
                secpath_reset(skb);
@@ -716,7 +697,7 @@ static const struct net_device_ops vti6_netdev_ops = {
        .ndo_start_xmit = vti6_tnl_xmit,
        .ndo_do_ioctl   = vti6_ioctl,
        .ndo_change_mtu = vti6_change_mtu,
-       .ndo_get_stats  = vti6_get_stats,
+       .ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
 /**
@@ -753,7 +734,7 @@ static inline int vti6_dev_init_gen(struct net_device *dev)
 
        t->dev = dev;
        t->net = dev_net(dev);
-       dev->tstats = alloc_percpu(struct pcpu_tstats);
+       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
        return 0;
index 7702f9e90a043ac458b63a2e0a07ed3975d37aa6..35750df744dc9ce92c3b98dcfd5dab27dcf73e85 100644 (file)
@@ -28,15 +28,27 @@ config NF_CONNTRACK_IPV6
 config NF_TABLES_IPV6
        depends on NF_TABLES
        tristate "IPv6 nf_tables support"
+       help
+         This option enables the IPv6 support for nf_tables.
 
 config NFT_CHAIN_ROUTE_IPV6
        depends on NF_TABLES_IPV6
        tristate "IPv6 nf_tables route chain support"
+       help
+         This option enables the "route" chain for IPv6 in nf_tables. This
+         chain type is used to force packet re-routing after mangling header
+         fields such as the source, destination, flowlabel, hop-limit and
+         the packet mark.
 
 config NFT_CHAIN_NAT_IPV6
        depends on NF_TABLES_IPV6
        depends on NF_NAT_IPV6 && NFT_NAT
        tristate "IPv6 nf_tables nat chain support"
+       help
+         This option enables the "nat" chain for IPv6 in nf_tables. This
+         chain type is used to perform Network Address Translation (NAT)
+         packet transformations such as the source, destination address and
+         source and destination ports.
 
 config IP6_NF_IPTABLES
        tristate "IP6 tables support (required for filtering)"
index da00a2ecde559431993f2e08ca29bc06a226155c..544b0a9da1b59db2fc59cbaf11a1eccd1de8dd3f 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/icmpv6.h>
 #include <linux/netdevice.h>
-#include <net/ipv6.h>
-#include <net/tcp.h>
 #include <net/icmp.h>
-#include <net/ip6_checksum.h>
-#include <net/ip6_fib.h>
-#include <net/ip6_route.h>
 #include <net/flow.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_REJECT.h>
 
+#include <net/netfilter/ipv6/nf_reject.h>
+
 MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
 MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv6");
 MODULE_LICENSE("GPL");
 
-/* Send RST reply */
-static void send_reset(struct net *net, struct sk_buff *oldskb, int hook)
-{
-       struct sk_buff *nskb;
-       struct tcphdr otcph, *tcph;
-       unsigned int otcplen, hh_len;
-       int tcphoff, needs_ack;
-       const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
-       struct ipv6hdr *ip6h;
-#define DEFAULT_TOS_VALUE      0x0U
-       const __u8 tclass = DEFAULT_TOS_VALUE;
-       struct dst_entry *dst = NULL;
-       u8 proto;
-       __be16 frag_off;
-       struct flowi6 fl6;
-
-       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
-           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
-               pr_debug("addr is not unicast.\n");
-               return;
-       }
-
-       proto = oip6h->nexthdr;
-       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off);
-
-       if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
-               pr_debug("Cannot get TCP header.\n");
-               return;
-       }
-
-       otcplen = oldskb->len - tcphoff;
-
-       /* IP header checks: fragment, too short. */
-       if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
-               pr_debug("proto(%d) != IPPROTO_TCP, "
-                        "or too short. otcplen = %d\n",
-                        proto, otcplen);
-               return;
-       }
-
-       if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr)))
-               BUG();
-
-       /* No RST for RST. */
-       if (otcph.rst) {
-               pr_debug("RST is set\n");
-               return;
-       }
-
-       /* Check checksum. */
-       if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) {
-               pr_debug("TCP checksum is invalid\n");
-               return;
-       }
-
-       memset(&fl6, 0, sizeof(fl6));
-       fl6.flowi6_proto = IPPROTO_TCP;
-       fl6.saddr = oip6h->daddr;
-       fl6.daddr = oip6h->saddr;
-       fl6.fl6_sport = otcph.dest;
-       fl6.fl6_dport = otcph.source;
-       security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
-       dst = ip6_route_output(net, NULL, &fl6);
-       if (dst == NULL || dst->error) {
-               dst_release(dst);
-               return;
-       }
-       dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
-       if (IS_ERR(dst))
-               return;
-
-       hh_len = (dst->dev->hard_header_len + 15)&~15;
-       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
-                        + sizeof(struct tcphdr) + dst->trailer_len,
-                        GFP_ATOMIC);
-
-       if (!nskb) {
-               net_dbg_ratelimited("cannot alloc skb\n");
-               dst_release(dst);
-               return;
-       }
-
-       skb_dst_set(nskb, dst);
-
-       skb_reserve(nskb, hh_len + dst->header_len);
-
-       skb_put(nskb, sizeof(struct ipv6hdr));
-       skb_reset_network_header(nskb);
-       ip6h = ipv6_hdr(nskb);
-       ip6_flow_hdr(ip6h, tclass, 0);
-       ip6h->hop_limit = ip6_dst_hoplimit(dst);
-       ip6h->nexthdr = IPPROTO_TCP;
-       ip6h->saddr = oip6h->daddr;
-       ip6h->daddr = oip6h->saddr;
-
-       skb_reset_transport_header(nskb);
-       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
-       /* Truncate to length (no data) */
-       tcph->doff = sizeof(struct tcphdr)/4;
-       tcph->source = otcph.dest;
-       tcph->dest = otcph.source;
-
-       if (otcph.ack) {
-               needs_ack = 0;
-               tcph->seq = otcph.ack_seq;
-               tcph->ack_seq = 0;
-       } else {
-               needs_ack = 1;
-               tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
-                                     + otcplen - (otcph.doff<<2));
-               tcph->seq = 0;
-       }
-
-       /* Reset flags */
-       ((u_int8_t *)tcph)[13] = 0;
-       tcph->rst = 1;
-       tcph->ack = needs_ack;
-       tcph->window = 0;
-       tcph->urg_ptr = 0;
-       tcph->check = 0;
-
-       /* Adjust TCP checksum */
-       tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr,
-                                     &ipv6_hdr(nskb)->daddr,
-                                     sizeof(struct tcphdr), IPPROTO_TCP,
-                                     csum_partial(tcph,
-                                                  sizeof(struct tcphdr), 0));
-
-       nf_ct_attach(nskb, oldskb);
-
-#ifdef CONFIG_BRIDGE_NETFILTER
-       /* If we use ip6_local_out for bridged traffic, the MAC source on
-        * the RST will be ours, instead of the destination's.  This confuses
-        * some routers/firewalls, and they drop the packet.  So we need to
-        * build the eth header using the original destination's MAC as the
-        * source, and send the RST packet directly.
-        */
-       if (oldskb->nf_bridge) {
-               struct ethhdr *oeth = eth_hdr(oldskb);
-               nskb->dev = oldskb->nf_bridge->physindev;
-               nskb->protocol = htons(ETH_P_IPV6);
-               ip6h->payload_len = htons(sizeof(struct tcphdr));
-               if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
-                                   oeth->h_source, oeth->h_dest, nskb->len) < 0)
-                       return;
-               dev_queue_xmit(nskb);
-       } else
-#endif
-               ip6_local_out(nskb);
-}
-
-static inline void
-send_unreach(struct net *net, struct sk_buff *skb_in, unsigned char code,
-            unsigned int hooknum)
-{
-       if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
-               skb_in->dev = net->loopback_dev;
-
-       icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
-}
 
 static unsigned int
 reject_tg6(struct sk_buff *skb, const struct xt_action_param *par)
@@ -208,25 +45,25 @@ reject_tg6(struct sk_buff *skb, const struct xt_action_param *par)
        pr_debug("%s: medium point\n", __func__);
        switch (reject->with) {
        case IP6T_ICMP6_NO_ROUTE:
-               send_unreach(net, skb, ICMPV6_NOROUTE, par->hooknum);
+               nf_send_unreach6(net, skb, ICMPV6_NOROUTE, par->hooknum);
                break;
        case IP6T_ICMP6_ADM_PROHIBITED:
-               send_unreach(net, skb, ICMPV6_ADM_PROHIBITED, par->hooknum);
+               nf_send_unreach6(net, skb, ICMPV6_ADM_PROHIBITED, par->hooknum);
                break;
        case IP6T_ICMP6_NOT_NEIGHBOUR:
-               send_unreach(net, skb, ICMPV6_NOT_NEIGHBOUR, par->hooknum);
+               nf_send_unreach6(net, skb, ICMPV6_NOT_NEIGHBOUR, par->hooknum);
                break;
        case IP6T_ICMP6_ADDR_UNREACH:
-               send_unreach(net, skb, ICMPV6_ADDR_UNREACH, par->hooknum);
+               nf_send_unreach6(net, skb, ICMPV6_ADDR_UNREACH, par->hooknum);
                break;
        case IP6T_ICMP6_PORT_UNREACH:
-               send_unreach(net, skb, ICMPV6_PORT_UNREACH, par->hooknum);
+               nf_send_unreach6(net, skb, ICMPV6_PORT_UNREACH, par->hooknum);
                break;
        case IP6T_ICMP6_ECHOREPLY:
                /* Do nothing */
                break;
        case IP6T_TCP_RESET:
-               send_reset(net, skb, par->hooknum);
+               nf_send_reset6(net, skb, par->hooknum);
                break;
        default:
                net_info_ratelimited("case %u not handled yet\n", reject->with);
index d77db8a13505083d18b1993b03da91b4c5e7ef23..0d812b31277d9eb04133dbc880e0e151e0f2cf1f 100644 (file)
 #include <net/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables_ipv6.h>
 
+static unsigned int nft_do_chain_ipv6(const struct nf_hook_ops *ops,
+                                     struct sk_buff *skb,
+                                     const struct net_device *in,
+                                     const struct net_device *out,
+                                     int (*okfn)(struct sk_buff *))
+{
+       struct nft_pktinfo pkt;
+
+       /* malformed packet, drop it */
+       if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
+               return NF_DROP;
+
+       return nft_do_chain(&pkt, ops);
+}
+
 static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
                                    const struct net_device *in,
                                    const struct net_device *out,
                                    int (*okfn)(struct sk_buff *))
 {
-       struct nft_pktinfo pkt;
-
        if (unlikely(skb->len < sizeof(struct ipv6hdr))) {
                if (net_ratelimit())
                        pr_info("nf_tables_ipv6: ignoring short SOCK_RAW "
                                "packet\n");
                return NF_ACCEPT;
        }
-       if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
-               return NF_DROP;
 
-       return nft_do_chain_pktinfo(&pkt, ops);
+       return nft_do_chain_ipv6(ops, skb, in, out, okfn);
 }
 
-static struct nft_af_info nft_af_ipv6 __read_mostly = {
+struct nft_af_info nft_af_ipv6 __read_mostly = {
        .family         = NFPROTO_IPV6,
        .nhooks         = NF_INET_NUMHOOKS,
        .owner          = THIS_MODULE,
+       .nops           = 1,
        .hooks          = {
+               [NF_INET_LOCAL_IN]      = nft_do_chain_ipv6,
                [NF_INET_LOCAL_OUT]     = nft_ipv6_output,
+               [NF_INET_FORWARD]       = nft_do_chain_ipv6,
+               [NF_INET_PRE_ROUTING]   = nft_do_chain_ipv6,
+               [NF_INET_POST_ROUTING]  = nft_do_chain_ipv6,
        },
 };
+EXPORT_SYMBOL_GPL(nft_af_ipv6);
 
 static int nf_tables_ipv6_init_net(struct net *net)
 {
@@ -73,44 +90,28 @@ static struct pernet_operations nf_tables_ipv6_net_ops = {
        .exit   = nf_tables_ipv6_exit_net,
 };
 
-static unsigned int
-nft_do_chain_ipv6(const struct nf_hook_ops *ops,
-                 struct sk_buff *skb,
-                 const struct net_device *in,
-                 const struct net_device *out,
-                 int (*okfn)(struct sk_buff *))
-{
-       struct nft_pktinfo pkt;
-
-       /* malformed packet, drop it */
-       if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
-               return NF_DROP;
-
-       return nft_do_chain_pktinfo(&pkt, ops);
-}
-
-static struct nf_chain_type filter_ipv6 = {
-       .family         = NFPROTO_IPV6,
+static const struct nf_chain_type filter_ipv6 = {
        .name           = "filter",
        .type           = NFT_CHAIN_T_DEFAULT,
+       .family         = NFPROTO_IPV6,
+       .owner          = THIS_MODULE,
        .hook_mask      = (1 << NF_INET_LOCAL_IN) |
                          (1 << NF_INET_LOCAL_OUT) |
                          (1 << NF_INET_FORWARD) |
                          (1 << NF_INET_PRE_ROUTING) |
                          (1 << NF_INET_POST_ROUTING),
-       .fn             = {
-               [NF_INET_LOCAL_IN]      = nft_do_chain_ipv6,
-               [NF_INET_LOCAL_OUT]     = nft_ipv6_output,
-               [NF_INET_FORWARD]       = nft_do_chain_ipv6,
-               [NF_INET_PRE_ROUTING]   = nft_do_chain_ipv6,
-               [NF_INET_POST_ROUTING]  = nft_do_chain_ipv6,
-       },
 };
 
 static int __init nf_tables_ipv6_init(void)
 {
+       int ret;
+
        nft_register_chain_type(&filter_ipv6);
-       return register_pernet_subsys(&nf_tables_ipv6_net_ops);
+       ret = register_pernet_subsys(&nf_tables_ipv6_net_ops);
+       if (ret < 0)
+               nft_unregister_chain_type(&filter_ipv6);
+
+       return ret;
 }
 
 static void __exit nf_tables_ipv6_exit(void)
index e86dcd70dc767fb9a64d5155ff60ecd17b17e2d8..9c3297a768fd1f0bb0aae5f784f2482b03a8ce15 100644 (file)
@@ -79,7 +79,7 @@ static unsigned int nf_nat_ipv6_fn(const struct nf_hook_ops *ops,
 
                nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out);
 
-               ret = nft_do_chain_pktinfo(&pkt, ops);
+               ret = nft_do_chain(&pkt, ops);
                if (ret != NF_ACCEPT)
                        return ret;
                if (!nf_nat_initialized(ct, maniptype)) {
@@ -170,21 +170,21 @@ static unsigned int nf_nat_ipv6_output(const struct nf_hook_ops *ops,
        return ret;
 }
 
-static struct nf_chain_type nft_chain_nat_ipv6 = {
-       .family         = NFPROTO_IPV6,
+static const struct nf_chain_type nft_chain_nat_ipv6 = {
        .name           = "nat",
        .type           = NFT_CHAIN_T_NAT,
+       .family         = NFPROTO_IPV6,
+       .owner          = THIS_MODULE,
        .hook_mask      = (1 << NF_INET_PRE_ROUTING) |
                          (1 << NF_INET_POST_ROUTING) |
                          (1 << NF_INET_LOCAL_OUT) |
                          (1 << NF_INET_LOCAL_IN),
-       .fn             = {
+       .hooks          = {
                [NF_INET_PRE_ROUTING]   = nf_nat_ipv6_prerouting,
                [NF_INET_POST_ROUTING]  = nf_nat_ipv6_postrouting,
                [NF_INET_LOCAL_OUT]     = nf_nat_ipv6_output,
                [NF_INET_LOCAL_IN]      = nf_nat_ipv6_fn,
        },
-       .me             = THIS_MODULE,
 };
 
 static int __init nft_chain_nat_ipv6_init(void)
index 3fe40f0456add7bd0272b25a6df05a4d34752632..42031299585e1be0452b35a264ee010bb9d7f7fb 100644 (file)
@@ -47,7 +47,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
        /* flowlabel and prio (includes version, which shouldn't change either */
        flowlabel = *((u32 *)ipv6_hdr(skb));
 
-       ret = nft_do_chain_pktinfo(&pkt, ops);
+       ret = nft_do_chain(&pkt, ops);
        if (ret != NF_DROP && ret != NF_QUEUE &&
            (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) ||
             memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) ||
@@ -59,15 +59,15 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
        return ret;
 }
 
-static struct nf_chain_type nft_chain_route_ipv6 = {
-       .family         = NFPROTO_IPV6,
+static const struct nf_chain_type nft_chain_route_ipv6 = {
        .name           = "route",
        .type           = NFT_CHAIN_T_ROUTE,
+       .family         = NFPROTO_IPV6,
+        .owner         = THIS_MODULE,
        .hook_mask      = (1 << NF_INET_LOCAL_OUT),
-       .fn             = {
+       .hooks          = {
                 [NF_INET_LOCAL_OUT]    = nf_route_table_hook,
         },
-        .me            = THIS_MODULE,
 };
 
 static int __init nft_chain_route_init(void)
index 89b2735cecf54f49ffeda4f69f57912917bb2ec9..11dac21e658690cdf01d7eb41c7e653d142ad9d4 100644 (file)
@@ -104,6 +104,36 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
                                           const struct in6_addr *gwaddr, int ifindex);
 #endif
 
+static void rt6_bind_peer(struct rt6_info *rt, int create)
+{
+       struct inet_peer_base *base;
+       struct inet_peer *peer;
+
+       base = inetpeer_base_ptr(rt->_rt6i_peer);
+       if (!base)
+               return;
+
+       peer = inet_getpeer_v6(base, &rt->rt6i_dst.addr, create);
+       if (peer) {
+               if (!rt6_set_peer(rt, peer))
+                       inet_putpeer(peer);
+       }
+}
+
+static struct inet_peer *__rt6_get_peer(struct rt6_info *rt, int create)
+{
+       if (rt6_has_peer(rt))
+               return rt6_peer_ptr(rt);
+
+       rt6_bind_peer(rt, create);
+       return (rt6_has_peer(rt) ? rt6_peer_ptr(rt) : NULL);
+}
+
+static struct inet_peer *rt6_get_peer_create(struct rt6_info *rt)
+{
+       return __rt6_get_peer(rt, 1);
+}
+
 static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
 {
        struct rt6_info *rt = (struct rt6_info *) dst;
@@ -312,22 +342,6 @@ static void ip6_dst_destroy(struct dst_entry *dst)
        }
 }
 
-void rt6_bind_peer(struct rt6_info *rt, int create)
-{
-       struct inet_peer_base *base;
-       struct inet_peer *peer;
-
-       base = inetpeer_base_ptr(rt->_rt6i_peer);
-       if (!base)
-               return;
-
-       peer = inet_getpeer_v6(base, &rt->rt6i_dst.addr, create);
-       if (peer) {
-               if (!rt6_set_peer(rt, peer))
-                       inet_putpeer(peer);
-       }
-}
-
 static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
                           int how)
 {
@@ -1909,9 +1923,7 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                else
                        rt->rt6i_gateway = *dest;
                rt->rt6i_flags = ort->rt6i_flags;
-               if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
-                   (RTF_DEFAULT | RTF_ADDRCONF))
-                       rt6_set_from(rt, ort);
+               rt6_set_from(rt, ort);
                rt->rt6i_metric = 0;
 
 #ifdef CONFIG_IPV6_SUBTREES
@@ -2244,7 +2256,7 @@ void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
                .net = net,
                .addr = &ifp->addr,
        };
-       fib6_clean_all(net, fib6_remove_prefsrc, 0, &adni);
+       fib6_clean_all(net, fib6_remove_prefsrc, &adni);
 }
 
 struct arg_dev_net {
@@ -2271,7 +2283,7 @@ void rt6_ifdown(struct net *net, struct net_device *dev)
                .net = net,
        };
 
-       fib6_clean_all(net, fib6_ifdown, 0, &adn);
+       fib6_clean_all(net, fib6_ifdown, &adn);
        icmp6_clean_all(fib6_ifdown, &adn);
 }
 
@@ -2326,7 +2338,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned int mtu)
                .mtu = mtu,
        };
 
-       fib6_clean_all(dev_net(dev), rt6_mtu_change_route, 0, &arg);
+       fib6_clean_all(dev_net(dev), rt6_mtu_change_route, &arg);
 }
 
 static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
index 366fbba3359ab790e1b22917931acdbdb1daebf3..3dfbcf1dcb1cbdb38a2a0b17a328bb424b139eb0 100644 (file)
@@ -671,7 +671,7 @@ static int ipip6_rcv(struct sk_buff *skb)
        tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
                                     iph->saddr, iph->daddr);
        if (tunnel != NULL) {
-               struct pcpu_tstats *tstats;
+               struct pcpu_sw_netstats *tstats;
 
                if (tunnel->parms.iph.protocol != IPPROTO_IPV6 &&
                    tunnel->parms.iph.protocol != 0)
@@ -702,8 +702,10 @@ static int ipip6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(tunnel->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
@@ -924,7 +926,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                if (tunnel->parms.iph.daddr && skb_dst(skb))
                        skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
 
-               if (skb->len > mtu) {
+               if (skb->len > mtu && !skb_is_gso(skb)) {
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                        ip_rt_put(rt);
                        goto tx_error;
@@ -966,8 +968,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
 
        skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT);
-       if (IS_ERR(skb))
+       if (IS_ERR(skb)) {
+               ip_rt_put(rt);
                goto out;
+       }
 
        err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos,
                            ttl, df, !net_eq(tunnel->net, dev_net(dev)));
@@ -1361,12 +1365,12 @@ static int ipip6_tunnel_init(struct net_device *dev)
        memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
 
        ipip6_tunnel_bind_dev(dev);
-       dev->tstats = alloc_percpu(struct pcpu_tstats);
+       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
        for_each_possible_cpu(i) {
-               struct pcpu_tstats *ipip6_tunnel_stats;
+               struct pcpu_sw_netstats *ipip6_tunnel_stats;
                ipip6_tunnel_stats = per_cpu_ptr(dev->tstats, i);
                u64_stats_init(&ipip6_tunnel_stats->syncp);
        }
@@ -1391,12 +1395,12 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
        iph->ihl                = 5;
        iph->ttl                = 64;
 
-       dev->tstats = alloc_percpu(struct pcpu_tstats);
+       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
        for_each_possible_cpu(i) {
-               struct pcpu_tstats *ipip6_fb_stats;
+               struct pcpu_sw_netstats *ipip6_fb_stats;
                ipip6_fb_stats = per_cpu_ptr(dev->tstats, i);
                u64_stats_init(&ipip6_fb_stats->syncp);
        }
index 107b2f1d90ae8ff5e092c8306215c21f82350314..6b6a2c83027eaa810936e14178d8db1cdb06c531 100644 (file)
@@ -24,6 +24,13 @@ static struct ctl_table ipv6_table_template[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
+       {
+               .procname       = "anycast_src_echo_reply",
+               .data           = &init_net.ipv6.anycast_src_echo_reply,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
        { }
 };
 
@@ -51,6 +58,7 @@ static int __net_init ipv6_sysctl_net_init(struct net *net)
        if (!ipv6_table)
                goto out;
        ipv6_table[0].data = &net->ipv6.sysctl.bindv6only;
+       ipv6_table[1].data = &net->ipv6.anycast_src_echo_reply;
 
        ipv6_route_table = ipv6_route_sysctl_init(net);
        if (!ipv6_route_table)
index 2bb87b8521253bee5ec3a8824535560f1121fe15..ffd5fa8bdb15098fa04a579349dbfd7fcec00dfb 100644 (file)
@@ -164,12 +164,12 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
         *      connect() to INADDR_ANY means loopback (BSD'ism).
         */
 
-       if(ipv6_addr_any(&usin->sin6_addr))
+       if (ipv6_addr_any(&usin->sin6_addr))
                usin->sin6_addr.s6_addr[15] = 0x1;
 
        addr_type = ipv6_addr_type(&usin->sin6_addr);
 
-       if(addr_type & IPV6_ADDR_MULTICAST)
+       if (addr_type & IPV6_ADDR_MULTICAST)
                return -ENETUNREACH;
 
        if (addr_type&IPV6_ADDR_LINKLOCAL) {
@@ -336,7 +336,7 @@ static void tcp_v6_mtu_reduced(struct sock *sk)
 static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                u8 type, u8 code, int offset, __be32 info)
 {
-       const struct ipv6hdr *hdr = (const struct ipv6hdr*)skb->data;
+       const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
        const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
        struct ipv6_pinfo *np;
        struct sock *sk;
@@ -469,7 +469,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
 {
        struct inet_request_sock *ireq = inet_rsk(req);
        struct ipv6_pinfo *np = inet6_sk(sk);
-       struct sk_buff * skb;
+       struct sk_buff *skb;
        int err = -ENOMEM;
 
        /* First, grab a route. */
@@ -912,7 +912,7 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
 }
 
 
-static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb)
 {
        struct request_sock *req, **prev;
        const struct tcphdr *th = tcp_hdr(skb);
@@ -1085,9 +1085,9 @@ drop:
        return 0; /* don't send reset */
 }
 
-static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
-                                         struct request_sock *req,
-                                         struct dst_entry *dst)
+static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+                                        struct request_sock *req,
+                                        struct dst_entry *dst)
 {
        struct inet_request_sock *ireq;
        struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
@@ -1382,7 +1382,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                 * otherwise we just shortcircuit this and continue with
                 * the new socket..
                 */
-               if(nsk != sk) {
+               if (nsk != sk) {
                        sock_rps_save_rxhash(nsk, skb);
                        if (tcp_child_process(sk, nsk, skb))
                                goto reset;
@@ -1742,7 +1742,7 @@ static void get_openreq6(struct seq_file *seq,
                   dest->s6_addr32[2], dest->s6_addr32[3],
                   ntohs(inet_rsk(req)->ir_rmt_port),
                   TCP_SYN_RECV,
-                  0,0, /* could print option size, but that is af dependent. */
+                  0, 0, /* could print option size, but that is af dependent. */
                   1,   /* timers active (only the expire timer) */
                   jiffies_to_clock_t(ttd),
                   req->num_timeout,
@@ -1801,7 +1801,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
                   atomic_read(&sp->sk_refcnt), sp,
                   jiffies_to_clock_t(icsk->icsk_rto),
                   jiffies_to_clock_t(icsk->icsk_ack.ato),
-                  (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
+                  (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
                   tp->snd_cwnd,
                   tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh
                   );
index 9af77d9c0ec9b7327c275feeacc6766c7681f54d..735d0f60c83a126683b599d1e967eb9ca18b0471 100644 (file)
@@ -176,7 +176,7 @@ l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id)
  * owned by userspace.  A struct sock returned from this function must be
  * released using l2tp_tunnel_sock_put once you're done with it.
  */
-struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel)
+static struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel)
 {
        int err = 0;
        struct socket *sock = NULL;
@@ -202,10 +202,9 @@ struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel)
 out:
        return sk;
 }
-EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_lookup);
 
 /* Drop a reference to a tunnel socket obtained via. l2tp_tunnel_sock_put */
-void l2tp_tunnel_sock_put(struct sock *sk)
+static void l2tp_tunnel_sock_put(struct sock *sk)
 {
        struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk);
        if (tunnel) {
@@ -217,7 +216,6 @@ void l2tp_tunnel_sock_put(struct sock *sk)
        }
        sock_put(sk);
 }
-EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_put);
 
 /* Lookup a session by id in the global session list
  */
index 1ee9f6965d6850c94f9ea70a6320836e3d0734f0..1f01ba3435bcf0889a79e510567f19f248b7eef5 100644 (file)
@@ -238,8 +238,6 @@ out:
        return tunnel;
 }
 
-struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel);
-void l2tp_tunnel_sock_put(struct sock *sk);
 struct l2tp_session *l2tp_session_find(struct net *net,
                                       struct l2tp_tunnel *tunnel,
                                       u32 session_id);
index 7b01b9f5846c845bcf4f04b21cfbcb5786c19421..c71b699eb555165e124ec21109e37212587c7741 100644 (file)
@@ -715,7 +715,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
        unsigned long cpu_flags;
        size_t copied = 0;
        u32 peek_seq = 0;
-       u32 *seq;
+       u32 *seq, skb_len;
        unsigned long used;
        int target;     /* Read at least this many bytes */
        long timeo;
@@ -812,6 +812,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
                continue;
        found_ok_skb:
+               skb_len = skb->len;
                /* Ok so how much can we use? */
                used = skb->len - offset;
                if (len < used)
@@ -844,7 +845,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
 
                /* Partial read */
-               if (used + offset < skb->len)
+               if (used + offset < skb_len)
                        continue;
        } while (len > 0);
 
index cd8724177965cd00aa226bca602ab5c2f05a438f..42dc2e45c921853bedea8987078b088a724e6fb5 100644 (file)
@@ -753,7 +753,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
  *
  *     Sends received pdus to the connection state machine.
  */
-static int llc_conn_rcv(struct socksk, struct sk_buff *skb)
+static int llc_conn_rcv(struct sock *sk, struct sk_buff *skb)
 {
        struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
@@ -891,7 +891,7 @@ out_kfree_skb:
  *
  *     Initializes a socket with default llc values.
  */
-static void llc_sk_init(struct socksk)
+static void llc_sk_init(struct sock *sk)
 {
        struct llc_sock *llc = llc_sk(sk);
 
index 2bb0ddff8c0fe3d72c072f175d54675a91a6922c..842851cef6987c157cc0bafe07104a2876ea7b38 100644 (file)
@@ -23,7 +23,7 @@
 #include <net/llc.h>
 
 LIST_HEAD(llc_sap_list);
-DEFINE_SPINLOCK(llc_sap_list_lock);
+static DEFINE_SPINLOCK(llc_sap_list_lock);
 
 /**
  *     llc_sap_alloc - allocates and initializes sap.
@@ -48,7 +48,7 @@ static struct llc_sap *llc_sap_alloc(void)
 
 static struct llc_sap *__llc_sap_find(unsigned char sap_value)
 {
-       struct llc_sapsap;
+       struct llc_sap *sap;
 
        list_for_each_entry(sap, &llc_sap_list, node)
                if (sap->laddr.lsap == sap_value)
@@ -159,7 +159,6 @@ module_init(llc_init);
 module_exit(llc_exit);
 
 EXPORT_SYMBOL(llc_sap_list);
-EXPORT_SYMBOL(llc_sap_list_lock);
 EXPORT_SYMBOL(llc_sap_find);
 EXPORT_SYMBOL(llc_sap_open);
 EXPORT_SYMBOL(llc_sap_close);
index e5850699098ef98787719dfd035fda0bfd4e3268..06033f6c845ff5d2ab73a98a41d08767b88e59fd 100644 (file)
@@ -66,7 +66,7 @@ struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
        return skb;
 }
 
-void llc_save_primitive(struct sock *sk, struct sk_buffskb, u8 prim)
+void llc_save_primitive(struct sock *sk, struct sk_buff *skb, u8 prim)
 {
        struct sockaddr_llc *addr;
 
@@ -114,7 +114,7 @@ void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb)
  *     failure.
  */
 static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
-                                                     struct sk_buffskb)
+                                                     struct sk_buff *skb)
 {
        int i = 0;
        struct llc_sap_state_trans *rc = NULL;
index 537488cbf941a3699ccaf533d8a9bb92c9788434..9b9009f99551bb18b9613b4c470361d7fded4eb3 100644 (file)
@@ -111,7 +111,7 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
 }
 
 
-struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[])
+struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[])
 {
        struct crypto_cipher *tfm;
 
index 20785a6472540efe147ebcfd1083221a08968db8..0ce6487af79536c03e7cae25639eeacd389f5f18 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <linux/crypto.h>
 
-struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]);
+struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[]);
 void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
                        const u8 *data, size_t data_len, u8 *mic);
 void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm);
index f80e8c4c6bcd303762781ed8a2aa613ff763f5fa..09d2e58a2ba70e50ff6489700565a3755358a3b0 100644 (file)
@@ -301,9 +301,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                if (!sta)
                        goto out;
 
-               if (pairwise)
+               if (pairwise && key_idx < NUM_DEFAULT_KEYS)
                        key = rcu_dereference(sta->ptk[key_idx]);
-               else if (key_idx < NUM_DEFAULT_KEYS)
+               else if (!pairwise &&
+                        key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
                        key = rcu_dereference(sta->gtk[key_idx]);
        } else
                key = rcu_dereference(sdata->keys[key_idx]);
@@ -827,6 +828,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
        if (cfg80211_chandef_identical(&local->monitor_chandef, chandef))
                return 0;
 
+       mutex_lock(&local->mtx);
        mutex_lock(&local->iflist_mtx);
        if (local->use_chanctx) {
                sdata = rcu_dereference_protected(
@@ -845,6 +847,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
        if (ret == 0)
                local->monitor_chandef = *chandef;
        mutex_unlock(&local->iflist_mtx);
+       mutex_unlock(&local->mtx);
 
        return ret;
 }
@@ -873,8 +876,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
        return 0;
 }
 
-int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
-                           struct cfg80211_beacon_data *params)
+static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
+                                  struct cfg80211_beacon_data *params)
 {
        struct beacon_data *new, *old;
        int new_head_len, new_tail_len;
@@ -950,6 +953,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
                              struct cfg80211_ap_settings *params)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
        struct beacon_data *old;
        struct ieee80211_sub_if_data *vlan;
        u32 changed = BSS_CHANGED_BEACON_INT |
@@ -968,8 +972,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
        sdata->needed_rx_chains = sdata->local->rx_chains;
        sdata->radar_required = params->radar_required;
 
+       mutex_lock(&local->mtx);
        err = ieee80211_vif_use_channel(sdata, &params->chandef,
                                        IEEE80211_CHANCTX_SHARED);
+       mutex_unlock(&local->mtx);
        if (err)
                return err;
        ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
@@ -1097,17 +1103,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        if (old_probe_resp)
                kfree_rcu(old_probe_resp, rcu_head);
 
-       list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
-               sta_info_flush_defer(vlan);
-       sta_info_flush_defer(sdata);
-       synchronize_net();
-       rcu_barrier();
-       list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
-               sta_info_flush_cleanup(vlan);
-               ieee80211_free_keys(vlan);
-       }
-       sta_info_flush_cleanup(sdata);
-       ieee80211_free_keys(sdata);
+       __sta_info_flush(sdata, true);
+       ieee80211_free_keys(sdata, true);
 
        sdata->vif.bss_conf.enable_beacon = false;
        sdata->vif.bss_conf.ssid_len = 0;
@@ -1129,7 +1126,9 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        skb_queue_purge(&sdata->u.ap.ps.bc_buf);
 
        ieee80211_vif_copy_chanctx_to_vlans(sdata, true);
+       mutex_lock(&local->mtx);
        ieee80211_vif_release_channel(sdata);
+       mutex_unlock(&local->mtx);
 
        return 0;
 }
@@ -1952,8 +1951,10 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
        sdata->smps_mode = IEEE80211_SMPS_OFF;
        sdata->needed_rx_chains = sdata->local->rx_chains;
 
+       mutex_lock(&sdata->local->mtx);
        err = ieee80211_vif_use_channel(sdata, &setup->chandef,
                                        IEEE80211_CHANCTX_SHARED);
+       mutex_unlock(&sdata->local->mtx);
        if (err)
                return err;
 
@@ -1965,7 +1966,9 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        ieee80211_stop_mesh(sdata);
+       mutex_lock(&sdata->local->mtx);
        ieee80211_vif_release_channel(sdata);
+       mutex_unlock(&sdata->local->mtx);
 
        return 0;
 }
@@ -2587,8 +2590,8 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
                int j;
 
                sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
-               memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs,
-                      sizeof(mask->control[i].mcs));
+               memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].ht_mcs,
+                      sizeof(mask->control[i].ht_mcs));
 
                sdata->rc_has_mcs_mask[i] = false;
                if (!sband)
@@ -2903,26 +2906,29 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
        unsigned long timeout;
        int err;
 
-       if (!list_empty(&local->roc_list) || local->scanning)
-               return -EBUSY;
+       mutex_lock(&local->mtx);
+       if (!list_empty(&local->roc_list) || local->scanning) {
+               err = -EBUSY;
+               goto out_unlock;
+       }
 
        /* whatever, but channel contexts should not complain about that one */
        sdata->smps_mode = IEEE80211_SMPS_OFF;
        sdata->needed_rx_chains = local->rx_chains;
        sdata->radar_required = true;
 
-       mutex_lock(&local->iflist_mtx);
        err = ieee80211_vif_use_channel(sdata, chandef,
                                        IEEE80211_CHANCTX_SHARED);
-       mutex_unlock(&local->iflist_mtx);
        if (err)
-               return err;
+               goto out_unlock;
 
        timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
        ieee80211_queue_delayed_work(&sdata->local->hw,
                                     &sdata->dfs_cac_timer_work, timeout);
 
-       return 0;
+ out_unlock:
+       mutex_unlock(&local->mtx);
+       return err;
 }
 
 static struct cfg80211_beacon_data *
@@ -2998,7 +3004,9 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
                goto unlock;
 
        sdata->radar_required = sdata->csa_radar_required;
+       mutex_lock(&local->mtx);
        err = ieee80211_vif_change_channel(sdata, &changed);
+       mutex_unlock(&local->mtx);
        if (WARN_ON(err < 0))
                goto unlock;
 
@@ -3047,8 +3055,8 @@ unlock:
        sdata_unlock(sdata);
 }
 
-static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
-                                   struct cfg80211_csa_settings *params)
+int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+                            struct cfg80211_csa_settings *params)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
@@ -3829,6 +3837,31 @@ static void ieee80211_set_wakeup(struct wiphy *wiphy, bool enabled)
 }
 #endif
 
+static int ieee80211_set_qos_map(struct wiphy *wiphy,
+                                struct net_device *dev,
+                                struct cfg80211_qos_map *qos_map)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct mac80211_qos_map *new_qos_map, *old_qos_map;
+
+       if (qos_map) {
+               new_qos_map = kzalloc(sizeof(*new_qos_map), GFP_KERNEL);
+               if (!new_qos_map)
+                       return -ENOMEM;
+               memcpy(&new_qos_map->qos_map, qos_map, sizeof(*qos_map));
+       } else {
+               /* A NULL qos_map was passed to disable QoS mapping */
+               new_qos_map = NULL;
+       }
+
+       old_qos_map = rtnl_dereference(sdata->qos_map);
+       rcu_assign_pointer(sdata->qos_map, new_qos_map);
+       if (old_qos_map)
+               kfree_rcu(old_qos_map, rcu_head);
+
+       return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
        .add_virtual_intf = ieee80211_add_iface,
        .del_virtual_intf = ieee80211_del_iface,
@@ -3908,4 +3941,5 @@ struct cfg80211_ops mac80211_config_ops = {
        .get_channel = ieee80211_cfg_get_channel,
        .start_radar_detection = ieee80211_start_radar_detection,
        .channel_switch = ieee80211_channel_switch,
+       .set_qos_map = ieee80211_set_qos_map,
 };
index a57d5d9466bcbca1c8aa05276502ede6987783e7..f43613a97dd664e2daf1856b001d7bdee5708d4f 100644 (file)
@@ -232,8 +232,8 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
        if (!local->use_chanctx)
                local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
 
-       /* acquire mutex to prevent idle from changing */
-       mutex_lock(&local->mtx);
+       /* we hold the mutex to prevent idle from changing */
+       lockdep_assert_held(&local->mtx);
        /* turn idle off *before* setting channel -- some drivers need that */
        changed = ieee80211_idle_off(local);
        if (changed)
@@ -246,19 +246,14 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
                err = drv_add_chanctx(local, ctx);
                if (err) {
                        kfree(ctx);
-                       ctx = ERR_PTR(err);
-
                        ieee80211_recalc_idle(local);
-                       goto out;
+                       return ERR_PTR(err);
                }
        }
 
        /* and keep the mutex held until the new chanctx is on the list */
        list_add_rcu(&ctx->list, &local->chanctx_list);
 
- out:
-       mutex_unlock(&local->mtx);
-
        return ctx;
 }
 
@@ -294,9 +289,7 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
        /* throw a warning if this wasn't the only channel context. */
        WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
 
-       mutex_lock(&local->mtx);
        ieee80211_recalc_idle(local);
-       mutex_unlock(&local->mtx);
 }
 
 static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
@@ -358,6 +351,31 @@ static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
        ieee80211_change_chanctx(local, ctx, compat);
 }
 
+static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
+                                          struct ieee80211_chanctx *chanctx)
+{
+       bool radar_enabled;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+       /* for setting local->radar_detect_enabled */
+       lockdep_assert_held(&local->mtx);
+
+       radar_enabled = ieee80211_is_radar_required(local);
+
+       if (radar_enabled == chanctx->conf.radar_enabled)
+               return;
+
+       chanctx->conf.radar_enabled = radar_enabled;
+       local->radar_detect_enabled = chanctx->conf.radar_enabled;
+
+       if (!local->use_chanctx) {
+               local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
+               ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+       }
+
+       drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
+}
+
 static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
                                           struct ieee80211_chanctx *ctx)
 {
@@ -404,29 +422,6 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
                ieee80211_free_chanctx(local, ctx);
 }
 
-void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
-                                   struct ieee80211_chanctx *chanctx)
-{
-       bool radar_enabled;
-
-       lockdep_assert_held(&local->chanctx_mtx);
-
-       radar_enabled = ieee80211_is_radar_required(local);
-
-       if (radar_enabled == chanctx->conf.radar_enabled)
-               return;
-
-       chanctx->conf.radar_enabled = radar_enabled;
-       local->radar_detect_enabled = chanctx->conf.radar_enabled;
-
-       if (!local->use_chanctx) {
-               local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
-               ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-       }
-
-       drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
-}
-
 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
                                   struct ieee80211_chanctx *chanctx)
 {
@@ -518,6 +513,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_chanctx *ctx;
        int ret;
 
+       lockdep_assert_held(&local->mtx);
+
        WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
 
        mutex_lock(&local->chanctx_mtx);
@@ -558,6 +555,8 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
        int ret;
        u32 chanctx_changed = 0;
 
+       lockdep_assert_held(&local->mtx);
+
        /* should never be called if not performing a channel switch. */
        if (WARN_ON(!sdata->vif.csa_active))
                return -EINVAL;
@@ -655,6 +654,8 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
 {
        WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
 
+       lockdep_assert_held(&sdata->local->mtx);
+
        mutex_lock(&sdata->local->chanctx_mtx);
        __ieee80211_vif_release_channel(sdata);
        mutex_unlock(&sdata->local->chanctx_mtx);
index 5d03c47c0a4cb4fa60e861750956c64bb8c90337..ef8b385eff04e4c7a279a92722fedc3f84163f6c 100644 (file)
@@ -242,22 +242,6 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
        return ret;
 }
 
-static inline void drv_set_multicast_list(struct ieee80211_local *local,
-                                         struct ieee80211_sub_if_data *sdata,
-                                         struct netdev_hw_addr_list *mc_list)
-{
-       bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
-
-       trace_drv_set_multicast_list(local, sdata, mc_list->count);
-
-       check_sdata_in_driver(sdata);
-
-       if (local->ops->set_multicast_list)
-               local->ops->set_multicast_list(&local->hw, &sdata->vif,
-                                              allmulti, mc_list);
-       trace_drv_return_void(local);
-}
-
 static inline void drv_configure_filter(struct ieee80211_local *local,
                                        unsigned int changed_flags,
                                        unsigned int *total_flags,
@@ -550,6 +534,22 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local,
 }
 #endif
 
+static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local,
+                                         struct ieee80211_sub_if_data *sdata,
+                                         struct sta_info *sta)
+{
+       might_sleep();
+
+       sdata = get_bss_sdata(sdata);
+       check_sdata_in_driver(sdata);
+
+       trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta);
+       if (local->ops->sta_pre_rcu_remove)
+               local->ops->sta_pre_rcu_remove(&local->hw, &sdata->vif,
+                                              &sta->sta);
+       trace_drv_return_void(local);
+}
+
 static inline __must_check
 int drv_sta_state(struct ieee80211_local *local,
                  struct ieee80211_sub_if_data *sdata,
index 2eda7b13124abb7469a8b7b86503de07c0155623..771080ec7212a43b5e3bb151a7e17ab392fe5557 100644 (file)
@@ -293,14 +293,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                radar_required = true;
        }
 
+       mutex_lock(&local->mtx);
        ieee80211_vif_release_channel(sdata);
        if (ieee80211_vif_use_channel(sdata, &chandef,
                                      ifibss->fixed_channel ?
                                        IEEE80211_CHANCTX_SHARED :
                                        IEEE80211_CHANCTX_EXCLUSIVE)) {
                sdata_info(sdata, "Failed to join IBSS, no channel context\n");
+               mutex_unlock(&local->mtx);
                return;
        }
+       mutex_unlock(&local->mtx);
 
        memcpy(ifibss->bssid, bssid, ETH_ALEN);
 
@@ -363,7 +366,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                sdata->vif.bss_conf.ssid_len = 0;
                RCU_INIT_POINTER(ifibss->presp, NULL);
                kfree_rcu(presp, rcu_head);
+               mutex_lock(&local->mtx);
                ieee80211_vif_release_channel(sdata);
+               mutex_unlock(&local->mtx);
                sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n",
                           err);
                return;
@@ -522,7 +527,7 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
        if (csa_settings)
                ieee80211_send_action_csa(sdata, csa_settings);
 
-       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
+       return BSS_CHANGED_BEACON;
  out:
        return ret;
 }
@@ -534,7 +539,8 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
        int err;
        u16 capability;
 
-       sdata_lock(sdata);
+       sdata_assert_lock(sdata);
+
        /* update cfg80211 bss information with the new channel */
        if (!is_zero_ether_addr(ifibss->bssid)) {
                capability = WLAN_CAPABILITY_IBSS;
@@ -559,10 +565,12 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
 
        /* generate the beacon */
        err = ieee80211_ibss_csa_beacon(sdata, NULL);
-       sdata_unlock(sdata);
        if (err < 0)
                return err;
 
+       if (err)
+               ieee80211_bss_info_change_notify(sdata, err);
+
        return 0;
 }
 
@@ -744,7 +752,9 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
                                                BSS_CHANGED_IBSS);
        drv_leave_ibss(local, sdata);
+       mutex_lock(&local->mtx);
        ieee80211_vif_release_channel(sdata);
+       mutex_unlock(&local->mtx);
 }
 
 static void ieee80211_csa_connection_drop_work(struct work_struct *work)
@@ -753,12 +763,16 @@ static void ieee80211_csa_connection_drop_work(struct work_struct *work)
                container_of(work, struct ieee80211_sub_if_data,
                             u.ibss.csa_connection_drop_work);
 
+       sdata_lock(sdata);
+
        ieee80211_ibss_disconnect(sdata);
        synchronize_rcu();
        skb_queue_purge(&sdata->skb_queue);
 
        /* trigger a scan to find another IBSS network to join */
        ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+
+       sdata_unlock(sdata);
 }
 
 static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
@@ -784,18 +798,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        struct cfg80211_csa_settings params;
        struct ieee80211_csa_ie csa_ie;
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-       struct ieee80211_chanctx_conf *chanctx_conf;
-       struct ieee80211_chanctx *chanctx;
        enum nl80211_channel_type ch_type;
-       int err, num_chanctx;
+       int err;
        u32 sta_flags;
 
-       if (sdata->vif.csa_active)
-               return true;
-
-       if (!sdata->vif.bss_conf.ibss_joined)
-               return false;
-
        sta_flags = IEEE80211_STA_DISABLE_VHT;
        switch (ifibss->chandef.width) {
        case NL80211_CHAN_WIDTH_5:
@@ -830,9 +836,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        params.count = csa_ie.count;
        params.chandef = csa_ie.chandef;
 
-       if (ifibss->chandef.chan->band != params.chandef.chan->band)
-               goto disconnect;
-
        switch (ifibss->chandef.width) {
        case NL80211_CHAN_WIDTH_20_NOHT:
        case NL80211_CHAN_WIDTH_20:
@@ -888,28 +891,12 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                params.radar_required = true;
        }
 
-       rcu_read_lock();
-       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-       if (!chanctx_conf) {
-               rcu_read_unlock();
-               goto disconnect;
-       }
-
-       /* don't handle for multi-VIF cases */
-       chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
-       if (chanctx->refcount > 1) {
-               rcu_read_unlock();
-               goto disconnect;
-       }
-       num_chanctx = 0;
-       list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list)
-               num_chanctx++;
-
-       if (num_chanctx > 1) {
-               rcu_read_unlock();
-               goto disconnect;
+       if (cfg80211_chandef_identical(&params.chandef,
+                                      &sdata->vif.bss_conf.chandef)) {
+               ibss_dbg(sdata,
+                        "received csa with an identical chandef, ignoring\n");
+               return true;
        }
-       rcu_read_unlock();
 
        /* all checks done, now perform the channel switch. */
        ibss_dbg(sdata,
@@ -918,19 +905,9 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 
        params.block_tx = !!csa_ie.mode;
 
-       ieee80211_ibss_csa_beacon(sdata, &params);
-       sdata->csa_radar_required = params.radar_required;
-
-       if (params.block_tx)
-               ieee80211_stop_queues_by_reason(&sdata->local->hw,
-                               IEEE80211_MAX_QUEUE_MAP,
-                               IEEE80211_QUEUE_STOP_REASON_CSA);
-
-       sdata->csa_chandef = params.chandef;
-       sdata->vif.csa_active = true;
-
-       ieee80211_bss_info_change_notify(sdata, err);
-       drv_channel_switch_beacon(sdata, &params.chandef);
+       if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev,
+                                    &params))
+               goto disconnect;
 
        ieee80211_ibss_csa_mark_radar(sdata);
 
@@ -966,7 +943,8 @@ ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata,
        if (len < required_len)
                return;
 
-       ieee80211_ibss_process_chanswitch(sdata, elems, false);
+       if (!sdata->vif.csa_active)
+               ieee80211_ibss_process_chanswitch(sdata, elems, false);
 }
 
 static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata,
@@ -1147,7 +1125,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                goto put_bss;
 
        /* process channel switch */
-       if (ieee80211_ibss_process_chanswitch(sdata, elems, true))
+       if (sdata->vif.csa_active ||
+           ieee80211_ibss_process_chanswitch(sdata, elems, true))
                goto put_bss;
 
        /* same BSSID */
index ed5bf8b4b5c2bfb8d4253a0dbaa15b76aac309dd..953b9e29454707b39460fb761a5ddba3e9377344 100644 (file)
@@ -232,6 +232,7 @@ struct ieee80211_rx_data {
 struct beacon_data {
        u8 *head, *tail;
        int head_len, tail_len;
+       struct ieee80211_meshconf_ie *meshconf;
        struct rcu_head rcu_head;
 };
 
@@ -245,7 +246,8 @@ struct ps_data {
        /* yes, this looks ugly, but guarantees that we can later use
         * bitmap_empty :)
         * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */
-       u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
+       u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]
+                       __aligned(__alignof__(unsigned long));
        struct sk_buff_head bc_buf;
        atomic_t num_sta_ps; /* number of stations in PS mode */
        int dtim_count;
@@ -540,7 +542,10 @@ struct ieee80211_mesh_sync_ops {
                             struct ieee80211_mgmt *mgmt,
                             struct ieee802_11_elems *elems,
                             struct ieee80211_rx_status *rx_status);
-       void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata);
+
+       /* should be called with beacon_data under RCU read lock */
+       void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata,
+                           struct beacon_data *beacon);
        /* add other framework functions here */
 };
 
@@ -614,6 +619,9 @@ struct ieee80211_if_mesh {
        bool chsw_init;
        u8 chsw_ttl;
        u16 pre_value;
+
+       /* offset from skb->data while building IE */
+       int meshconf_offset;
 };
 
 #ifdef CONFIG_MAC80211_MESH
@@ -686,6 +694,11 @@ struct ieee80211_chanctx {
        struct ieee80211_chanctx_conf conf;
 };
 
+struct mac80211_qos_map {
+       struct cfg80211_qos_map qos_map;
+       struct rcu_head rcu_head;
+};
+
 struct ieee80211_sub_if_data {
        struct list_head list;
 
@@ -731,6 +744,7 @@ struct ieee80211_sub_if_data {
        int encrypt_headroom;
 
        struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
+       struct mac80211_qos_map __rcu *qos_map;
 
        struct work_struct csa_finalize_work;
        int csa_counter_offset_beacon;
@@ -776,10 +790,6 @@ struct ieee80211_sub_if_data {
                u32 mntr_flags;
        } u;
 
-       spinlock_t cleanup_stations_lock;
-       struct list_head cleanup_stations;
-       struct work_struct cleanup_stations_wk;
-
 #ifdef CONFIG_MAC80211_DEBUGFS
        struct {
                struct dentry *subdir_stations;
@@ -1117,6 +1127,7 @@ struct ieee80211_local {
 
        struct work_struct sched_scan_stopped_work;
        struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
+       struct cfg80211_sched_scan_request *sched_scan_req;
 
        unsigned long leave_oper_channel_time;
        enum mac80211_scan_state next_scan_state;
@@ -1425,6 +1436,9 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local,
                          struct ieee80211_bss *bss);
 
 /* scheduled scan handling */
+int
+__ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
+                                    struct cfg80211_sched_scan_request *req);
 int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
                                       struct cfg80211_sched_scan_request *req);
 int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
@@ -1443,6 +1457,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
 
 /* channel switch handling */
 void ieee80211_csa_finalize_work(struct work_struct *work);
+int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+                            struct cfg80211_csa_settings *params);
 
 /* interface handling */
 int ieee80211_iface_init(void);
@@ -1465,8 +1481,6 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
 
 bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
 void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
-int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
-                           struct cfg80211_beacon_data *params);
 
 static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
 {
@@ -1768,8 +1782,6 @@ void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
 
 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
                                   struct ieee80211_chanctx *chanctx);
-void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
-                                   struct ieee80211_chanctx *chanctx);
 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
                                      struct ieee80211_chanctx *ctx);
 
index 7aa9f9dea9df0af487c25c36d52004179d76b72c..b2c83c0f06d027b80da1c4fe93e4028b0a379413 100644 (file)
@@ -418,8 +418,10 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
                return ret;
        }
 
+       mutex_lock(&local->mtx);
        ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
                                        IEEE80211_CHANCTX_EXCLUSIVE);
+       mutex_unlock(&local->mtx);
        if (ret) {
                drv_remove_interface(local, sdata);
                kfree(sdata);
@@ -456,7 +458,9 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
 
        synchronize_net();
 
+       mutex_lock(&local->mtx);
        ieee80211_vif_release_channel(sdata);
+       mutex_unlock(&local->mtx);
 
        drv_remove_interface(local, sdata);
 
@@ -786,10 +790,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
         * This is relevant only in WDS mode, in all other modes we've
         * already removed all stations when disconnecting or similar,
         * so warn otherwise.
-        *
-        * We call sta_info_flush_cleanup() later, to combine RCU waits.
         */
-       flushed = sta_info_flush_defer(sdata);
+       flushed = sta_info_flush(sdata);
        WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
                     (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));
 
@@ -828,9 +830,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        if (sdata->wdev.cac_started) {
                chandef = sdata->vif.bss_conf.chandef;
                WARN_ON(local->suspended);
-               mutex_lock(&local->iflist_mtx);
+               mutex_lock(&local->mtx);
                ieee80211_vif_release_channel(sdata);
-               mutex_unlock(&local->iflist_mtx);
+               mutex_unlock(&local->mtx);
                cfg80211_cac_event(sdata->dev, &chandef,
                                   NL80211_RADAR_CAC_ABORTED,
                                   GFP_KERNEL);
@@ -891,23 +893,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                cancel_work_sync(&sdata->work);
                /*
                 * When we get here, the interface is marked down.
+                * Free the remaining keys, if there are any
+                * (shouldn't be, except maybe in WDS mode?)
                 *
-                * sta_info_flush_cleanup() requires rcu_barrier()
-                * first to wait for the station call_rcu() calls
-                * to complete, and we also need synchronize_rcu()
-                * to wait for the RX path in case it is using the
-                * interface and enqueuing frames at this very time on
+                * Force the key freeing to always synchronize_net()
+                * to wait for the RX path in case it is using this
+                * interface enqueuing frames * at this very time on
                 * another CPU.
                 */
-               synchronize_rcu();
-               rcu_barrier();
-               sta_info_flush_cleanup(sdata);
-
-               /*
-                * Free all remaining keys, there shouldn't be any,
-                * except maybe in WDS mode?
-                */
-               ieee80211_free_keys(sdata);
+               ieee80211_free_keys(sdata, true);
 
                /* fall through */
        case NL80211_IFTYPE_AP:
@@ -1018,17 +1012,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
                        atomic_dec(&local->iff_promiscs);
                sdata->flags ^= IEEE80211_SDATA_PROMISC;
        }
-
-       /*
-        * TODO: If somebody needs this on AP interfaces,
-        *       it can be enabled easily but multicast
-        *       addresses from VLANs need to be synced.
-        */
-       if (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
-           sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
-           sdata->vif.type != NL80211_IFTYPE_AP)
-               drv_set_multicast_list(local, sdata, &dev->mc);
-
        spin_lock_bh(&local->filter_lock);
        __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
        spin_unlock_bh(&local->filter_lock);
@@ -1044,7 +1027,7 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
        int i;
 
        /* free extra data */
-       ieee80211_free_keys(sdata);
+       ieee80211_free_keys(sdata, false);
 
        ieee80211_debugfs_remove_netdev(sdata);
 
@@ -1497,8 +1480,8 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
                        bool used = false;
 
                        list_for_each_entry(sdata, &local->interfaces, list) {
-                               if (memcmp(local->hw.wiphy->addresses[i].addr,
-                                          sdata->vif.addr, ETH_ALEN) == 0) {
+                               if (ether_addr_equal(local->hw.wiphy->addresses[i].addr,
+                                                    sdata->vif.addr)) {
                                        used = true;
                                        break;
                                }
@@ -1558,8 +1541,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
                        val += inc;
 
                        list_for_each_entry(sdata, &local->interfaces, list) {
-                               if (memcmp(tmp_addr, sdata->vif.addr,
-                                                       ETH_ALEN) == 0) {
+                               if (ether_addr_equal(tmp_addr, sdata->vif.addr)) {
                                        used = true;
                                        break;
                                }
@@ -1579,15 +1561,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
        mutex_unlock(&local->iflist_mtx);
 }
 
-static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
-{
-       struct ieee80211_sub_if_data *sdata;
-
-       sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);
-
-       ieee80211_cleanup_sdata_stas(sdata);
-}
-
 int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                     struct wireless_dev **new_wdev, enum nl80211_iftype type,
                     struct vif_params *params)
@@ -1660,9 +1633,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
        INIT_LIST_HEAD(&sdata->key_list);
 
-       spin_lock_init(&sdata->cleanup_stations_lock);
-       INIT_LIST_HEAD(&sdata->cleanup_stations);
-       INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
        INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
                          ieee80211_dfs_cac_timer_work);
        INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
index e568d98167d0244e499e53c0b2a3aad1263b1ea0..6ff65a1ebaa905ffecfbdedebc7428882aecc551 100644 (file)
@@ -589,14 +589,10 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_iter_keys);
 
-void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
+                                     struct list_head *keys)
 {
        struct ieee80211_key *key, *tmp;
-       LIST_HEAD(keys);
-
-       cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
-
-       mutex_lock(&sdata->local->key_mtx);
 
        sdata->crypto_tx_tailroom_needed_cnt -=
                sdata->crypto_tx_tailroom_pending_dec;
@@ -608,28 +604,51 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
                ieee80211_key_replace(key->sdata, key->sta,
                                key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
                                key, NULL);
-               list_add_tail(&key->list, &keys);
+               list_add_tail(&key->list, keys);
        }
 
        ieee80211_debugfs_key_update_default(sdata);
+}
 
-       if (!list_empty(&keys)) {
-               synchronize_net();
-               list_for_each_entry_safe(key, tmp, &keys, list)
-                       __ieee80211_key_destroy(key, false);
+void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
+                        bool force_synchronize)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_sub_if_data *vlan;
+       struct ieee80211_key *key, *tmp;
+       LIST_HEAD(keys);
+
+       cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
+
+       mutex_lock(&local->key_mtx);
+
+       ieee80211_free_keys_iface(sdata, &keys);
+
+       if (sdata->vif.type == NL80211_IFTYPE_AP) {
+               list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+                       ieee80211_free_keys_iface(vlan, &keys);
        }
 
+       if (!list_empty(&keys) || force_synchronize)
+               synchronize_net();
+       list_for_each_entry_safe(key, tmp, &keys, list)
+               __ieee80211_key_destroy(key, false);
+
        WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
                     sdata->crypto_tx_tailroom_pending_dec);
+       if (sdata->vif.type == NL80211_IFTYPE_AP) {
+               list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+                       WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt ||
+                                    vlan->crypto_tx_tailroom_pending_dec);
+       }
 
-       mutex_unlock(&sdata->local->key_mtx);
+       mutex_unlock(&local->key_mtx);
 }
 
 void ieee80211_free_sta_keys(struct ieee80211_local *local,
                             struct sta_info *sta)
 {
-       struct ieee80211_key *key, *tmp;
-       LIST_HEAD(keys);
+       struct ieee80211_key *key;
        int i;
 
        mutex_lock(&local->key_mtx);
@@ -640,7 +659,7 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
                ieee80211_key_replace(key->sdata, key->sta,
                                key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
                                key, NULL);
-               list_add(&key->list, &keys);
+               __ieee80211_key_destroy(key, true);
        }
 
        for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
@@ -650,17 +669,8 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
                ieee80211_key_replace(key->sdata, key->sta,
                                key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
                                key, NULL);
-               list_add(&key->list, &keys);
-       }
-
-       /*
-        * NB: the station code relies on this being
-        * done even if there aren't any keys
-        */
-       synchronize_net();
-
-       list_for_each_entry_safe(key, tmp, &keys, list)
                __ieee80211_key_destroy(key, true);
+       }
 
        mutex_unlock(&local->key_mtx);
 }
index 0aebb889cabae566d6f33e00e59a2f299c9baa69..19db68663d7555461768eeae45a0afad8b0b163b 100644 (file)
@@ -136,7 +136,8 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
                               bool uni, bool multi);
 void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
                                    int idx);
-void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
+void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
+                        bool force_synchronize);
 void ieee80211_free_sta_keys(struct ieee80211_local *local,
                             struct sta_info *sta);
 void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
index fa34cd2344b98b9615a940a00e78363b494bc06c..2bd5b552b2f6c41629022876265bdd9a10e8890e 100644 (file)
@@ -250,12 +250,8 @@ static void ieee80211_restart_work(struct work_struct *work)
        /* wait for scan work complete */
        flush_workqueue(local->workqueue);
 
-       mutex_lock(&local->mtx);
-       WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
-            rcu_dereference_protected(local->sched_scan_sdata,
-                                      lockdep_is_held(&local->mtx)),
-               "%s called with hardware scan in progress\n", __func__);
-       mutex_unlock(&local->mtx);
+       WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
+            "%s called with hardware scan in progress\n", __func__);
 
        rtnl_lock();
        ieee80211_scan_cancel(local);
index 89df62b2b6896f05a2d3170bce62a40fff23cf8c..5a74b249ba35d0f47a499b08d4d0f04d75d4a5ec 100644 (file)
@@ -259,6 +259,9 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
        *pos++ = WLAN_EID_MESH_CONFIG;
        *pos++ = meshconf_len;
 
+       /* save a pointer for quick updates in pre-tbtt */
+       ifmsh->meshconf_offset = pos - skb->data;
+
        /* Active path selection protocol ID */
        *pos++ = ifmsh->mesh_pp_id;
        /* Active path selection metric ID   */
@@ -723,6 +726,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
 
        bcn->tail_len = skb->len;
        memcpy(bcn->tail, skb->data, bcn->tail_len);
+       bcn->meshconf = (struct ieee80211_meshconf_ie *)
+                                       (bcn->tail + ifmsh->meshconf_offset);
 
        dev_kfree_skb(skb);
        rcu_assign_pointer(ifmsh->beacon, bcn);
index d1cf2d5534998957c13cfbd5ca23c630d7c9f6a7..2bc5dc25d5adc79a92cd29bc94d058e141d011c6 100644 (file)
@@ -164,12 +164,15 @@ no_sync:
        rcu_read_unlock();
 }
 
-static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
+static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata,
+                                        struct beacon_data *beacon)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+       u8 cap;
 
        WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET);
        BUG_ON(!rcu_read_lock_held());
+       cap = beacon->meshconf->meshconf_cap;
 
        spin_lock_bh(&ifmsh->sync_offset_lock);
 
@@ -194,6 +197,10 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
                ifmsh->adjusting_tbtt = false;
        }
        spin_unlock_bh(&ifmsh->sync_offset_lock);
+
+       beacon->meshconf->meshconf_cap = ifmsh->adjusting_tbtt ?
+                       IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING | cap :
+                       ~IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING & cap;
 }
 
 static const struct sync_method sync_methods[] = {
index 900ead344f5bd526fa5f9a54b438a8cae52012e6..fc1d82465b3ce1b1cdcc9edb4f5157618b70e8ce 100644 (file)
@@ -888,7 +888,9 @@ static void ieee80211_chswitch_work(struct work_struct *work)
        if (!ifmgd->associated)
                goto out;
 
+       mutex_lock(&local->mtx);
        ret = ieee80211_vif_change_channel(sdata, &changed);
+       mutex_unlock(&local->mtx);
        if (ret) {
                sdata_info(sdata,
                           "vif channel switch failed, disconnecting\n");
@@ -1401,10 +1403,14 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work)
                             dfs_cac_timer_work);
        struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef;
 
-       ieee80211_vif_release_channel(sdata);
-       cfg80211_cac_event(sdata->dev, &chandef,
-                          NL80211_RADAR_CAC_FINISHED,
-                          GFP_KERNEL);
+       mutex_lock(&sdata->local->mtx);
+       if (sdata->wdev.cac_started) {
+               ieee80211_vif_release_channel(sdata);
+               cfg80211_cac_event(sdata->dev, &chandef,
+                                  NL80211_RADAR_CAC_FINISHED,
+                                  GFP_KERNEL);
+       }
+       mutex_unlock(&sdata->local->mtx);
 }
 
 /* MLME */
@@ -1698,7 +1704,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        memset(ifmgd->bssid, 0, ETH_ALEN);
 
        /* remove AP and TDLS peers */
-       sta_info_flush_defer(sdata);
+       sta_info_flush(sdata);
 
        /* finally reset all BSS / config parameters */
        changed |= ieee80211_reset_erp_info(sdata);
@@ -1747,7 +1753,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        ifmgd->have_beacon = false;
 
        ifmgd->flags = 0;
+       mutex_lock(&local->mtx);
        ieee80211_vif_release_channel(sdata);
+       mutex_unlock(&local->mtx);
 
        sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
 }
@@ -2070,7 +2078,9 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
                memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
                sdata->u.mgd.flags = 0;
+               mutex_lock(&sdata->local->mtx);
                ieee80211_vif_release_channel(sdata);
+               mutex_unlock(&sdata->local->mtx);
        }
 
        cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss);
@@ -2319,7 +2329,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
                memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
                sdata->u.mgd.flags = 0;
+               mutex_lock(&sdata->local->mtx);
                ieee80211_vif_release_channel(sdata);
+               mutex_unlock(&sdata->local->mtx);
        }
 
        kfree(assoc_data);
@@ -3670,6 +3682,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        /* will change later if needed */
        sdata->smps_mode = IEEE80211_SMPS_OFF;
 
+       mutex_lock(&local->mtx);
        /*
         * If this fails (possibly due to channel context sharing
         * on incompatible channels, e.g. 80+80 and 160 sharing the
@@ -3681,13 +3694,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        /* don't downgrade for 5 and 10 MHz channels, though. */
        if (chandef.width == NL80211_CHAN_WIDTH_5 ||
            chandef.width == NL80211_CHAN_WIDTH_10)
-               return ret;
+               goto out;
 
        while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
                ifmgd->flags |= ieee80211_chandef_downgrade(&chandef);
                ret = ieee80211_vif_use_channel(sdata, &chandef,
                                                IEEE80211_CHANCTX_SHARED);
        }
+ out:
+       mutex_unlock(&local->mtx);
        return ret;
 }
 
index 340126204343a063902bb205675cc14bea743a4c..af64fb8e8addb58e5933cc3a45a8043f55659f81 100644 (file)
@@ -37,9 +37,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
                                        IEEE80211_MAX_QUEUE_MAP,
                                        IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
-       /* flush out all packets and station cleanup call_rcu()s */
+       /* flush out all packets */
        synchronize_net();
-       rcu_barrier();
 
        ieee80211_flush_queues(local, NULL);
 
index d2f19f7e7091b6e6b9111702f19b02f612fdb52c..f3d88b0c054c219fde20b907195c3bdb5a481c97 100644 (file)
@@ -135,7 +135,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
        u32 usecs;
        int i;
 
-       for (i=0; i < MAX_THR_RATES; i++)
+       for (i = 0; i < MAX_THR_RATES; i++)
            tmp_tp_rate[i] = 0;
 
        for (i = 0; i < mi->n_rates; i++) {
@@ -190,7 +190,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
                 * choose the maximum throughput rate as max_prob_rate
                 * (2) if all success probabilities < 95%, the rate with
                 * highest success probability is choosen as max_prob_rate */
-               if (mr->probability >= MINSTREL_FRAC(95,100)) {
+               if (mr->probability >= MINSTREL_FRAC(95, 100)) {
                        if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp)
                                tmp_prob_rate = i;
                } else {
@@ -220,7 +220,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 
 static void
 minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
-                   struct ieee80211_sta *sta, void *priv_sta,
+                  struct ieee80211_sta *sta, void *priv_sta,
                   struct sk_buff *skb)
 {
        struct minstrel_priv *mp = priv;
@@ -260,7 +260,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
 
 static inline unsigned int
 minstrel_get_retry_count(struct minstrel_rate *mr,
-                         struct ieee80211_tx_info *info)
+                        struct ieee80211_tx_info *info)
 {
        unsigned int retry = mr->adjusted_retry_count;
 
index d2ed18d82fe1dd1f55a2f5c13f319920bbb9b887..c1b5b73c5b91353597eb1dfcf7a0f70946c72562 100644 (file)
@@ -63,7 +63,7 @@
 
 #define CCK_DURATION(_bitrate, _short, _len)           \
        (1000 * (10 /* SIFS */ +                        \
-        (_short ? 72 + 24 : 144 + 48 ) +               \
+        (_short ? 72 + 24 : 144 + 48) +                \
         (8 * (_len + 4) * 10) / (_bitrate)))
 
 #define CCK_ACK_DURATION(_bitrate, _short)                     \
index 2dfa755227339533d2c105313ba8ab4ea3ba67b5..5a2afe9583a806d5f9059c390e0cc70ae7799e22 100644 (file)
@@ -1963,20 +1963,17 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
                }
        }
 
-       if (skb) {
-               int align __maybe_unused;
-
 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-               /*
-                * 'align' will only take the values 0 or 2 here
-                * since all frames are required to be aligned
-                * to 2-byte boundaries when being passed to
-                * mac80211; the code here works just as well if
-                * that isn't true, but mac80211 assumes it can
-                * access fields as 2-byte aligned (e.g. for
-                * compare_ether_addr)
+       if (skb) {
+               /* 'align' will only take the values 0 or 2 here since all
+                * frames are required to be aligned to 2-byte boundaries
+                * when being passed to mac80211; the code here works just
+                * as well if that isn't true, but mac80211 assumes it can
+                * access fields as 2-byte aligned (e.g. for ether_addr_equal)
                 */
-               align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3;
+               int align;
+
+               align = (unsigned long)(skb->data + sizeof(struct ethhdr)) & 3;
                if (align) {
                        if (WARN_ON(skb_headroom(skb) < 3)) {
                                dev_kfree_skb(skb);
@@ -1989,14 +1986,14 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
                                skb_set_tail_pointer(skb, len);
                        }
                }
+       }
 #endif
 
-               if (skb) {
-                       /* deliver to local stack */
-                       skb->protocol = eth_type_trans(skb, dev);
-                       memset(skb->cb, 0, sizeof(skb->cb));
-                       netif_receive_skb(skb);
-               }
+       if (skb) {
+               /* deliver to local stack */
+               skb->protocol = eth_type_trans(skb, dev);
+               memset(skb->cb, 0, sizeof(skb->cb));
+               netif_receive_skb(skb);
        }
 
        if (xmit_skb) {
index 4d73c46df86262a385ad5fb9a5912c6a8168831e..88c81616f8f758595e90cced1d503448ce6ba969 100644 (file)
@@ -271,10 +271,11 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
        return true;
 }
 
-static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
-                                      bool was_hw_scan)
+static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
 {
        struct ieee80211_local *local = hw_to_local(hw);
+       bool hw_scan = local->ops->hw_scan;
+       bool was_scanning = local->scanning;
 
        lockdep_assert_held(&local->mtx);
 
@@ -290,7 +291,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
        if (WARN_ON(!local->scan_req))
                return;
 
-       if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
+       if (hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
                int rc;
 
                rc = drv_hw_scan(local,
@@ -316,7 +317,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
        /* Set power back to normal operating levels. */
        ieee80211_hw_config(local, 0);
 
-       if (!was_hw_scan) {
+       if (!hw_scan) {
                ieee80211_configure_filter(local);
                drv_sw_scan_complete(local);
                ieee80211_offchannel_return(local);
@@ -327,7 +328,8 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
        ieee80211_mlme_notify_scan_completed(local);
        ieee80211_ibss_notify_scan_completed(local);
        ieee80211_mesh_notify_scan_completed(local);
-       ieee80211_start_next_roc(local);
+       if (was_scanning)
+               ieee80211_start_next_roc(local);
 }
 
 void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
@@ -747,7 +749,7 @@ void ieee80211_scan_work(struct work_struct *work)
                container_of(work, struct ieee80211_local, scan_work.work);
        struct ieee80211_sub_if_data *sdata;
        unsigned long next_delay = 0;
-       bool aborted, hw_scan;
+       bool aborted;
 
        mutex_lock(&local->mtx);
 
@@ -785,14 +787,6 @@ void ieee80211_scan_work(struct work_struct *work)
                        goto out;
        }
 
-       /*
-        * Avoid re-scheduling when the sdata is going away.
-        */
-       if (!ieee80211_sdata_running(sdata)) {
-               aborted = true;
-               goto out_complete;
-       }
-
        /*
         * as long as no delay is required advance immediately
         * without scheduling a new work
@@ -834,8 +828,7 @@ void ieee80211_scan_work(struct work_struct *work)
        goto out;
 
 out_complete:
-       hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
-       __ieee80211_scan_completed(&local->hw, aborted, hw_scan);
+       __ieee80211_scan_completed(&local->hw, aborted);
 out:
        mutex_unlock(&local->mtx);
 }
@@ -973,13 +966,13 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
         */
        cancel_delayed_work(&local->scan_work);
        /* and clean up */
-       __ieee80211_scan_completed(&local->hw, true, false);
+       __ieee80211_scan_completed(&local->hw, true);
 out:
        mutex_unlock(&local->mtx);
 }
 
-int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
-                                      struct cfg80211_sched_scan_request *req)
+int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
+                                       struct cfg80211_sched_scan_request *req)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_sched_scan_ies sched_scan_ies = {};
@@ -989,17 +982,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
        iebufsz = 2 + IEEE80211_MAX_SSID_LEN +
                  local->scan_ies_len + req->ie_len;
 
-       mutex_lock(&local->mtx);
-
-       if (rcu_access_pointer(local->sched_scan_sdata)) {
-               ret = -EBUSY;
-               goto out;
-       }
+       lockdep_assert_held(&local->mtx);
 
-       if (!local->ops->sched_scan_start) {
-               ret = -ENOTSUPP;
-               goto out;
-       }
+       if (!local->ops->sched_scan_start)
+               return -ENOTSUPP;
 
        for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
                if (!local->hw.wiphy->bands[i])
@@ -1020,13 +1006,39 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
        }
 
        ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
-       if (ret == 0)
+       if (ret == 0) {
                rcu_assign_pointer(local->sched_scan_sdata, sdata);
+               local->sched_scan_req = req;
+       }
 
 out_free:
        while (i > 0)
                kfree(sched_scan_ies.ie[--i]);
-out:
+
+       if (ret) {
+               /* Clean in case of failure after HW restart or upon resume. */
+               rcu_assign_pointer(local->sched_scan_sdata, NULL);
+               local->sched_scan_req = NULL;
+       }
+
+       return ret;
+}
+
+int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
+                                      struct cfg80211_sched_scan_request *req)
+{
+       struct ieee80211_local *local = sdata->local;
+       int ret;
+
+       mutex_lock(&local->mtx);
+
+       if (rcu_access_pointer(local->sched_scan_sdata)) {
+               mutex_unlock(&local->mtx);
+               return -EBUSY;
+       }
+
+       ret = __ieee80211_request_sched_scan_start(sdata, req);
+
        mutex_unlock(&local->mtx);
        return ret;
 }
@@ -1043,6 +1055,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
                goto out;
        }
 
+       /* We don't want to restart sched scan anymore. */
+       local->sched_scan_req = NULL;
+
        if (rcu_access_pointer(local->sched_scan_sdata))
                drv_sched_scan_stop(local, sdata);
 
@@ -1077,6 +1092,9 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
 
        rcu_assign_pointer(local->sched_scan_sdata, NULL);
 
+       /* If sched scan was aborted by the driver. */
+       local->sched_scan_req = NULL;
+
        mutex_unlock(&local->mtx);
 
        cfg80211_sched_scan_stopped(local->hw.wiphy);
index 8ed97f76c3cfade5f0986fa2d17c8275753b3c35..4576ba0ff2211af31664b10dd40e996e490286df 100644 (file)
@@ -99,23 +99,6 @@ static void cleanup_single_sta(struct sta_info *sta)
        struct ieee80211_local *local = sdata->local;
        struct ps_data *ps;
 
-       /*
-        * At this point, when being called as call_rcu callback,
-        * neither mac80211 nor the driver can reference this
-        * sta struct any more except by still existing timers
-        * associated with this station that we clean up below.
-        *
-        * Note though that this still uses the sdata and even
-        * calls the driver in AP and mesh mode, so interfaces
-        * of those types mush use call sta_info_flush_cleanup()
-        * (typically via sta_info_flush()) before deconfiguring
-        * the driver.
-        *
-        * In station mode, nothing happens here so it doesn't
-        * have to (and doesn't) do that, this is intentional to
-        * speed up roaming.
-        */
-
        if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
                if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
                    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -160,37 +143,6 @@ static void cleanup_single_sta(struct sta_info *sta)
        sta_info_free(local, sta);
 }
 
-void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata)
-{
-       struct sta_info *sta;
-
-       spin_lock_bh(&sdata->cleanup_stations_lock);
-       while (!list_empty(&sdata->cleanup_stations)) {
-               sta = list_first_entry(&sdata->cleanup_stations,
-                                      struct sta_info, list);
-               list_del(&sta->list);
-               spin_unlock_bh(&sdata->cleanup_stations_lock);
-
-               cleanup_single_sta(sta);
-
-               spin_lock_bh(&sdata->cleanup_stations_lock);
-       }
-
-       spin_unlock_bh(&sdata->cleanup_stations_lock);
-}
-
-static void free_sta_rcu(struct rcu_head *h)
-{
-       struct sta_info *sta = container_of(h, struct sta_info, rcu_head);
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
-
-       spin_lock(&sdata->cleanup_stations_lock);
-       list_add_tail(&sta->list, &sdata->cleanup_stations);
-       spin_unlock(&sdata->cleanup_stations_lock);
-
-       ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk);
-}
-
 /* protected by RCU */
 struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
                              const u8 *addr)
@@ -842,7 +794,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
        return have_buffered;
 }
 
-int __must_check __sta_info_destroy(struct sta_info *sta)
+static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
 {
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
@@ -868,12 +820,35 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA);
 
        ret = sta_info_hash_del(local, sta);
-       if (ret)
+       if (WARN_ON(ret))
                return ret;
 
        list_del_rcu(&sta->list);
 
-       /* this always calls synchronize_net() */
+       drv_sta_pre_rcu_remove(local, sta->sdata, sta);
+
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+           rcu_access_pointer(sdata->u.vlan.sta) == sta)
+               RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
+
+       return 0;
+}
+
+static void __sta_info_destroy_part2(struct sta_info *sta)
+{
+       struct ieee80211_local *local = sta->local;
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
+       int ret;
+
+       /*
+        * NOTE: This assumes at least synchronize_net() was done
+        *       after _part1 and before _part2!
+        */
+
+       might_sleep();
+       lockdep_assert_held(&local->sta_mtx);
+
+       /* now keys can no longer be reached */
        ieee80211_free_sta_keys(local, sta);
 
        sta->dead = true;
@@ -881,9 +856,6 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        local->num_sta--;
        local->sta_generation++;
 
-       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-               RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
-
        while (sta->sta_state > IEEE80211_STA_NONE) {
                ret = sta_info_move_state(sta, sta->sta_state - 1);
                if (ret) {
@@ -906,7 +878,19 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        ieee80211_sta_debugfs_remove(sta);
        ieee80211_recalc_min_chandef(sdata);
 
-       call_rcu(&sta->rcu_head, free_sta_rcu);
+       cleanup_single_sta(sta);
+}
+
+int __must_check __sta_info_destroy(struct sta_info *sta)
+{
+       int err = __sta_info_destroy_part1(sta);
+
+       if (err)
+               return err;
+
+       synchronize_net();
+
+       __sta_info_destroy_part2(sta);
 
        return 0;
 }
@@ -976,32 +960,38 @@ void sta_info_stop(struct ieee80211_local *local)
 }
 
 
-int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata)
+int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans)
 {
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta, *tmp;
+       LIST_HEAD(free_list);
        int ret = 0;
 
        might_sleep();
 
+       WARN_ON(vlans && sdata->vif.type != NL80211_IFTYPE_AP);
+       WARN_ON(vlans && !sdata->bss);
+
        mutex_lock(&local->sta_mtx);
        list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
-               if (sdata == sta->sdata) {
-                       WARN_ON(__sta_info_destroy(sta));
+               if (sdata == sta->sdata ||
+                   (vlans && sdata->bss == sta->sdata->bss)) {
+                       if (!WARN_ON(__sta_info_destroy_part1(sta)))
+                               list_add(&sta->free_list, &free_list);
                        ret++;
                }
        }
+
+       if (!list_empty(&free_list)) {
+               synchronize_net();
+               list_for_each_entry_safe(sta, tmp, &free_list, free_list)
+                       __sta_info_destroy_part2(sta);
+       }
        mutex_unlock(&local->sta_mtx);
 
        return ret;
 }
 
-void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata)
-{
-       ieee80211_cleanup_sdata_stas(sdata);
-       cancel_work_sync(&sdata->cleanup_stations_wk);
-}
-
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
                          unsigned long exp_time)
 {
index 0218caf5c14a793ef14045da6c0db6a13781b259..d77ff70906303855458734a5bfac0526460056eb 100644 (file)
@@ -247,6 +247,7 @@ struct ieee80211_tx_latency_stat {
  * mac80211 is communicating with.
  *
  * @list: global linked list entry
+ * @free_list: list entry for keeping track of stations to free
  * @hnext: hash table linked list pointer
  * @local: pointer to the global information
  * @sdata: virtual interface this station belongs to
@@ -329,7 +330,7 @@ struct ieee80211_tx_latency_stat {
  */
 struct sta_info {
        /* General information, mostly static */
-       struct list_head list;
+       struct list_head list, free_list;
        struct rcu_head rcu_head;
        struct sta_info __rcu *hnext;
        struct ieee80211_local *local;
@@ -605,21 +606,6 @@ void sta_info_recalc_tim(struct sta_info *sta);
 
 void sta_info_init(struct ieee80211_local *local);
 void sta_info_stop(struct ieee80211_local *local);
-int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata);
-
-/**
- * sta_info_flush_cleanup - flush the sta_info cleanup queue
- * @sdata: the interface
- *
- * Flushes the sta_info cleanup queue for a given interface;
- * this is necessary before the interface is removed or, for
- * AP/mesh interfaces, before it is deconfigured.
- *
- * Note an rcu_barrier() must precede the function, after all
- * stations have been flushed/removed to ensure the call_rcu()
- * calls that add stations to the cleanup queue have completed.
- */
-void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata);
 
 /**
  * sta_info_flush - flush matching STA entries from the STA table
@@ -627,15 +613,13 @@ void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata);
  * Returns the number of removed STA entries.
  *
  * @sdata: sdata to remove all stations from
+ * @vlans: if the given interface is an AP interface, also flush VLANs
  */
+int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans);
+
 static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata)
 {
-       int ret = sta_info_flush_defer(sdata);
-
-       rcu_barrier();
-       sta_info_flush_cleanup(sdata);
-
-       return ret;
+       return __sta_info_flush(sdata, false);
 }
 
 void sta_set_rate_info_tx(struct sta_info *sta,
@@ -651,6 +635,4 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
 
-void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata);
-
 #endif /* STA_INFO_H */
index 124b1fdc20d05531bccfa32e6ccc5f72c7cef1bb..0ae207771a5837ff73d359fe4032be26ac4ca358 100644 (file)
@@ -186,7 +186,7 @@ void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf,
 EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv);
 
 void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf,
-                               const u8 *ta, u32 iv32, u16 *p1k)
+                              const u8 *ta, u32 iv32, u16 *p1k)
 {
        const u8 *tk = &keyconf->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
        struct tkip_ctx ctx;
index e9ccf22f6dd972c8b0517c5d35a345085eb45ec6..da9366632f378651d14c12d543aa80525d8a6ba8 100644 (file)
@@ -443,30 +443,6 @@ TRACE_EVENT(drv_prepare_multicast,
        )
 );
 
-TRACE_EVENT(drv_set_multicast_list,
-       TP_PROTO(struct ieee80211_local *local,
-                struct ieee80211_sub_if_data *sdata, int mc_count),
-
-       TP_ARGS(local, sdata, mc_count),
-
-       TP_STRUCT__entry(
-               LOCAL_ENTRY
-               __field(bool, allmulti)
-               __field(int, mc_count)
-       ),
-
-       TP_fast_assign(
-               LOCAL_ASSIGN;
-               __entry->allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
-               __entry->mc_count = mc_count;
-       ),
-
-       TP_printk(
-               LOCAL_PR_FMT " configure mc filter, count=%d, allmulti=%d",
-               LOCAL_PR_ARG, __entry->mc_count, __entry->allmulti
-       )
-);
-
 TRACE_EVENT(drv_configure_filter,
        TP_PROTO(struct ieee80211_local *local,
                 unsigned int changed_flags,
@@ -577,7 +553,7 @@ TRACE_EVENT(drv_update_tkip_key,
 
        TP_printk(
                LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " iv32:%#x",
-               LOCAL_PR_ARG,VIF_PR_ARG,STA_PR_ARG, __entry->iv32
+               LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->iv32
        )
 );
 
@@ -790,7 +766,7 @@ TRACE_EVENT(drv_sta_rc_update,
        )
 );
 
-TRACE_EVENT(drv_sta_add,
+DECLARE_EVENT_CLASS(sta_event,
        TP_PROTO(struct ieee80211_local *local,
                 struct ieee80211_sub_if_data *sdata,
                 struct ieee80211_sta *sta),
@@ -815,29 +791,25 @@ TRACE_EVENT(drv_sta_add,
        )
 );
 
-TRACE_EVENT(drv_sta_remove,
+DEFINE_EVENT(sta_event, drv_sta_add,
        TP_PROTO(struct ieee80211_local *local,
                 struct ieee80211_sub_if_data *sdata,
                 struct ieee80211_sta *sta),
+       TP_ARGS(local, sdata, sta)
+);
 
-       TP_ARGS(local, sdata, sta),
-
-       TP_STRUCT__entry(
-               LOCAL_ENTRY
-               VIF_ENTRY
-               STA_ENTRY
-       ),
-
-       TP_fast_assign(
-               LOCAL_ASSIGN;
-               VIF_ASSIGN;
-               STA_ASSIGN;
-       ),
+DEFINE_EVENT(sta_event, drv_sta_remove,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_sta *sta),
+       TP_ARGS(local, sdata, sta)
+);
 
-       TP_printk(
-               LOCAL_PR_FMT  VIF_PR_FMT  STA_PR_FMT,
-               LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG
-       )
+DEFINE_EVENT(sta_event, drv_sta_pre_rcu_remove,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_sta *sta),
+       TP_ARGS(local, sdata, sta)
 );
 
 TRACE_EVENT(drv_conf_tx,
index 6d59e21cdb9fe8b686fdcef53ddc83a83738d0cf..377cf974d97d15b41773b0ea7aed9ae7ebc1edba 100644 (file)
@@ -2161,7 +2161,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        if (ieee80211_is_data_qos(fc)) {
                __le16 *qos_control;
 
-               qos_control = (__le16*) skb_push(skb, 2);
+               qos_control = (__le16 *) skb_push(skb, 2);
                memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2);
                /*
                 * Maybe we could actually set some fields here, for now just
@@ -2323,7 +2323,7 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
        if (atomic_read(&ps->num_sta_ps) > 0)
                /* in the hope that this is faster than
                 * checking byte-for-byte */
-               have_bits = !bitmap_empty((unsigned long*)ps->tim,
+               have_bits = !bitmap_empty((unsigned long *)ps->tim,
                                          IEEE80211_MAX_AID+1);
 
        if (ps->dtim_count == 0)
@@ -2549,7 +2549,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                         */
                        skb = dev_alloc_skb(local->tx_headroom +
                                            beacon->head_len +
-                                           beacon->tail_len + 256);
+                                           beacon->tail_len + 256 +
+                                           local->hw.extra_beacon_tailroom);
                        if (!skb)
                                goto out;
 
@@ -2581,7 +2582,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                        ieee80211_update_csa(sdata, presp);
 
 
-               skb = dev_alloc_skb(local->tx_headroom + presp->head_len);
+               skb = dev_alloc_skb(local->tx_headroom + presp->head_len +
+                                   local->hw.extra_beacon_tailroom);
                if (!skb)
                        goto out;
                skb_reserve(skb, local->tx_headroom);
@@ -2602,13 +2604,13 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                        ieee80211_update_csa(sdata, bcn);
 
                if (ifmsh->sync_ops)
-                       ifmsh->sync_ops->adjust_tbtt(
-                                               sdata);
+                       ifmsh->sync_ops->adjust_tbtt(sdata, bcn);
 
                skb = dev_alloc_skb(local->tx_headroom +
                                    bcn->head_len +
                                    256 + /* TIM IE */
-                                   bcn->tail_len);
+                                   bcn->tail_len +
+                                   local->hw.extra_beacon_tailroom);
                if (!skb)
                        goto out;
                skb_reserve(skb, local->tx_headroom);
index 875e172c001c697a72f85941fd0db8ef1b28b86a..df00f1978a77574857a9e8cf5c37cad66ce3e487 100644 (file)
@@ -76,7 +76,7 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
        }
 
        if (ieee80211_is_ctl(fc)) {
-               if(ieee80211_is_pspoll(fc))
+               if (ieee80211_is_pspoll(fc))
                        return hdr->addr1;
 
                if (ieee80211_is_back_req(fc)) {
@@ -642,6 +642,17 @@ void ieee80211_iterate_active_interfaces_rtnl(
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl);
 
+struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+
+       if (!ieee80211_sdata_running(sdata) ||
+           !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+               return NULL;
+       return &sdata->vif;
+}
+EXPORT_SYMBOL_GPL(wdev_to_ieee80211_vif);
+
 /*
  * Nothing should have been stuffed into the workqueue during
  * the suspend->resume cycle. If this WARN is seen then there
@@ -1451,6 +1462,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        struct sta_info *sta;
        int res, i;
        bool reconfig_due_to_wowlan = false;
+       struct ieee80211_sub_if_data *sched_scan_sdata;
+       bool sched_scan_stopped = false;
 
 #ifdef CONFIG_PM
        if (local->suspended)
@@ -1754,6 +1767,27 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 #else
        WARN_ON(1);
 #endif
+
+       /*
+        * Reconfigure sched scan if it was interrupted by FW restart or
+        * suspend.
+        */
+       mutex_lock(&local->mtx);
+       sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
+                                               lockdep_is_held(&local->mtx));
+       if (sched_scan_sdata && local->sched_scan_req)
+               /*
+                * Sched scan stopped, but we don't want to report it. Instead,
+                * we're trying to reschedule.
+                */
+               if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
+                                                        local->sched_scan_req))
+                       sched_scan_stopped = true;
+       mutex_unlock(&local->mtx);
+
+       if (sched_scan_stopped)
+               cfg80211_sched_scan_stopped(local->hw.wiphy);
+
        return 0;
 }
 
@@ -2281,9 +2315,14 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
        struct ieee80211_sub_if_data *sdata;
        struct cfg80211_chan_def chandef;
 
+       mutex_lock(&local->mtx);
        mutex_lock(&local->iflist_mtx);
        list_for_each_entry(sdata, &local->interfaces, list) {
-               cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
+               /* it might be waiting for the local->mtx, but then
+                * by the time it gets it, sdata->wdev.cac_started
+                * will no longer be true
+                */
+               cancel_delayed_work(&sdata->dfs_cac_timer_work);
 
                if (sdata->wdev.cac_started) {
                        chandef = sdata->vif.bss_conf.chandef;
@@ -2295,6 +2334,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
                }
        }
        mutex_unlock(&local->iflist_mtx);
+       mutex_unlock(&local->mtx);
 }
 
 void ieee80211_dfs_radar_detected_work(struct work_struct *work)
@@ -2554,3 +2594,143 @@ int ieee80211_cs_headroom(struct ieee80211_local *local,
 
        return headroom;
 }
+
+static bool
+ieee80211_extend_noa_desc(struct ieee80211_noa_data *data, u32 tsf, int i)
+{
+       s32 end = data->desc[i].start + data->desc[i].duration - (tsf + 1);
+       int skip;
+
+       if (end > 0)
+               return false;
+
+       /* End time is in the past, check for repetitions */
+       skip = DIV_ROUND_UP(-end, data->desc[i].interval);
+       if (data->count[i] < 255) {
+               if (data->count[i] <= skip) {
+                       data->count[i] = 0;
+                       return false;
+               }
+
+               data->count[i] -= skip;
+       }
+
+       data->desc[i].start += skip * data->desc[i].interval;
+
+       return true;
+}
+
+static bool
+ieee80211_extend_absent_time(struct ieee80211_noa_data *data, u32 tsf,
+                            s32 *offset)
+{
+       bool ret = false;
+       int i;
+
+       for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) {
+               s32 cur;
+
+               if (!data->count[i])
+                       continue;
+
+               if (ieee80211_extend_noa_desc(data, tsf + *offset, i))
+                       ret = true;
+
+               cur = data->desc[i].start - tsf;
+               if (cur > *offset)
+                       continue;
+
+               cur = data->desc[i].start + data->desc[i].duration - tsf;
+               if (cur > *offset)
+                       *offset = cur;
+       }
+
+       return ret;
+}
+
+static u32
+ieee80211_get_noa_absent_time(struct ieee80211_noa_data *data, u32 tsf)
+{
+       s32 offset = 0;
+       int tries = 0;
+       /*
+        * arbitrary limit, used to avoid infinite loops when combined NoA
+        * descriptors cover the full time period.
+        */
+       int max_tries = 5;
+
+       ieee80211_extend_absent_time(data, tsf, &offset);
+       do {
+               if (!ieee80211_extend_absent_time(data, tsf, &offset))
+                       break;
+
+               tries++;
+       } while (tries < max_tries);
+
+       return offset;
+}
+
+void ieee80211_update_p2p_noa(struct ieee80211_noa_data *data, u32 tsf)
+{
+       u32 next_offset = BIT(31) - 1;
+       int i;
+
+       data->absent = 0;
+       data->has_next_tsf = false;
+       for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) {
+               s32 start;
+
+               if (!data->count[i])
+                       continue;
+
+               ieee80211_extend_noa_desc(data, tsf, i);
+               start = data->desc[i].start - tsf;
+               if (start <= 0)
+                       data->absent |= BIT(i);
+
+               if (next_offset > start)
+                       next_offset = start;
+
+               data->has_next_tsf = true;
+       }
+
+       if (data->absent)
+               next_offset = ieee80211_get_noa_absent_time(data, tsf);
+
+       data->next_tsf = tsf + next_offset;
+}
+EXPORT_SYMBOL(ieee80211_update_p2p_noa);
+
+int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr,
+                           struct ieee80211_noa_data *data, u32 tsf)
+{
+       int ret = 0;
+       int i;
+
+       memset(data, 0, sizeof(*data));
+
+       for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) {
+               const struct ieee80211_p2p_noa_desc *desc = &attr->desc[i];
+
+               if (!desc->count || !desc->duration)
+                       continue;
+
+               data->count[i] = desc->count;
+               data->desc[i].start = le32_to_cpu(desc->start_time);
+               data->desc[i].duration = le32_to_cpu(desc->duration);
+               data->desc[i].interval = le32_to_cpu(desc->interval);
+
+               if (data->count[i] > 1 &&
+                   data->desc[i].interval < data->desc[i].duration)
+                       continue;
+
+               ieee80211_extend_noa_desc(data, tsf, i);
+               ret++;
+       }
+
+       if (ret)
+               ieee80211_update_p2p_noa(data, tsf);
+
+       return ret;
+}
+EXPORT_SYMBOL(ieee80211_parse_p2p_noa);
index afba19cb6f87af534f67904b96c0efcd7f421896..21211c60ca988992034bfc330977e846c3fc7010 100644 (file)
@@ -106,6 +106,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta = NULL;
        const u8 *ra = NULL;
        bool qos = false;
+       struct mac80211_qos_map *qos_map;
 
        if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
                skb->priority = 0; /* required for correct WPA/11i MIC */
@@ -155,7 +156,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
 
        /* use the data classifier to determine what 802.1d tag the
         * data frame has */
-       skb->priority = cfg80211_classify8021d(skb);
+       rcu_read_lock();
+       qos_map = rcu_dereference(sdata->qos_map);
+       skb->priority = cfg80211_classify8021d(skb, qos_map ?
+                                              &qos_map->qos_map : NULL);
+       rcu_read_unlock();
 
        return ieee80211_downgrade_queue(sdata, skb);
 }
index e24bcf9772968d9e5a8dc59bbc8597dc2dfca1e8..372d8a222b9184e2881d108a087cf9ebaad768e6 100644 (file)
@@ -444,8 +444,8 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb)
        case IEEE802154_FC_TYPE_DATA:
                return mac802154_process_data(sdata->dev, skb);
        default:
-               pr_warning("ieee802154: bad frame received (type = %d)\n",
-                          mac_cb_type(skb));
+               pr_warn("ieee802154: bad frame received (type = %d)\n",
+                       mac_cb_type(skb));
                kfree_skb(skb);
                return NET_RX_DROP;
        }
index c3398cd99b94ed4c68da3927c1612da815f1a06d..afe50c0f526f3398e8dbf689d5905a9445448804 100644 (file)
@@ -414,47 +414,112 @@ config NETFILTER_SYNPROXY
 endif # NF_CONNTRACK
 
 config NF_TABLES
-       depends on NETFILTER_NETLINK
+       select NETFILTER_NETLINK
        tristate "Netfilter nf_tables support"
+       help
+         nftables is the new packet classification framework that intends to
+         replace the existing {ip,ip6,arp,eb}_tables infrastructure. It
+         provides a pseudo-state machine with an extensible instruction-set
+         (also known as expressions) that the userspace 'nft' utility
+         (http://www.netfilter.org/projects/nftables) uses to build the
+         rule-set. It also comes with the generic set infrastructure that
+         allows you to construct mappings between matchings and actions
+         for performance lookups.
+
+         To compile it as a module, choose M here.
+
+config NF_TABLES_INET
+       depends on NF_TABLES
+       select NF_TABLES_IPV4
+       select NF_TABLES_IPV6
+       tristate "Netfilter nf_tables mixed IPv4/IPv6 tables support"
+       help
+         This option enables support for a mixed IPv4/IPv6 "inet" table.
 
 config NFT_EXTHDR
        depends on NF_TABLES
        tristate "Netfilter nf_tables IPv6 exthdr module"
+       help
+         This option adds the "exthdr" expression that you can use to match
+         IPv6 extension headers.
 
 config NFT_META
        depends on NF_TABLES
        tristate "Netfilter nf_tables meta module"
+       help
+         This option adds the "meta" expression that you can use to match and
+         to set packet metainformation such as the packet mark.
 
 config NFT_CT
        depends on NF_TABLES
        depends on NF_CONNTRACK
        tristate "Netfilter nf_tables conntrack module"
+       help
+         This option adds the "meta" expression that you can use to match
+         connection tracking information such as the flow state.
 
 config NFT_RBTREE
        depends on NF_TABLES
        tristate "Netfilter nf_tables rbtree set module"
+       help
+         This option adds the "rbtree" set type (Red Black tree) that is used
+         to build interval-based sets.
 
 config NFT_HASH
        depends on NF_TABLES
        tristate "Netfilter nf_tables hash set module"
+       help
+         This option adds the "hash" set type that is used to build one-way
+         mappings between matchings and actions.
 
 config NFT_COUNTER
        depends on NF_TABLES
        tristate "Netfilter nf_tables counter module"
+       help
+         This option adds the "counter" expression that you can use to
+         include packet and byte counters in a rule.
 
 config NFT_LOG
        depends on NF_TABLES
        tristate "Netfilter nf_tables log module"
+       help
+         This option adds the "log" expression that you can use to log
+         packets matching some criteria.
 
 config NFT_LIMIT
        depends on NF_TABLES
        tristate "Netfilter nf_tables limit module"
+       help
+         This option adds the "limit" expression that you can use to
+         ratelimit rule matchings.
 
 config NFT_NAT
        depends on NF_TABLES
        depends on NF_CONNTRACK
        depends on NF_NAT
        tristate "Netfilter nf_tables nat module"
+       help
+         This option adds the "nat" expression that you can use to perform
+         typical Network Address Translation (NAT) packet transformations.
+
+config NFT_QUEUE
+       depends on NF_TABLES
+       depends on NETFILTER_XTABLES
+       depends on NETFILTER_NETLINK_QUEUE
+       tristate "Netfilter nf_tables queue module"
+       help
+         This is required if you intend to use the userspace queueing
+         infrastructure (also known as NFQUEUE) from nftables.
+
+config NFT_REJECT
+       depends on NF_TABLES
+       depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6
+       default m if NETFILTER_ADVANCED=n
+       tristate "Netfilter nf_tables reject support"
+       help
+         This option adds the "reject" expression that you can use to
+         explicitly deny and notify via TCP reset/ICMP informational errors
+         unallowed traffic.
 
 config NFT_COMPAT
        depends on NF_TABLES
@@ -858,6 +923,16 @@ config NETFILTER_XT_MATCH_BPF
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_CGROUP
+       tristate '"control group" match support'
+       depends on NETFILTER_ADVANCED
+       depends on CGROUPS
+       select CGROUP_NET_CLASSID
+       ---help---
+       Socket/process control group matching allows you to match locally
+       generated packets based on which net_cls control group processes
+       belong to.
+
 config NETFILTER_XT_MATCH_CLUSTER
        tristate '"cluster" match support'
        depends on NF_CONNTRACK
@@ -1035,6 +1110,15 @@ config NETFILTER_XT_MATCH_HL
        in the IPv6 header, or the time-to-live field in the IPv4
        header of the packet.
 
+config NETFILTER_XT_MATCH_IPCOMP
+       tristate '"ipcomp" match support'
+       depends on NETFILTER_ADVANCED
+       help
+         This match extension allows you to match a range of CPIs(16 bits)
+         inside IPComp header of IPSec packets.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_IPRANGE
        tristate '"iprange" address range match support'
        depends on NETFILTER_ADVANCED
@@ -1055,6 +1139,16 @@ config NETFILTER_XT_MATCH_IPVS
 
          If unsure, say N.
 
+config NETFILTER_XT_MATCH_L2TP
+       tristate '"l2tp" match support'
+       depends on NETFILTER_ADVANCED
+       default L2TP
+       ---help---
+       This option adds an "L2TP" match, which allows you to match against
+       L2TP protocol header fields.
+
+       To compile it as a module, choose M here. If unsure, say N.
+
 config NETFILTER_XT_MATCH_LENGTH
        tristate '"length" match support'
        depends on NETFILTER_ADVANCED
index 394483b2c193c53fb08dd98591969db0fa995fa8..ee9c4de5f8eded2b7e545eea47dfbd1f42edfafc 100644 (file)
@@ -70,13 +70,15 @@ nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o
 nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o
 
 obj-$(CONFIG_NF_TABLES)                += nf_tables.o
+obj-$(CONFIG_NF_TABLES_INET)   += nf_tables_inet.o
 obj-$(CONFIG_NFT_COMPAT)       += nft_compat.o
 obj-$(CONFIG_NFT_EXTHDR)       += nft_exthdr.o
 obj-$(CONFIG_NFT_META)         += nft_meta.o
 obj-$(CONFIG_NFT_CT)           += nft_ct.o
 obj-$(CONFIG_NFT_LIMIT)                += nft_limit.o
 obj-$(CONFIG_NFT_NAT)          += nft_nat.o
-#nf_tables-objs                        += nft_meta_target.o
+obj-$(CONFIG_NFT_QUEUE)                += nft_queue.o
+obj-$(CONFIG_NFT_REJECT)       += nft_reject.o
 obj-$(CONFIG_NFT_RBTREE)       += nft_rbtree.o
 obj-$(CONFIG_NFT_HASH)         += nft_hash.o
 obj-$(CONFIG_NFT_COUNTER)      += nft_counter.o
@@ -133,8 +135,10 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_IPCOMP) += xt_ipcomp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_IPVS) += xt_ipvs.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_L2TP) += xt_l2tp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
@@ -142,6 +146,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_NFACCT) += xt_nfacct.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_CGROUP) += xt_cgroup.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
index bac7e01df67fae97ea041f908a8dc316d8798459..de770ec39e5112e4cbf5b4b90629144bad1d957b 100644 (file)
@@ -624,34 +624,6 @@ EXPORT_SYMBOL_GPL(ip_set_name_byindex);
  * call nfnl_lock for us.
  */
 
-/*
- * Find set by name, reference it once. The reference makes sure the
- * thing pointed to, does not go away under our feet.
- *
- * The nfnl mutex is used in the function.
- */
-ip_set_id_t
-ip_set_nfnl_get(struct net *net, const char *name)
-{
-       ip_set_id_t i, index = IPSET_INVALID_ID;
-       struct ip_set *s;
-       struct ip_set_net *inst = ip_set_pernet(net);
-
-       nfnl_lock(NFNL_SUBSYS_IPSET);
-       for (i = 0; i < inst->ip_set_max; i++) {
-               s = nfnl_set(inst, i);
-               if (s != NULL && STREQ(s->name, name)) {
-                       __ip_set_get(s);
-                       index = i;
-                       break;
-               }
-       }
-       nfnl_unlock(NFNL_SUBSYS_IPSET);
-
-       return index;
-}
-EXPORT_SYMBOL_GPL(ip_set_nfnl_get);
-
 /*
  * Find set by index, reference it once. The reference makes sure the
  * thing pointed to, does not go away under our feet.
index d5f41514f5778d23293f6b9e36fe1bd9b83276e0..5882bbfd198c24b9e72d1d6ddc05f21ad38f53bc 100644 (file)
@@ -62,6 +62,7 @@
 #include <net/ip_vs.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_seqadj.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 
@@ -96,6 +97,11 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
        if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
                return;
 
+       /* Applications may adjust TCP seqs */
+       if (cp->app && nf_ct_protonum(ct) == IPPROTO_TCP &&
+           !nfct_seqadj(ct) && !nfct_seqadj_ext_add(ct))
+               return;
+
        /*
         * The connection is not yet in the hashtable, so we update it.
         * CIP->VIP will remain the same, so leave the tuple in
index f63c2388f38d80f470d2ef0e5b38a7a20741696f..db801263ee9fa81a832f4656071198cdc16110e7 100644 (file)
@@ -1637,7 +1637,10 @@ static int sync_thread_master(void *data)
                        continue;
                }
                while (ip_vs_send_sync_msg(tinfo->sock, sb->mesg) < 0) {
-                       int ret = __wait_event_interruptible(*sk_sleep(sk),
+                       /* (Ab)use interruptible sleep to avoid increasing
+                        * the load avg.
+                        */
+                       __wait_event_interruptible(*sk_sleep(sk),
                                                   sock_writeable(sk) ||
                                                   kthread_should_stop());
                        if (unlikely(kthread_should_stop()))
index 43549eb7a7bec4312a1bbf768de2c125a79a526b..8824ed0ccc9cd544e4799484ea7158f1f8db9c67 100644 (file)
@@ -60,12 +60,6 @@ int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
                                      const struct nlattr *attr) __read_mostly;
 EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook);
 
-int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
-                             struct nf_conn *ct,
-                             enum ip_conntrack_info ctinfo,
-                             unsigned int protoff);
-EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook);
-
 DEFINE_SPINLOCK(nf_conntrack_lock);
 EXPORT_SYMBOL_GPL(nf_conntrack_lock);
 
@@ -361,15 +355,6 @@ begin:
        return NULL;
 }
 
-struct nf_conntrack_tuple_hash *
-__nf_conntrack_find(struct net *net, u16 zone,
-                   const struct nf_conntrack_tuple *tuple)
-{
-       return ____nf_conntrack_find(net, zone, tuple,
-                                    hash_conntrack_raw(tuple, zone));
-}
-EXPORT_SYMBOL_GPL(__nf_conntrack_find);
-
 /* Find a connection corresponding to a tuple. */
 static struct nf_conntrack_tuple_hash *
 __nf_conntrack_find_get(struct net *net, u16 zone,
index 08870b859046fb17f40125b7e1f8faeb42d93061..bb322d0beb484f3c66a334a5e0b24651f2a1ffca 100644 (file)
@@ -2118,8 +2118,16 @@ ctnetlink_nfqueue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
                        return err;
        }
 #if defined(CONFIG_NF_CONNTRACK_MARK)
-       if (cda[CTA_MARK])
-               ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
+       if (cda[CTA_MARK]) {
+               u32 mask = 0, mark, newmark;
+               if (cda[CTA_MARK_MASK])
+                       mask = ~ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
+
+               mark = ntohl(nla_get_be32(cda[CTA_MARK]));
+               newmark = (ct->mark & mask) ^ mark;
+               if (newmark != ct->mark)
+                       ct->mark = newmark;
+       }
 #endif
        return 0;
 }
index ce3004156eeb923171c2ef08eae6e3447ce7906e..b65d5864b6d948a0f902bc95af1b3b2de149c7f9 100644 (file)
@@ -92,12 +92,6 @@ nf_ct_l3proto_find_get(u_int16_t l3proto)
 }
 EXPORT_SYMBOL_GPL(nf_ct_l3proto_find_get);
 
-void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
-{
-       module_put(p->me);
-}
-EXPORT_SYMBOL_GPL(nf_ct_l3proto_put);
-
 int
 nf_ct_l3proto_try_module_get(unsigned short l3proto)
 {
index a99b6c3427b0ce3e06458cb1fd37bc3bfac98723..cb372f96f10dc3c2f60064e49b86d35c76c6cd1b 100644 (file)
@@ -428,7 +428,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
        const char *msg;
        u_int8_t state;
 
-       dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
+       dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
        BUG_ON(dh == NULL);
 
        state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
@@ -457,7 +457,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
 out_invalid:
        if (LOG_INVALID(net, IPPROTO_DCCP))
                nf_log_packet(net, nf_ct_l3num(ct), 0, skb, NULL, NULL,
-                             NULL, msg);
+                             NULL, "%s", msg);
        return false;
 }
 
@@ -486,7 +486,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
        u_int8_t type, old_state, new_state;
        enum ct_dccp_roles role;
 
-       dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
+       dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
        BUG_ON(dh == NULL);
        type = dh->dccph_type;
 
@@ -577,7 +577,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl,
        unsigned int cscov;
        const char *msg;
 
-       dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
+       dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
        if (dh == NULL) {
                msg = "nf_ct_dccp: short packet ";
                goto out_invalid;
@@ -614,7 +614,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl,
 
 out_invalid:
        if (LOG_INVALID(net, IPPROTO_DCCP))
-               nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, msg);
+               nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", msg);
        return -NF_ACCEPT;
 }
 
index 17c1bcb182c6b58a782744e23bfe671de160bf92..b2d38da6782201862eb29321c921dd254e8408f3 100644 (file)
@@ -36,6 +36,11 @@ int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
        if (off == 0)
                return 0;
 
+       if (unlikely(!seqadj)) {
+               WARN(1, "Wrong seqadj usage, missing nfct_seqadj_ext_add()\n");
+               return 0;
+       }
+
        set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 
        spin_lock_bh(&ct->lock);
index 902fb0a6b38ad9baac15c3fc3f17a3e695510db8..7a394df0deb7686fa7fe4da162ff77d3c03435c5 100644 (file)
@@ -97,7 +97,6 @@ int nf_conntrack_tstamp_pernet_init(struct net *net)
 void nf_conntrack_tstamp_pernet_fini(struct net *net)
 {
        nf_conntrack_tstamp_fini_sysctl(net);
-       nf_ct_extend_unregister(&tstamp_extend);
 }
 
 int nf_conntrack_tstamp_init(void)
index 63a81540221169fcc6115e8c36cc84500beb809d..d3f5cd6dd962b195ea85775cd0432cf204e697b2 100644 (file)
@@ -315,7 +315,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
         * manips not an issue.
         */
        if (maniptype == NF_NAT_MANIP_SRC &&
-           !(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) {
+           !(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL)) {
                /* try the original tuple first */
                if (in_range(l3proto, l4proto, orig_tuple, range)) {
                        if (!nf_nat_used_tuple(orig_tuple, ct)) {
@@ -339,7 +339,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
         */
 
        /* Only bother mapping if it's not already in range and unique */
-       if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) {
+       if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL)) {
                if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
                        if (l4proto->in_range(tuple, maniptype,
                                              &range->min_proto,
index 9baaf734c1421e4e1334a5aed777af7d8ee9d9d1..83a72a235cae7c6b9ee3c97dcabb8629fe6e7008 100644 (file)
@@ -74,22 +74,24 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
                range_size = ntohs(range->max_proto.all) - min + 1;
        }
 
-       if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+       if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) {
                off = l3proto->secure_port(tuple, maniptype == NF_NAT_MANIP_SRC
                                                  ? tuple->dst.u.all
                                                  : tuple->src.u.all);
-       else
+       } else if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
+               off = prandom_u32();
+       } else {
                off = *rover;
+       }
 
        for (i = 0; ; ++off) {
                *portptr = htons(min + off % range_size);
                if (++i != range_size && nf_nat_used_tuple(tuple, ct))
                        continue;
-               if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM))
+               if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL))
                        *rover = off;
                return;
        }
-       return;
 }
 EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple);
 
index f93b7d06f4be9525ad4ab4314a106b01e85749ba..36add31e08e7345d23894004622f59fc618bb058 100644 (file)
@@ -124,37 +124,43 @@ static inline u64 nf_tables_alloc_handle(struct nft_table *table)
        return ++table->hgenerator;
 }
 
-static struct nf_chain_type *chain_type[AF_MAX][NFT_CHAIN_T_MAX];
+static const struct nf_chain_type *chain_type[AF_MAX][NFT_CHAIN_T_MAX];
 
-static int __nf_tables_chain_type_lookup(int family, const struct nlattr *nla)
+static const struct nf_chain_type *
+__nf_tables_chain_type_lookup(int family, const struct nlattr *nla)
 {
        int i;
 
-       for (i=0; i<NFT_CHAIN_T_MAX; i++) {
+       for (i = 0; i < NFT_CHAIN_T_MAX; i++) {
                if (chain_type[family][i] != NULL &&
                    !nla_strcmp(nla, chain_type[family][i]->name))
-                       return i;
+                       return chain_type[family][i];
        }
-       return -1;
+       return NULL;
 }
 
-static int nf_tables_chain_type_lookup(const struct nft_af_info *afi,
-                                      const struct nlattr *nla,
-                                      bool autoload)
+static const struct nf_chain_type *
+nf_tables_chain_type_lookup(const struct nft_af_info *afi,
+                           const struct nlattr *nla,
+                           bool autoload)
 {
-       int type;
+       const struct nf_chain_type *type;
 
        type = __nf_tables_chain_type_lookup(afi->family, nla);
+       if (type != NULL)
+               return type;
 #ifdef CONFIG_MODULES
-       if (type < 0 && autoload) {
+       if (autoload) {
                nfnl_unlock(NFNL_SUBSYS_NFTABLES);
                request_module("nft-chain-%u-%*.s", afi->family,
                               nla_len(nla)-1, (const char *)nla_data(nla));
                nfnl_lock(NFNL_SUBSYS_NFTABLES);
                type = __nf_tables_chain_type_lookup(afi->family, nla);
+               if (type != NULL)
+                       return ERR_PTR(-EAGAIN);
        }
 #endif
-       return type;
+       return ERR_PTR(-ENOENT);
 }
 
 static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = {
@@ -180,7 +186,8 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, u32 portid, u32 seq,
        nfmsg->res_id           = 0;
 
        if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) ||
-           nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)))
+           nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) ||
+           nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)))
                goto nla_put_failure;
 
        return nlmsg_end(skb, nlh);
@@ -306,13 +313,17 @@ err:
        return err;
 }
 
-static int nf_tables_table_enable(struct nft_table *table)
+static int nf_tables_table_enable(const struct nft_af_info *afi,
+                                 struct nft_table *table)
 {
        struct nft_chain *chain;
        int err, i = 0;
 
        list_for_each_entry(chain, &table->chains, list) {
-               err = nf_register_hook(&nft_base_chain(chain)->ops);
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
+               err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops);
                if (err < 0)
                        goto err;
 
@@ -321,20 +332,27 @@ static int nf_tables_table_enable(struct nft_table *table)
        return 0;
 err:
        list_for_each_entry(chain, &table->chains, list) {
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
                if (i-- <= 0)
                        break;
 
-               nf_unregister_hook(&nft_base_chain(chain)->ops);
+               nf_unregister_hooks(nft_base_chain(chain)->ops, afi->nops);
        }
        return err;
 }
 
-static int nf_tables_table_disable(struct nft_table *table)
+static int nf_tables_table_disable(const struct nft_af_info *afi,
+                                  struct nft_table *table)
 {
        struct nft_chain *chain;
 
-       list_for_each_entry(chain, &table->chains, list)
-               nf_unregister_hook(&nft_base_chain(chain)->ops);
+       list_for_each_entry(chain, &table->chains, list) {
+               if (chain->flags & NFT_BASE_CHAIN)
+                       nf_unregister_hooks(nft_base_chain(chain)->ops,
+                                           afi->nops);
+       }
 
        return 0;
 }
@@ -348,7 +366,7 @@ static int nf_tables_updtable(struct sock *nlsk, struct sk_buff *skb,
        int family = nfmsg->nfgen_family, ret = 0;
 
        if (nla[NFTA_TABLE_FLAGS]) {
-               __be32 flags;
+               u32 flags;
 
                flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS]));
                if (flags & ~NFT_TABLE_F_DORMANT)
@@ -356,12 +374,12 @@ static int nf_tables_updtable(struct sock *nlsk, struct sk_buff *skb,
 
                if ((flags & NFT_TABLE_F_DORMANT) &&
                    !(table->flags & NFT_TABLE_F_DORMANT)) {
-                       ret = nf_tables_table_disable(table);
+                       ret = nf_tables_table_disable(afi, table);
                        if (ret >= 0)
                                table->flags |= NFT_TABLE_F_DORMANT;
                } else if (!(flags & NFT_TABLE_F_DORMANT) &&
                           table->flags & NFT_TABLE_F_DORMANT) {
-                       ret = nf_tables_table_enable(table);
+                       ret = nf_tables_table_enable(afi, table);
                        if (ret >= 0)
                                table->flags &= ~NFT_TABLE_F_DORMANT;
                }
@@ -384,6 +402,7 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
        struct nft_table *table;
        struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
+       u32 flags = 0;
 
        afi = nf_tables_afinfo_lookup(net, family, true);
        if (IS_ERR(afi))
@@ -405,25 +424,25 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
                return nf_tables_updtable(nlsk, skb, nlh, nla, afi, table);
        }
 
+       if (nla[NFTA_TABLE_FLAGS]) {
+               flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS]));
+               if (flags & ~NFT_TABLE_F_DORMANT)
+                       return -EINVAL;
+       }
+
+       if (!try_module_get(afi->owner))
+               return -EAFNOSUPPORT;
+
        table = kzalloc(sizeof(*table) + nla_len(name), GFP_KERNEL);
-       if (table == NULL)
+       if (table == NULL) {
+               module_put(afi->owner);
                return -ENOMEM;
+       }
 
        nla_strlcpy(table->name, name, nla_len(name));
        INIT_LIST_HEAD(&table->chains);
        INIT_LIST_HEAD(&table->sets);
-
-       if (nla[NFTA_TABLE_FLAGS]) {
-               __be32 flags;
-
-               flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS]));
-               if (flags & ~NFT_TABLE_F_DORMANT) {
-                       kfree(table);
-                       return -EINVAL;
-               }
-
-               table->flags |= flags;
-       }
+       table->flags = flags;
 
        list_add_tail(&table->list, &afi->tables);
        nf_tables_table_notify(skb, nlh, table, NFT_MSG_NEWTABLE, family);
@@ -448,16 +467,17 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
        if (IS_ERR(table))
                return PTR_ERR(table);
 
-       if (table->use)
+       if (!list_empty(&table->chains) || !list_empty(&table->sets))
                return -EBUSY;
 
        list_del(&table->list);
        nf_tables_table_notify(skb, nlh, table, NFT_MSG_DELTABLE, family);
        kfree(table);
+       module_put(afi->owner);
        return 0;
 }
 
-int nft_register_chain_type(struct nf_chain_type *ctype)
+int nft_register_chain_type(const struct nf_chain_type *ctype)
 {
        int err = 0;
 
@@ -466,10 +486,6 @@ int nft_register_chain_type(struct nf_chain_type *ctype)
                err = -EBUSY;
                goto out;
        }
-
-       if (!try_module_get(ctype->me))
-               goto out;
-
        chain_type[ctype->family][ctype->type] = ctype;
 out:
        nfnl_unlock(NFNL_SUBSYS_NFTABLES);
@@ -477,11 +493,10 @@ out:
 }
 EXPORT_SYMBOL_GPL(nft_register_chain_type);
 
-void nft_unregister_chain_type(struct nf_chain_type *ctype)
+void nft_unregister_chain_type(const struct nf_chain_type *ctype)
 {
        nfnl_lock(NFNL_SUBSYS_NFTABLES);
        chain_type[ctype->family][ctype->type] = NULL;
-       module_put(ctype->me);
        nfnl_unlock(NFNL_SUBSYS_NFTABLES);
 }
 EXPORT_SYMBOL_GPL(nft_unregister_chain_type);
@@ -589,7 +604,7 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, u32 portid, u32 seq,
 
        if (chain->flags & NFT_BASE_CHAIN) {
                const struct nft_base_chain *basechain = nft_base_chain(chain);
-               const struct nf_hook_ops *ops = &basechain->ops;
+               const struct nf_hook_ops *ops = &basechain->ops[0];
                struct nlattr *nest;
 
                nest = nla_nest_start(skb, NFTA_CHAIN_HOOK);
@@ -605,9 +620,8 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, u32 portid, u32 seq,
                                 htonl(basechain->policy)))
                        goto nla_put_failure;
 
-               if (nla_put_string(skb, NFTA_CHAIN_TYPE,
-                       chain_type[ops->pf][nft_base_chain(chain)->type]->name))
-                               goto nla_put_failure;
+               if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name))
+                       goto nla_put_failure;
 
                if (nft_dump_stats(skb, nft_base_chain(chain)->stats))
                        goto nla_put_failure;
@@ -748,22 +762,6 @@ err:
        return err;
 }
 
-static int
-nf_tables_chain_policy(struct nft_base_chain *chain, const struct nlattr *attr)
-{
-       switch (ntohl(nla_get_be32(attr))) {
-       case NF_DROP:
-               chain->policy = NF_DROP;
-               break;
-       case NF_ACCEPT:
-               chain->policy = NF_ACCEPT;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
 static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = {
        [NFTA_COUNTER_PACKETS]  = { .type = NLA_U64 },
        [NFTA_COUNTER_BYTES]    = { .type = NLA_U64 },
@@ -822,7 +820,9 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
        struct nlattr *ha[NFTA_HOOK_MAX + 1];
        struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
+       u8 policy = NF_ACCEPT;
        u64 handle = 0;
+       unsigned int i;
        int err;
        bool create;
 
@@ -836,9 +836,6 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
        if (IS_ERR(table))
                return PTR_ERR(table);
 
-       if (table->use == UINT_MAX)
-               return -EOVERFLOW;
-
        chain = NULL;
        name = nla[NFTA_CHAIN_NAME];
 
@@ -856,6 +853,22 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
                }
        }
 
+       if (nla[NFTA_CHAIN_POLICY]) {
+               if ((chain != NULL &&
+                   !(chain->flags & NFT_BASE_CHAIN)) ||
+                   nla[NFTA_CHAIN_HOOK] == NULL)
+                       return -EOPNOTSUPP;
+
+               policy = nla_get_be32(nla[NFTA_CHAIN_POLICY]);
+               switch (policy) {
+               case NF_DROP:
+               case NF_ACCEPT:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
        if (chain != NULL) {
                if (nlh->nlmsg_flags & NLM_F_EXCL)
                        return -EEXIST;
@@ -866,16 +879,6 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
                    !IS_ERR(nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME])))
                        return -EEXIST;
 
-               if (nla[NFTA_CHAIN_POLICY]) {
-                       if (!(chain->flags & NFT_BASE_CHAIN))
-                               return -EOPNOTSUPP;
-
-                       err = nf_tables_chain_policy(nft_base_chain(chain),
-                                                    nla[NFTA_CHAIN_POLICY]);
-                       if (err < 0)
-                               return err;
-               }
-
                if (nla[NFTA_CHAIN_COUNTERS]) {
                        if (!(chain->flags & NFT_BASE_CHAIN))
                                return -EOPNOTSUPP;
@@ -886,24 +889,31 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
                                return err;
                }
 
+               if (nla[NFTA_CHAIN_POLICY])
+                       nft_base_chain(chain)->policy = policy;
+
                if (nla[NFTA_CHAIN_HANDLE] && name)
                        nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN);
 
                goto notify;
        }
 
+       if (table->use == UINT_MAX)
+               return -EOVERFLOW;
+
        if (nla[NFTA_CHAIN_HOOK]) {
+               const struct nf_chain_type *type;
                struct nf_hook_ops *ops;
                nf_hookfn *hookfn;
-               u32 hooknum;
-               int type = NFT_CHAIN_T_DEFAULT;
+               u32 hooknum, priority;
 
+               type = chain_type[family][NFT_CHAIN_T_DEFAULT];
                if (nla[NFTA_CHAIN_TYPE]) {
                        type = nf_tables_chain_type_lookup(afi,
                                                           nla[NFTA_CHAIN_TYPE],
                                                           create);
-                       if (type < 0)
-                               return -ENOENT;
+                       if (IS_ERR(type))
+                               return PTR_ERR(type);
                }
 
                err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK],
@@ -917,46 +927,23 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
                hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
                if (hooknum >= afi->nhooks)
                        return -EINVAL;
+               priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
 
-               hookfn = chain_type[family][type]->fn[hooknum];
-               if (hookfn == NULL)
+               if (!(type->hook_mask & (1 << hooknum)))
                        return -EOPNOTSUPP;
+               if (!try_module_get(type->owner))
+                       return -ENOENT;
+               hookfn = type->hooks[hooknum];
 
                basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
                if (basechain == NULL)
                        return -ENOMEM;
 
-               basechain->type = type;
-               chain = &basechain->chain;
-
-               ops = &basechain->ops;
-               ops->pf         = family;
-               ops->owner      = afi->owner;
-               ops->hooknum    = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
-               ops->priority   = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
-               ops->priv       = chain;
-               ops->hook       = hookfn;
-               if (afi->hooks[ops->hooknum])
-                       ops->hook = afi->hooks[ops->hooknum];
-
-               chain->flags |= NFT_BASE_CHAIN;
-
-               if (nla[NFTA_CHAIN_POLICY]) {
-                       err = nf_tables_chain_policy(basechain,
-                                                    nla[NFTA_CHAIN_POLICY]);
-                       if (err < 0) {
-                               free_percpu(basechain->stats);
-                               kfree(basechain);
-                               return err;
-                       }
-               } else
-                       basechain->policy = NF_ACCEPT;
-
                if (nla[NFTA_CHAIN_COUNTERS]) {
                        err = nf_tables_counters(basechain,
                                                 nla[NFTA_CHAIN_COUNTERS]);
                        if (err < 0) {
-                               free_percpu(basechain->stats);
+                               module_put(type->owner);
                                kfree(basechain);
                                return err;
                        }
@@ -964,12 +951,33 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
                        struct nft_stats __percpu *newstats;
 
                        newstats = alloc_percpu(struct nft_stats);
-                       if (newstats == NULL)
+                       if (newstats == NULL) {
+                               module_put(type->owner);
+                               kfree(basechain);
                                return -ENOMEM;
+                       }
+                       rcu_assign_pointer(basechain->stats, newstats);
+               }
+
+               basechain->type = type;
+               chain = &basechain->chain;
 
-                       rcu_assign_pointer(nft_base_chain(chain)->stats,
-                                          newstats);
+               for (i = 0; i < afi->nops; i++) {
+                       ops = &basechain->ops[i];
+                       ops->pf         = family;
+                       ops->owner      = afi->owner;
+                       ops->hooknum    = hooknum;
+                       ops->priority   = priority;
+                       ops->priv       = chain;
+                       ops->hook       = afi->hooks[ops->hooknum];
+                       if (hookfn)
+                               ops->hook = hookfn;
+                       if (afi->hook_ops_init)
+                               afi->hook_ops_init(ops, i);
                }
+
+               chain->flags |= NFT_BASE_CHAIN;
+               basechain->policy = policy;
        } else {
                chain = kzalloc(sizeof(*chain), GFP_KERNEL);
                if (chain == NULL)
@@ -984,8 +992,9 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
 
        if (!(table->flags & NFT_TABLE_F_DORMANT) &&
            chain->flags & NFT_BASE_CHAIN) {
-               err = nf_register_hook(&nft_base_chain(chain)->ops);
+               err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops);
                if (err < 0) {
+                       module_put(basechain->type->owner);
                        free_percpu(basechain->stats);
                        kfree(basechain);
                        return err;
@@ -1006,6 +1015,7 @@ static void nf_tables_rcu_chain_destroy(struct rcu_head *head)
        BUG_ON(chain->use > 0);
 
        if (chain->flags & NFT_BASE_CHAIN) {
+               module_put(nft_base_chain(chain)->type->owner);
                free_percpu(nft_base_chain(chain)->stats);
                kfree(nft_base_chain(chain));
        } else
@@ -1043,7 +1053,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
 
        if (!(table->flags & NFT_TABLE_F_DORMANT) &&
            chain->flags & NFT_BASE_CHAIN)
-               nf_unregister_hook(&nft_base_chain(chain)->ops);
+               nf_unregister_hooks(nft_base_chain(chain)->ops, afi->nops);
 
        nf_tables_chain_notify(skb, nlh, table, chain, NFT_MSG_DELCHAIN,
                               family);
@@ -1923,12 +1933,14 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
 {
        struct net *net = sock_net(skb->sk);
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
-       const struct nft_af_info *afi;
+       const struct nft_af_info *afi = NULL;
        const struct nft_table *table = NULL;
 
-       afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
-       if (IS_ERR(afi))
-               return PTR_ERR(afi);
+       if (nfmsg->nfgen_family != NFPROTO_UNSPEC) {
+               afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
+               if (IS_ERR(afi))
+                       return PTR_ERR(afi);
+       }
 
        if (nla[NFTA_SET_TABLE] != NULL) {
                table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
@@ -1973,11 +1985,14 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
                        return -ENOMEM;
 
                list_for_each_entry(i, &ctx->table->sets, list) {
-                       if (!sscanf(i->name, name, &n))
+                       int tmp;
+
+                       if (!sscanf(i->name, name, &tmp))
                                continue;
-                       if (n < 0 || n > BITS_PER_LONG * PAGE_SIZE)
+                       if (tmp < 0 || tmp > BITS_PER_LONG * PAGE_SIZE)
                                continue;
-                       set_bit(n, inuse);
+
+                       set_bit(tmp, inuse);
                }
 
                n = find_first_zero_bit(inuse, BITS_PER_LONG * PAGE_SIZE);
@@ -2094,21 +2109,25 @@ done:
        return skb->len;
 }
 
-static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
-                                  struct netlink_callback *cb)
+static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
+                                     struct netlink_callback *cb)
 {
        const struct nft_set *set;
-       unsigned int idx = 0, s_idx = cb->args[0];
+       unsigned int idx, s_idx = cb->args[0];
        struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
 
        if (cb->args[1])
                return skb->len;
 
        list_for_each_entry(table, &ctx->afi->tables, list) {
-               if (cur_table && cur_table != table)
-                       continue;
+               if (cur_table) {
+                       if (cur_table != table)
+                               continue;
 
+                       cur_table = NULL;
+               }
                ctx->table = table;
+               idx = 0;
                list_for_each_entry(set, &ctx->table->sets, list) {
                        if (idx < s_idx)
                                goto cont;
@@ -2127,6 +2146,61 @@ done:
        return skb->len;
 }
 
+static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
+                                  struct netlink_callback *cb)
+{
+       const struct nft_set *set;
+       unsigned int idx, s_idx = cb->args[0];
+       const struct nft_af_info *afi;
+       struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
+       struct net *net = sock_net(skb->sk);
+       int cur_family = cb->args[3];
+
+       if (cb->args[1])
+               return skb->len;
+
+       list_for_each_entry(afi, &net->nft.af_info, list) {
+               if (cur_family) {
+                       if (afi->family != cur_family)
+                               continue;
+
+                       cur_family = 0;
+               }
+
+               list_for_each_entry(table, &afi->tables, list) {
+                       if (cur_table) {
+                               if (cur_table != table)
+                                       continue;
+
+                               cur_table = NULL;
+                       }
+
+                       ctx->table = table;
+                       ctx->afi = afi;
+                       idx = 0;
+                       list_for_each_entry(set, &ctx->table->sets, list) {
+                               if (idx < s_idx)
+                                       goto cont;
+                               if (nf_tables_fill_set(skb, ctx, set,
+                                                      NFT_MSG_NEWSET,
+                                                      NLM_F_MULTI) < 0) {
+                                       cb->args[0] = idx;
+                                       cb->args[2] = (unsigned long) table;
+                                       cb->args[3] = afi->family;
+                                       goto done;
+                               }
+cont:
+                               idx++;
+                       }
+                       if (s_idx)
+                               s_idx = 0;
+               }
+       }
+       cb->args[1] = 1;
+done:
+       return skb->len;
+}
+
 static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
@@ -2143,9 +2217,12 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
        if (err < 0)
                return err;
 
-       if (ctx.table == NULL)
-               ret = nf_tables_dump_sets_all(&ctx, skb, cb);
-       else
+       if (ctx.table == NULL) {
+               if (ctx.afi == NULL)
+                       ret = nf_tables_dump_sets_all(&ctx, skb, cb);
+               else
+                       ret = nf_tables_dump_sets_family(&ctx, skb, cb);
+       } else
                ret = nf_tables_dump_sets_table(&ctx, skb, cb);
 
        return ret;
@@ -2158,6 +2235,7 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
        const struct nft_set *set;
        struct nft_ctx ctx;
        struct sk_buff *skb2;
+       const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        int err;
 
        /* Verify existance before starting dump */
@@ -2172,6 +2250,10 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
                return netlink_dump_start(nlsk, skb, nlh, &c);
        }
 
+       /* Only accept unspec with dump */
+       if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
+               return -EAFNOSUPPORT;
+
        set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
        if (IS_ERR(set))
                return PTR_ERR(set);
@@ -2341,6 +2423,7 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
                            const struct nlmsghdr *nlh,
                            const struct nlattr * const nla[])
 {
+       const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        struct nft_set *set;
        struct nft_ctx ctx;
        int err;
@@ -2352,6 +2435,9 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
        if (err < 0)
                return err;
 
+       if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
+               return -EAFNOSUPPORT;
+
        set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
        if (IS_ERR(set))
                return PTR_ERR(set);
@@ -2370,7 +2456,9 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
        enum nft_registers dreg;
 
        dreg = nft_type_to_reg(set->dtype);
-       return nft_validate_data_load(ctx, dreg, &elem->data, set->dtype);
+       return nft_validate_data_load(ctx, dreg, &elem->data,
+                                     set->dtype == NFT_DATA_VERDICT ?
+                                     NFT_DATA_VERDICT : NFT_DATA_VALUE);
 }
 
 int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
@@ -2521,9 +2609,8 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
        u32 portid, seq;
        int event, err;
 
-       nfmsg = nlmsg_data(cb->nlh);
-       err = nlmsg_parse(cb->nlh, sizeof(*nfmsg), nla, NFTA_SET_ELEM_LIST_MAX,
-                         nft_set_elem_list_policy);
+       err = nlmsg_parse(cb->nlh, sizeof(struct nfgenmsg), nla,
+                         NFTA_SET_ELEM_LIST_MAX, nft_set_elem_list_policy);
        if (err < 0)
                return err;
 
index cb9e685caae19120545a7883b6883033406971ea..0d879fcb8763c043430d242d68524e0256c4411d 100644 (file)
@@ -109,14 +109,14 @@ static inline void nft_trace_packet(const struct nft_pktinfo *pkt,
 {
        struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
 
-       nf_log_packet(net, pkt->xt.family, pkt->hooknum, pkt->skb, pkt->in,
+       nf_log_packet(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in,
                      pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ",
                      chain->table->name, chain->name, comments[type],
                      rulenum);
 }
 
 unsigned int
-nft_do_chain_pktinfo(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
+nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
 {
        const struct nft_chain *chain = ops->priv;
        const struct nft_rule *rule;
@@ -164,7 +164,7 @@ next_rule:
                break;
        }
 
-       switch (data[NFT_REG_VERDICT].verdict) {
+       switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) {
        case NF_ACCEPT:
        case NF_DROP:
        case NF_QUEUE:
@@ -172,6 +172,9 @@ next_rule:
                        nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
 
                return data[NFT_REG_VERDICT].verdict;
+       }
+
+       switch (data[NFT_REG_VERDICT].verdict) {
        case NFT_JUMP:
                if (unlikely(pkt->skb->nf_trace))
                        nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
@@ -213,7 +216,7 @@ next_rule:
 
        return nft_base_chain(chain)->policy;
 }
-EXPORT_SYMBOL_GPL(nft_do_chain_pktinfo);
+EXPORT_SYMBOL_GPL(nft_do_chain);
 
 int __init nf_tables_core_module_init(void)
 {
diff --git a/net/netfilter/nf_tables_inet.c b/net/netfilter/nf_tables_inet.c
new file mode 100644 (file)
index 0000000..9dd2d21
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012-2014 Patrick McHardy <kaber@trash.net>
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_ipv4.h>
+#include <net/netfilter/nf_tables_ipv6.h>
+#include <net/ip.h>
+
+static void nft_inet_hook_ops_init(struct nf_hook_ops *ops, unsigned int n)
+{
+       struct nft_af_info *afi;
+
+       if (n == 1)
+               afi = &nft_af_ipv4;
+       else
+               afi = &nft_af_ipv6;
+
+       ops->pf = afi->family;
+       if (afi->hooks[ops->hooknum])
+               ops->hook = afi->hooks[ops->hooknum];
+}
+
+static struct nft_af_info nft_af_inet __read_mostly = {
+       .family         = NFPROTO_INET,
+       .nhooks         = NF_INET_NUMHOOKS,
+       .owner          = THIS_MODULE,
+       .nops           = 2,
+       .hook_ops_init  = nft_inet_hook_ops_init,
+};
+
+static int __net_init nf_tables_inet_init_net(struct net *net)
+{
+       net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
+       if (net->nft.inet == NULL)
+               return -ENOMEM;
+       memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet));
+
+       if (nft_register_afinfo(net, net->nft.inet) < 0)
+               goto err;
+
+       return 0;
+
+err:
+       kfree(net->nft.inet);
+       return -ENOMEM;
+}
+
+static void __net_exit nf_tables_inet_exit_net(struct net *net)
+{
+       nft_unregister_afinfo(net->nft.inet);
+       kfree(net->nft.inet);
+}
+
+static struct pernet_operations nf_tables_inet_net_ops = {
+       .init   = nf_tables_inet_init_net,
+       .exit   = nf_tables_inet_exit_net,
+};
+
+static const struct nf_chain_type filter_inet = {
+       .name           = "filter",
+       .type           = NFT_CHAIN_T_DEFAULT,
+       .family         = NFPROTO_INET,
+       .owner          = THIS_MODULE,
+       .hook_mask      = (1 << NF_INET_LOCAL_IN) |
+                         (1 << NF_INET_LOCAL_OUT) |
+                         (1 << NF_INET_FORWARD) |
+                         (1 << NF_INET_PRE_ROUTING) |
+                         (1 << NF_INET_POST_ROUTING),
+};
+
+static int __init nf_tables_inet_init(void)
+{
+       int ret;
+
+       nft_register_chain_type(&filter_inet);
+       ret = register_pernet_subsys(&nf_tables_inet_net_ops);
+       if (ret < 0)
+               nft_unregister_chain_type(&filter_inet);
+
+       return ret;
+}
+
+static void __exit nf_tables_inet_exit(void)
+{
+       unregister_pernet_subsys(&nf_tables_inet_net_ops);
+       nft_unregister_chain_type(&filter_inet);
+}
+
+module_init(nf_tables_inet_init);
+module_exit(nf_tables_inet_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_ALIAS_NFT_FAMILY(1);
index 3c4b69e5fe17348b422f390bf79ab4269043fe5d..a155d19a225edcfb4b1a550ebc898f40d51c564d 100644 (file)
@@ -1053,6 +1053,7 @@ static void __net_exit nfnl_log_net_exit(struct net *net)
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
 #endif
+       nf_log_unset(net, &nfulnl_logger);
 }
 
 static struct pernet_operations nfnl_log_net_ops = {
index 21258cf7009118c3820c7b9575b4a4bd1b331f1f..f072fe803510320f7210c31b1a08ccddea5ae5b6 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/netfilter/nfnetlink_queue.h>
 #include <linux/list.h>
 #include <net/sock.h>
+#include <net/tcp_states.h>
 #include <net/netfilter/nf_queue.h>
 #include <net/netns/generic.h>
 #include <net/netfilter/nfnetlink_queue.h>
@@ -235,51 +236,6 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
        spin_unlock_bh(&queue->lock);
 }
 
-static void
-nfqnl_zcopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
-{
-       int i, j = 0;
-       int plen = 0; /* length of skb->head fragment */
-       struct page *page;
-       unsigned int offset;
-
-       /* dont bother with small payloads */
-       if (len <= skb_tailroom(to)) {
-               skb_copy_bits(from, 0, skb_put(to, len), len);
-               return;
-       }
-
-       if (hlen) {
-               skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
-               len -= hlen;
-       } else {
-               plen = min_t(int, skb_headlen(from), len);
-               if (plen) {
-                       page = virt_to_head_page(from->head);
-                       offset = from->data - (unsigned char *)page_address(page);
-                       __skb_fill_page_desc(to, 0, page, offset, plen);
-                       get_page(page);
-                       j = 1;
-                       len -= plen;
-               }
-       }
-
-       to->truesize += len + plen;
-       to->len += len + plen;
-       to->data_len += len + plen;
-
-       for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
-               if (!len)
-                       break;
-               skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i];
-               skb_shinfo(to)->frags[j].size = min_t(int, skb_shinfo(to)->frags[j].size, len);
-               len -= skb_shinfo(to)->frags[j].size;
-               skb_frag_ref(to, j);
-               j++;
-       }
-       skb_shinfo(to)->nr_frags = j;
-}
-
 static int
 nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet,
                      bool csum_verify)
@@ -297,6 +253,31 @@ nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet,
        return flags ? nla_put_be32(nlskb, NFQA_SKB_INFO, htonl(flags)) : 0;
 }
 
+static int nfqnl_put_sk_uidgid(struct sk_buff *skb, struct sock *sk)
+{
+       const struct cred *cred;
+
+       if (sk->sk_state == TCP_TIME_WAIT)
+               return 0;
+
+       read_lock_bh(&sk->sk_callback_lock);
+       if (sk->sk_socket && sk->sk_socket->file) {
+               cred = sk->sk_socket->file->f_cred;
+               if (nla_put_be32(skb, NFQA_UID,
+                   htonl(from_kuid_munged(&init_user_ns, cred->fsuid))))
+                       goto nla_put_failure;
+               if (nla_put_be32(skb, NFQA_GID,
+                   htonl(from_kgid_munged(&init_user_ns, cred->fsgid))))
+                       goto nla_put_failure;
+       }
+       read_unlock_bh(&sk->sk_callback_lock);
+       return 0;
+
+nla_put_failure:
+       read_unlock_bh(&sk->sk_callback_lock);
+       return -1;
+}
+
 static struct sk_buff *
 nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                           struct nf_queue_entry *entry,
@@ -304,7 +285,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
 {
        size_t size;
        size_t data_len = 0, cap_len = 0;
-       int hlen = 0;
+       unsigned int hlen = 0;
        struct sk_buff *skb;
        struct nlattr *nla;
        struct nfqnl_msg_packet_hdr *pmsg;
@@ -356,14 +337,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                if (data_len > entskb->len)
                        data_len = entskb->len;
 
-               if (!entskb->head_frag ||
-                   skb_headlen(entskb) < L1_CACHE_BYTES ||
-                   skb_shinfo(entskb)->nr_frags >= MAX_SKB_FRAGS)
-                       hlen = skb_headlen(entskb);
-
-               if (skb_has_frag_list(entskb))
-                       hlen = entskb->len;
-               hlen = min_t(int, data_len, hlen);
+               hlen = skb_zerocopy_headlen(entskb);
+               hlen = min_t(unsigned int, hlen, data_len);
                size += sizeof(struct nlattr) + hlen;
                cap_len = entskb->len;
                break;
@@ -372,6 +347,11 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
        if (queue->flags & NFQA_CFG_F_CONNTRACK)
                ct = nfqnl_ct_get(entskb, &size, &ctinfo);
 
+       if (queue->flags & NFQA_CFG_F_UID_GID) {
+               size +=  (nla_total_size(sizeof(u_int32_t))     /* uid */
+                       + nla_total_size(sizeof(u_int32_t)));   /* gid */
+       }
+
        skb = nfnetlink_alloc_skb(net, size, queue->peer_portid,
                                  GFP_ATOMIC);
        if (!skb)
@@ -484,6 +464,10 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                        goto nla_put_failure;
        }
 
+       if ((queue->flags & NFQA_CFG_F_UID_GID) && entskb->sk &&
+           nfqnl_put_sk_uidgid(skb, entskb->sk) < 0)
+               goto nla_put_failure;
+
        if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
                goto nla_put_failure;
 
@@ -504,7 +488,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                nla->nla_type = NFQA_PAYLOAD;
                nla->nla_len = nla_attr_size(data_len);
 
-               nfqnl_zcopy(skb, entskb, data_len, hlen);
+               skb_zerocopy(skb, entskb, data_len, hlen);
        }
 
        nlh->nlmsg_len = skb->len;
index da0c1f4ada128d79c41d0425d4072641b7b34fe3..82cb8236f8a101d260a9f3cc6eb1c218e34163f3 100644 (file)
@@ -92,7 +92,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
        if (ctx->chain->flags & NFT_BASE_CHAIN) {
                const struct nft_base_chain *basechain =
                                                nft_base_chain(ctx->chain);
-               const struct nf_hook_ops *ops = &basechain->ops;
+               const struct nf_hook_ops *ops = &basechain->ops[0];
 
                par->hook_mask = 1 << ops->hooknum;
        }
@@ -253,7 +253,7 @@ static int nft_target_validate(const struct nft_ctx *ctx,
        if (ctx->chain->flags & NFT_BASE_CHAIN) {
                const struct nft_base_chain *basechain =
                                                nft_base_chain(ctx->chain);
-               const struct nf_hook_ops *ops = &basechain->ops;
+               const struct nf_hook_ops *ops = &basechain->ops[0];
 
                hook_mask = 1 << ops->hooknum;
                if (hook_mask & target->hooks)
@@ -323,7 +323,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
        if (ctx->chain->flags & NFT_BASE_CHAIN) {
                const struct nft_base_chain *basechain =
                                                nft_base_chain(ctx->chain);
-               const struct nf_hook_ops *ops = &basechain->ops;
+               const struct nf_hook_ops *ops = &basechain->ops[0];
 
                par->hook_mask = 1 << ops->hooknum;
        }
@@ -449,7 +449,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,
        if (ctx->chain->flags & NFT_BASE_CHAIN) {
                const struct nft_base_chain *basechain =
                                                nft_base_chain(ctx->chain);
-               const struct nf_hook_ops *ops = &basechain->ops;
+               const struct nf_hook_ops *ops = &basechain->ops[0];
 
                hook_mask = 1 << ops->hooknum;
                if (hook_mask & match->hooks)
index 955f4e6e708981af46ab781c806b4794740d79ac..c7c12858e1136fbb3164670a46ea46827b1ecf7b 100644 (file)
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
 #include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
 
 struct nft_ct {
        enum nft_ct_keys        key:8;
        enum ip_conntrack_dir   dir:8;
-       enum nft_registers      dreg:8;
+       union{
+               enum nft_registers      dreg:8;
+               enum nft_registers      sreg:8;
+       };
        uint8_t                 family;
 };
 
-static void nft_ct_eval(const struct nft_expr *expr,
-                       struct nft_data data[NFT_REG_MAX + 1],
-                       const struct nft_pktinfo *pkt)
+static void nft_ct_get_eval(const struct nft_expr *expr,
+                           struct nft_data data[NFT_REG_MAX + 1],
+                           const struct nft_pktinfo *pkt)
 {
        const struct nft_ct *priv = nft_expr_priv(expr);
        struct nft_data *dest = &data[priv->dreg];
@@ -123,24 +127,77 @@ err:
        data[NFT_REG_VERDICT].verdict = NFT_BREAK;
 }
 
+static void nft_ct_set_eval(const struct nft_expr *expr,
+                           struct nft_data data[NFT_REG_MAX + 1],
+                           const struct nft_pktinfo *pkt)
+{
+       const struct nft_ct *priv = nft_expr_priv(expr);
+       struct sk_buff *skb = pkt->skb;
+       u32 value = data[priv->sreg].data[0];
+       enum ip_conntrack_info ctinfo;
+       struct nf_conn *ct;
+
+       ct = nf_ct_get(skb, &ctinfo);
+       if (ct == NULL)
+               return;
+
+       switch (priv->key) {
+#ifdef CONFIG_NF_CONNTRACK_MARK
+       case NFT_CT_MARK:
+               if (ct->mark != value) {
+                       ct->mark = value;
+                       nf_conntrack_event_cache(IPCT_MARK, ct);
+               }
+               break;
+#endif
+       }
+}
+
 static const struct nla_policy nft_ct_policy[NFTA_CT_MAX + 1] = {
        [NFTA_CT_DREG]          = { .type = NLA_U32 },
        [NFTA_CT_KEY]           = { .type = NLA_U32 },
        [NFTA_CT_DIRECTION]     = { .type = NLA_U8 },
+       [NFTA_CT_SREG]          = { .type = NLA_U32 },
 };
 
-static int nft_ct_init(const struct nft_ctx *ctx,
-                      const struct nft_expr *expr,
-                      const struct nlattr * const tb[])
+static int nft_ct_l3proto_try_module_get(uint8_t family)
 {
-       struct nft_ct *priv = nft_expr_priv(expr);
        int err;
 
-       if (tb[NFTA_CT_DREG] == NULL ||
-           tb[NFTA_CT_KEY] == NULL)
-               return -EINVAL;
+       if (family == NFPROTO_INET) {
+               err = nf_ct_l3proto_try_module_get(NFPROTO_IPV4);
+               if (err < 0)
+                       goto err1;
+               err = nf_ct_l3proto_try_module_get(NFPROTO_IPV6);
+               if (err < 0)
+                       goto err2;
+       } else {
+               err = nf_ct_l3proto_try_module_get(family);
+               if (err < 0)
+                       goto err1;
+       }
+       return 0;
+
+err2:
+       nf_ct_l3proto_module_put(NFPROTO_IPV4);
+err1:
+       return err;
+}
+
+static void nft_ct_l3proto_module_put(uint8_t family)
+{
+       if (family == NFPROTO_INET) {
+               nf_ct_l3proto_module_put(NFPROTO_IPV4);
+               nf_ct_l3proto_module_put(NFPROTO_IPV6);
+       } else
+               nf_ct_l3proto_module_put(family);
+}
+
+static int nft_ct_init_validate_get(const struct nft_expr *expr,
+                                   const struct nlattr * const tb[])
+{
+       struct nft_ct *priv = nft_expr_priv(expr);
 
-       priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
        if (tb[NFTA_CT_DIRECTION] != NULL) {
                priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]);
                switch (priv->dir) {
@@ -179,34 +236,72 @@ static int nft_ct_init(const struct nft_ctx *ctx,
                return -EOPNOTSUPP;
        }
 
-       err = nf_ct_l3proto_try_module_get(ctx->afi->family);
+       return 0;
+}
+
+static int nft_ct_init_validate_set(uint32_t key)
+{
+       switch (key) {
+       case NFT_CT_MARK:
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int nft_ct_init(const struct nft_ctx *ctx,
+                      const struct nft_expr *expr,
+                      const struct nlattr * const tb[])
+{
+       struct nft_ct *priv = nft_expr_priv(expr);
+       int err;
+
+       priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
+
+       if (tb[NFTA_CT_DREG]) {
+               err = nft_ct_init_validate_get(expr, tb);
+               if (err < 0)
+                       return err;
+
+               priv->dreg = ntohl(nla_get_be32(tb[NFTA_CT_DREG]));
+               err = nft_validate_output_register(priv->dreg);
+               if (err < 0)
+                       return err;
+
+               err = nft_validate_data_load(ctx, priv->dreg, NULL,
+                                            NFT_DATA_VALUE);
+               if (err < 0)
+                       return err;
+       } else {
+               err = nft_ct_init_validate_set(priv->key);
+               if (err < 0)
+                       return err;
+
+               priv->sreg = ntohl(nla_get_be32(tb[NFTA_CT_SREG]));
+               err = nft_validate_input_register(priv->sreg);
+               if (err < 0)
+                       return err;
+       }
+
+       err = nft_ct_l3proto_try_module_get(ctx->afi->family);
        if (err < 0)
                return err;
-       priv->family = ctx->afi->family;
 
-       priv->dreg = ntohl(nla_get_be32(tb[NFTA_CT_DREG]));
-       err = nft_validate_output_register(priv->dreg);
-       if (err < 0)
-               goto err1;
+       priv->family = ctx->afi->family;
 
-       err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
-       if (err < 0)
-               goto err1;
        return 0;
-
-err1:
-       nf_ct_l3proto_module_put(ctx->afi->family);
-       return err;
 }
 
 static void nft_ct_destroy(const struct nft_expr *expr)
 {
        struct nft_ct *priv = nft_expr_priv(expr);
 
-       nf_ct_l3proto_module_put(priv->family);
+       nft_ct_l3proto_module_put(priv->family);
 }
 
-static int nft_ct_dump(struct sk_buff *skb, const struct nft_expr *expr)
+static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
        const struct nft_ct *priv = nft_expr_priv(expr);
 
@@ -222,19 +317,61 @@ nla_put_failure:
        return -1;
 }
 
+static int nft_ct_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+       const struct nft_ct *priv = nft_expr_priv(expr);
+
+       if (nla_put_be32(skb, NFTA_CT_SREG, htonl(priv->sreg)))
+               goto nla_put_failure;
+       if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
+               goto nla_put_failure;
+       return 0;
+
+nla_put_failure:
+       return -1;
+}
+
 static struct nft_expr_type nft_ct_type;
-static const struct nft_expr_ops nft_ct_ops = {
+static const struct nft_expr_ops nft_ct_get_ops = {
        .type           = &nft_ct_type,
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
-       .eval           = nft_ct_eval,
+       .eval           = nft_ct_get_eval,
        .init           = nft_ct_init,
        .destroy        = nft_ct_destroy,
-       .dump           = nft_ct_dump,
+       .dump           = nft_ct_get_dump,
 };
 
+static const struct nft_expr_ops nft_ct_set_ops = {
+       .type           = &nft_ct_type,
+       .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
+       .eval           = nft_ct_set_eval,
+       .init           = nft_ct_init,
+       .destroy        = nft_ct_destroy,
+       .dump           = nft_ct_set_dump,
+};
+
+static const struct nft_expr_ops *
+nft_ct_select_ops(const struct nft_ctx *ctx,
+                   const struct nlattr * const tb[])
+{
+       if (tb[NFTA_CT_KEY] == NULL)
+               return ERR_PTR(-EINVAL);
+
+       if (tb[NFTA_CT_DREG] && tb[NFTA_CT_SREG])
+               return ERR_PTR(-EINVAL);
+
+       if (tb[NFTA_CT_DREG])
+               return &nft_ct_get_ops;
+
+       if (tb[NFTA_CT_SREG])
+               return &nft_ct_set_ops;
+
+       return ERR_PTR(-EINVAL);
+}
+
 static struct nft_expr_type nft_ct_type __read_mostly = {
        .name           = "ct",
-       .ops            = &nft_ct_ops,
+       .select_ops     = &nft_ct_select_ops,
        .policy         = nft_ct_policy,
        .maxattr        = NFTA_CT_MAX,
        .owner          = THIS_MODULE,
index 8e0bb75e7c51e61092fb904dc1d93befe1e7320d..55c939f5371fabf35ad996efb51ea52a29630703 100644 (file)
@@ -31,7 +31,7 @@ static void nft_exthdr_eval(const struct nft_expr *expr,
 {
        struct nft_exthdr *priv = nft_expr_priv(expr);
        struct nft_data *dest = &data[priv->dreg];
-       unsigned int offset;
+       unsigned int offset = 0;
        int err;
 
        err = ipv6_find_hdr(pkt->skb, &offset, priv->type, NULL, NULL);
index 57cad072a13e50886ba1a2fa1da2c778953d8203..5af790123ad865dbb88c9e172ed4b9beb8590e01 100644 (file)
@@ -33,7 +33,7 @@ static void nft_log_eval(const struct nft_expr *expr,
        const struct nft_log *priv = nft_expr_priv(expr);
        struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
 
-       nf_log_packet(net, priv->family, pkt->hooknum, pkt->skb, pkt->in,
+       nf_log_packet(net, priv->family, pkt->ops->hooknum, pkt->skb, pkt->in,
                      pkt->out, &priv->loginfo, "%s", priv->prefix);
 }
 
index 8c28220a90b34baa013620d0ab13fdaf5355a33e..e8254ad2e5a9f37e84694293c8ba4069b5e5f35e 100644 (file)
 
 struct nft_meta {
        enum nft_meta_keys      key:8;
-       enum nft_registers      dreg:8;
+       union {
+               enum nft_registers      dreg:8;
+               enum nft_registers      sreg:8;
+       };
 };
 
-static void nft_meta_eval(const struct nft_expr *expr,
-                         struct nft_data data[NFT_REG_MAX + 1],
-                         const struct nft_pktinfo *pkt)
+static void nft_meta_get_eval(const struct nft_expr *expr,
+                             struct nft_data data[NFT_REG_MAX + 1],
+                             const struct nft_pktinfo *pkt)
 {
        const struct nft_meta *priv = nft_expr_priv(expr);
        const struct sk_buff *skb = pkt->skb;
@@ -40,6 +43,12 @@ static void nft_meta_eval(const struct nft_expr *expr,
        case NFT_META_PROTOCOL:
                *(__be16 *)dest->data = skb->protocol;
                break;
+       case NFT_META_NFPROTO:
+               dest->data[0] = pkt->ops->pf;
+               break;
+       case NFT_META_L4PROTO:
+               dest->data[0] = pkt->tprot;
+               break;
        case NFT_META_PRIORITY:
                dest->data[0] = skb->priority;
                break;
@@ -132,25 +141,54 @@ err:
        data[NFT_REG_VERDICT].verdict = NFT_BREAK;
 }
 
+static void nft_meta_set_eval(const struct nft_expr *expr,
+                             struct nft_data data[NFT_REG_MAX + 1],
+                             const struct nft_pktinfo *pkt)
+{
+       const struct nft_meta *meta = nft_expr_priv(expr);
+       struct sk_buff *skb = pkt->skb;
+       u32 value = data[meta->sreg].data[0];
+
+       switch (meta->key) {
+       case NFT_META_MARK:
+               skb->mark = value;
+               break;
+       case NFT_META_PRIORITY:
+               skb->priority = value;
+               break;
+       case NFT_META_NFTRACE:
+               skb->nf_trace = 1;
+               break;
+       default:
+               WARN_ON(1);
+       }
+}
+
 static const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
        [NFTA_META_DREG]        = { .type = NLA_U32 },
        [NFTA_META_KEY]         = { .type = NLA_U32 },
+       [NFTA_META_SREG]        = { .type = NLA_U32 },
 };
 
-static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
-                        const struct nlattr * const tb[])
+static int nft_meta_init_validate_set(uint32_t key)
 {
-       struct nft_meta *priv = nft_expr_priv(expr);
-       int err;
-
-       if (tb[NFTA_META_DREG] == NULL ||
-           tb[NFTA_META_KEY] == NULL)
-               return -EINVAL;
+       switch (key) {
+       case NFT_META_MARK:
+       case NFT_META_PRIORITY:
+       case NFT_META_NFTRACE:
+               return 0;
+       default:
+               return -EOPNOTSUPP;
+       }
+}
 
-       priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
-       switch (priv->key) {
+static int nft_meta_init_validate_get(uint32_t key)
+{
+       switch (key) {
        case NFT_META_LEN:
        case NFT_META_PROTOCOL:
+       case NFT_META_NFPROTO:
+       case NFT_META_L4PROTO:
        case NFT_META_PRIORITY:
        case NFT_META_MARK:
        case NFT_META_IIF:
@@ -167,26 +205,72 @@ static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 #ifdef CONFIG_NETWORK_SECMARK
        case NFT_META_SECMARK:
 #endif
-               break;
+               return 0;
        default:
                return -EOPNOTSUPP;
        }
 
-       priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG]));
-       err = nft_validate_output_register(priv->dreg);
+}
+
+static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
+                        const struct nlattr * const tb[])
+{
+       struct nft_meta *priv = nft_expr_priv(expr);
+       int err;
+
+       priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
+
+       if (tb[NFTA_META_DREG]) {
+               err = nft_meta_init_validate_get(priv->key);
+               if (err < 0)
+                       return err;
+
+               priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG]));
+               err = nft_validate_output_register(priv->dreg);
+               if (err < 0)
+                       return err;
+
+               return nft_validate_data_load(ctx, priv->dreg, NULL,
+                                             NFT_DATA_VALUE);
+       }
+
+       err = nft_meta_init_validate_set(priv->key);
+       if (err < 0)
+               return err;
+
+       priv->sreg = ntohl(nla_get_be32(tb[NFTA_META_SREG]));
+       err = nft_validate_input_register(priv->sreg);
        if (err < 0)
                return err;
-       return nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
+
+       return 0;
 }
 
-static int nft_meta_dump(struct sk_buff *skb, const struct nft_expr *expr)
+static int nft_meta_get_dump(struct sk_buff *skb,
+                            const struct nft_expr *expr)
 {
        const struct nft_meta *priv = nft_expr_priv(expr);
 
+       if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
+               goto nla_put_failure;
        if (nla_put_be32(skb, NFTA_META_DREG, htonl(priv->dreg)))
                goto nla_put_failure;
+       return 0;
+
+nla_put_failure:
+       return -1;
+}
+
+static int nft_meta_set_dump(struct sk_buff *skb,
+                            const struct nft_expr *expr)
+{
+       const struct nft_meta *priv = nft_expr_priv(expr);
+
        if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
                goto nla_put_failure;
+       if (nla_put_be32(skb, NFTA_META_SREG, htonl(priv->sreg)))
+               goto nla_put_failure;
+
        return 0;
 
 nla_put_failure:
@@ -194,17 +278,44 @@ nla_put_failure:
 }
 
 static struct nft_expr_type nft_meta_type;
-static const struct nft_expr_ops nft_meta_ops = {
+static const struct nft_expr_ops nft_meta_get_ops = {
+       .type           = &nft_meta_type,
+       .size           = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
+       .eval           = nft_meta_get_eval,
+       .init           = nft_meta_init,
+       .dump           = nft_meta_get_dump,
+};
+
+static const struct nft_expr_ops nft_meta_set_ops = {
        .type           = &nft_meta_type,
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
-       .eval           = nft_meta_eval,
+       .eval           = nft_meta_set_eval,
        .init           = nft_meta_init,
-       .dump           = nft_meta_dump,
+       .dump           = nft_meta_set_dump,
 };
 
+static const struct nft_expr_ops *
+nft_meta_select_ops(const struct nft_ctx *ctx,
+                   const struct nlattr * const tb[])
+{
+       if (tb[NFTA_META_KEY] == NULL)
+               return ERR_PTR(-EINVAL);
+
+       if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
+               return ERR_PTR(-EINVAL);
+
+       if (tb[NFTA_META_DREG])
+               return &nft_meta_get_ops;
+
+       if (tb[NFTA_META_SREG])
+               return &nft_meta_set_ops;
+
+       return ERR_PTR(-EINVAL);
+}
+
 static struct nft_expr_type nft_meta_type __read_mostly = {
        .name           = "meta",
-       .ops            = &nft_meta_ops,
+       .select_ops     = &nft_meta_select_ops,
        .policy         = nft_meta_policy,
        .maxattr        = NFTA_META_MAX,
        .owner          = THIS_MODULE,
diff --git a/net/netfilter/nft_meta_target.c b/net/netfilter/nft_meta_target.c
deleted file mode 100644 (file)
index 71177df..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
- *
- * 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.
- *
- * Development of this code funded by Astaro AG (http://www.astaro.com/)
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/rbtree.h>
-#include <linux/netlink.h>
-#include <linux/netfilter.h>
-#include <linux/netfilter/nf_tables.h>
-#include <net/netfilter/nf_tables.h>
-
-struct nft_meta {
-       enum nft_meta_keys      key;
-};
-
-static void nft_meta_eval(const struct nft_expr *expr,
-                         struct nft_data *nfres,
-                         struct nft_data *data,
-                         const struct nft_pktinfo *pkt)
-{
-       const struct nft_meta *meta = nft_expr_priv(expr);
-       struct sk_buff *skb = pkt->skb;
-       u32 val = data->data[0];
-
-       switch (meta->key) {
-       case NFT_META_MARK:
-               skb->mark = val;
-               break;
-       case NFT_META_PRIORITY:
-               skb->priority = val;
-               break;
-       case NFT_META_NFTRACE:
-               skb->nf_trace = val;
-               break;
-#ifdef CONFIG_NETWORK_SECMARK
-       case NFT_META_SECMARK:
-               skb->secmark = val;
-               break;
-#endif
-       default:
-               WARN_ON(1);
-       }
-}
-
-static const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
-       [NFTA_META_KEY]         = { .type = NLA_U32 },
-};
-
-static int nft_meta_init(const struct nft_expr *expr, struct nlattr *tb[])
-{
-       struct nft_meta *meta = nft_expr_priv(expr);
-
-       if (tb[NFTA_META_KEY] == NULL)
-               return -EINVAL;
-
-       meta->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
-       switch (meta->key) {
-       case NFT_META_MARK:
-       case NFT_META_PRIORITY:
-       case NFT_META_NFTRACE:
-#ifdef CONFIG_NETWORK_SECMARK
-       case NFT_META_SECMARK:
-#endif
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int nft_meta_dump(struct sk_buff *skb, const struct nft_expr *expr)
-{
-       struct nft_meta *meta = nft_expr_priv(expr);
-
-       NLA_PUT_BE32(skb, NFTA_META_KEY, htonl(meta->key));
-       return 0;
-
-nla_put_failure:
-       return -1;
-}
-
-static struct nft_expr_ops meta_target __read_mostly = {
-       .name           = "meta",
-       .size           = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
-       .owner          = THIS_MODULE,
-       .eval           = nft_meta_eval,
-       .init           = nft_meta_init,
-       .dump           = nft_meta_dump,
-       .policy         = nft_meta_policy,
-       .maxattr        = NFTA_META_MAX,
-};
-
-static int __init nft_meta_target_init(void)
-{
-       return nft_register_expr(&meta_target);
-}
-
-static void __exit nft_meta_target_exit(void)
-{
-       nft_unregister_expr(&meta_target);
-}
-
-module_init(nft_meta_target_init);
-module_exit(nft_meta_target_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
-MODULE_ALIAS_NFT_EXPR("meta");
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
new file mode 100644 (file)
index 0000000..cbea473
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
+ *
+ * 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.
+ *
+ * Development of this code partly funded by OISF
+ * (http://www.openinfosecfoundation.org/)
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/jhash.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_queue.h>
+
+static u32 jhash_initval __read_mostly;
+
+struct nft_queue {
+       u16     queuenum;
+       u16     queues_total;
+       u16     flags;
+       u8      family;
+};
+
+static void nft_queue_eval(const struct nft_expr *expr,
+                          struct nft_data data[NFT_REG_MAX + 1],
+                          const struct nft_pktinfo *pkt)
+{
+       struct nft_queue *priv = nft_expr_priv(expr);
+       u32 queue = priv->queuenum;
+       u32 ret;
+
+       if (priv->queues_total > 1) {
+               if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
+                       int cpu = smp_processor_id();
+
+                       queue = priv->queuenum + cpu % priv->queues_total;
+               } else {
+                       queue = nfqueue_hash(pkt->skb, queue,
+                                            priv->queues_total, priv->family,
+                                            jhash_initval);
+               }
+       }
+
+       ret = NF_QUEUE_NR(queue);
+       if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
+               ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
+
+       data[NFT_REG_VERDICT].verdict = ret;
+}
+
+static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = {
+       [NFTA_QUEUE_NUM]        = { .type = NLA_U16 },
+       [NFTA_QUEUE_TOTAL]      = { .type = NLA_U16 },
+       [NFTA_QUEUE_FLAGS]      = { .type = NLA_U16 },
+};
+
+static int nft_queue_init(const struct nft_ctx *ctx,
+                          const struct nft_expr *expr,
+                          const struct nlattr * const tb[])
+{
+       struct nft_queue *priv = nft_expr_priv(expr);
+
+       if (tb[NFTA_QUEUE_NUM] == NULL)
+               return -EINVAL;
+
+       init_hashrandom(&jhash_initval);
+       priv->family = ctx->afi->family;
+       priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
+
+       if (tb[NFTA_QUEUE_TOTAL] != NULL)
+               priv->queues_total = ntohs(nla_get_be16(tb[NFTA_QUEUE_TOTAL]));
+       if (tb[NFTA_QUEUE_FLAGS] != NULL) {
+               priv->flags = ntohs(nla_get_be16(tb[NFTA_QUEUE_FLAGS]));
+               if (priv->flags & ~NFT_QUEUE_FLAG_MASK)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+static int nft_queue_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+       const struct nft_queue *priv = nft_expr_priv(expr);
+
+       if (nla_put_be16(skb, NFTA_QUEUE_NUM, htons(priv->queuenum)) ||
+           nla_put_be16(skb, NFTA_QUEUE_TOTAL, htons(priv->queues_total)) ||
+           nla_put_be16(skb, NFTA_QUEUE_FLAGS, htons(priv->flags)))
+               goto nla_put_failure;
+
+       return 0;
+
+nla_put_failure:
+       return -1;
+}
+
+static struct nft_expr_type nft_queue_type;
+static const struct nft_expr_ops nft_queue_ops = {
+       .type           = &nft_queue_type,
+       .size           = NFT_EXPR_SIZE(sizeof(struct nft_queue)),
+       .eval           = nft_queue_eval,
+       .init           = nft_queue_init,
+       .dump           = nft_queue_dump,
+};
+
+static struct nft_expr_type nft_queue_type __read_mostly = {
+       .name           = "queue",
+       .ops            = &nft_queue_ops,
+       .policy         = nft_queue_policy,
+       .maxattr        = NFTA_QUEUE_MAX,
+       .owner          = THIS_MODULE,
+};
+
+static int __init nft_queue_module_init(void)
+{
+       return nft_register_expr(&nft_queue_type);
+}
+
+static void __exit nft_queue_module_exit(void)
+{
+       nft_unregister_expr(&nft_queue_type);
+}
+
+module_init(nft_queue_module_init);
+module_exit(nft_queue_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Leblond <eric@regit.org>");
+MODULE_ALIAS_NFT_EXPR("queue");
similarity index 78%
rename from net/ipv4/netfilter/nft_reject_ipv4.c
rename to net/netfilter/nft_reject.c
index 4a5e94ac314a8cfdae20d8e393724ea2d01bd588..5e204711d7049781052095ca317a4efd944ea07a 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
  *
  * 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
 #include <linux/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables.h>
 #include <net/icmp.h>
+#include <net/netfilter/ipv4/nf_reject.h>
+
+#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+#include <net/netfilter/ipv6/nf_reject.h>
+#endif
 
 struct nft_reject {
        enum nft_reject_types   type:8;
        u8                      icmp_code;
+       u8                      family;
 };
 
 static void nft_reject_eval(const struct nft_expr *expr,
@@ -27,12 +34,26 @@ static void nft_reject_eval(const struct nft_expr *expr,
                              const struct nft_pktinfo *pkt)
 {
        struct nft_reject *priv = nft_expr_priv(expr);
-
+#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+       struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
+#endif
        switch (priv->type) {
        case NFT_REJECT_ICMP_UNREACH:
-               icmp_send(pkt->skb, ICMP_DEST_UNREACH, priv->icmp_code, 0);
+               if (priv->family == NFPROTO_IPV4)
+                       nf_send_unreach(pkt->skb, priv->icmp_code);
+#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+               else if (priv->family == NFPROTO_IPV6)
+                       nf_send_unreach6(net, pkt->skb, priv->icmp_code,
+                                     pkt->ops->hooknum);
+#endif
                break;
        case NFT_REJECT_TCP_RST:
+               if (priv->family == NFPROTO_IPV4)
+                       nf_send_reset(pkt->skb, pkt->ops->hooknum);
+#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+               else if (priv->family == NFPROTO_IPV6)
+                       nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
+#endif
                break;
        }
 
@@ -53,6 +74,7 @@ static int nft_reject_init(const struct nft_ctx *ctx,
        if (tb[NFTA_REJECT_TYPE] == NULL)
                return -EINVAL;
 
+       priv->family = ctx->afi->family;
        priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
        switch (priv->type) {
        case NFT_REJECT_ICMP_UNREACH:
index da35ac06a975ded85b76953e4d7eb54c33478b04..5929be622c5cd27b9e706811042c9e176a3c78f7 100644 (file)
@@ -211,8 +211,10 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
        ret = 0;
        if ((info->ct_events || info->exp_events) &&
            !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
-                                 GFP_KERNEL))
+                                 GFP_KERNEL)) {
+               ret = -EINVAL;
                goto err3;
+       }
 
        if (info->helper[0]) {
                ret = xt_ct_set_helper(ct, info->helper, par);
index ed00fef58996a8d702b6020720daf679caa1af15..8f1779ff7e30619825c43db9b06be07274bc2f8e 100644 (file)
 #include <linux/module.h>
 #include <linux/skbuff.h>
 
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/jhash.h>
-
 #include <linux/netfilter.h>
 #include <linux/netfilter_arp.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_NFQUEUE.h>
 
+#include <net/netfilter/nf_queue.h>
+
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
 MODULE_LICENSE("GPL");
@@ -28,7 +26,6 @@ MODULE_ALIAS("ip6t_NFQUEUE");
 MODULE_ALIAS("arpt_NFQUEUE");
 
 static u32 jhash_initval __read_mostly;
-static bool rnd_inited __read_mostly;
 
 static unsigned int
 nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
@@ -38,69 +35,16 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
        return NF_QUEUE_NR(tinfo->queuenum);
 }
 
-static u32 hash_v4(const struct sk_buff *skb)
-{
-       const struct iphdr *iph = ip_hdr(skb);
-
-       /* packets in either direction go into same queue */
-       if ((__force u32)iph->saddr < (__force u32)iph->daddr)
-               return jhash_3words((__force u32)iph->saddr,
-                       (__force u32)iph->daddr, iph->protocol, jhash_initval);
-
-       return jhash_3words((__force u32)iph->daddr,
-                       (__force u32)iph->saddr, iph->protocol, jhash_initval);
-}
-
-#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
-static u32 hash_v6(const struct sk_buff *skb)
-{
-       const struct ipv6hdr *ip6h = ipv6_hdr(skb);
-       u32 a, b, c;
-
-       if ((__force u32)ip6h->saddr.s6_addr32[3] <
-           (__force u32)ip6h->daddr.s6_addr32[3]) {
-               a = (__force u32) ip6h->saddr.s6_addr32[3];
-               b = (__force u32) ip6h->daddr.s6_addr32[3];
-       } else {
-               b = (__force u32) ip6h->saddr.s6_addr32[3];
-               a = (__force u32) ip6h->daddr.s6_addr32[3];
-       }
-
-       if ((__force u32)ip6h->saddr.s6_addr32[1] <
-           (__force u32)ip6h->daddr.s6_addr32[1])
-               c = (__force u32) ip6h->saddr.s6_addr32[1];
-       else
-               c = (__force u32) ip6h->daddr.s6_addr32[1];
-
-       return jhash_3words(a, b, c, jhash_initval);
-}
-#endif
-
-static u32
-nfqueue_hash(const struct sk_buff *skb, const struct xt_action_param *par)
-{
-       const struct xt_NFQ_info_v1 *info = par->targinfo;
-       u32 queue = info->queuenum;
-
-       if (par->family == NFPROTO_IPV4)
-               queue += ((u64) hash_v4(skb) * info->queues_total) >> 32;
-#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
-       else if (par->family == NFPROTO_IPV6)
-               queue += ((u64) hash_v6(skb) * info->queues_total) >> 32;
-#endif
-
-       return queue;
-}
-
 static unsigned int
 nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
 {
        const struct xt_NFQ_info_v1 *info = par->targinfo;
        u32 queue = info->queuenum;
 
-       if (info->queues_total > 1)
-               queue = nfqueue_hash(skb, par);
-
+       if (info->queues_total > 1) {
+               queue = nfqueue_hash(skb, queue, info->queues_total,
+                                    par->family, jhash_initval);
+       }
        return NF_QUEUE_NR(queue);
 }
 
@@ -120,10 +64,8 @@ static int nfqueue_tg_check(const struct xt_tgchk_param *par)
        const struct xt_NFQ_info_v3 *info = par->targinfo;
        u32 maxid;
 
-       if (unlikely(!rnd_inited)) {
-               get_random_bytes(&jhash_initval, sizeof(jhash_initval));
-               rnd_inited = true;
-       }
+       init_hashrandom(&jhash_initval);
+
        if (info->queues_total == 0) {
                pr_err("NFQUEUE: number of total queues is 0\n");
                return -EINVAL;
@@ -154,8 +96,10 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
                        int cpu = smp_processor_id();
 
                        queue = info->queuenum + cpu % info->queues_total;
-               } else
-                       queue = nfqueue_hash(skb, par);
+               } else {
+                       queue = nfqueue_hash(skb, queue, info->queues_total,
+                                            par->family, jhash_initval);
+               }
        }
 
        ret = NF_QUEUE_NR(queue);
diff --git a/net/netfilter/xt_cgroup.c b/net/netfilter/xt_cgroup.c
new file mode 100644 (file)
index 0000000..9a8e77e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Xtables module to match the process control group.
+ *
+ * Might be used to implement individual "per-application" firewall
+ * policies in contrast to global policies based on control groups.
+ * Matching is based upon processes tagged to net_cls' classid marker.
+ *
+ * (C) 2013 Daniel Borkmann <dborkman@redhat.com>
+ *
+ * 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 <linux/skbuff.h>
+#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_cgroup.h>
+#include <net/sock.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>");
+MODULE_DESCRIPTION("Xtables: process control group matching");
+MODULE_ALIAS("ipt_cgroup");
+MODULE_ALIAS("ip6t_cgroup");
+
+static int cgroup_mt_check(const struct xt_mtchk_param *par)
+{
+       struct xt_cgroup_info *info = par->matchinfo;
+
+       if (info->invert & ~1)
+               return -EINVAL;
+
+       return info->id ? 0 : -EINVAL;
+}
+
+static bool
+cgroup_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+       const struct xt_cgroup_info *info = par->matchinfo;
+
+       if (skb->sk == NULL)
+               return false;
+
+       return (info->id == skb->sk->sk_classid) ^ info->invert;
+}
+
+static struct xt_match cgroup_mt_reg __read_mostly = {
+       .name       = "cgroup",
+       .revision   = 0,
+       .family     = NFPROTO_UNSPEC,
+       .checkentry = cgroup_mt_check,
+       .match      = cgroup_mt,
+       .matchsize  = sizeof(struct xt_cgroup_info),
+       .me         = THIS_MODULE,
+       .hooks      = (1 << NF_INET_LOCAL_OUT) |
+                     (1 << NF_INET_POST_ROUTING),
+};
+
+static int __init cgroup_mt_init(void)
+{
+       return xt_register_match(&cgroup_mt_reg);
+}
+
+static void __exit cgroup_mt_exit(void)
+{
+       xt_unregister_match(&cgroup_mt_reg);
+}
+
+module_init(cgroup_mt_init);
+module_exit(cgroup_mt_exit);
diff --git a/net/netfilter/xt_ipcomp.c b/net/netfilter/xt_ipcomp.c
new file mode 100644 (file)
index 0000000..a4c7561
--- /dev/null
@@ -0,0 +1,111 @@
+/*  Kernel module to match IPComp parameters for IPv4 and IPv6
+ *
+ *  Copyright (C) 2013 WindRiver
+ *
+ *  Author:
+ *  Fan Du <fan.du@windriver.com>
+ *
+ *  Based on:
+ *  net/netfilter/xt_esp.c
+ *
+ *  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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/in.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+
+#include <linux/netfilter/xt_ipcomp.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Fan Du <fan.du@windriver.com>");
+MODULE_DESCRIPTION("Xtables: IPv4/6 IPsec-IPComp SPI match");
+
+/* Returns 1 if the spi is matched by the range, 0 otherwise */
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
+{
+       bool r;
+       pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n",
+                invert ? '!' : ' ', min, spi, max);
+       r = (spi >= min && spi <= max) ^ invert;
+       pr_debug(" result %s\n", r ? "PASS" : "FAILED");
+       return r;
+}
+
+static bool comp_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+       struct ip_comp_hdr _comphdr;
+       const struct ip_comp_hdr *chdr;
+       const struct xt_ipcomp *compinfo = par->matchinfo;
+
+       /* Must not be a fragment. */
+       if (par->fragoff != 0)
+               return false;
+
+       chdr = skb_header_pointer(skb, par->thoff, sizeof(_comphdr), &_comphdr);
+       if (chdr == NULL) {
+               /* We've been asked to examine this packet, and we
+                * can't.  Hence, no choice but to drop.
+                */
+               pr_debug("Dropping evil IPComp tinygram.\n");
+               par->hotdrop = true;
+               return 0;
+       }
+
+       return spi_match(compinfo->spis[0], compinfo->spis[1],
+                        ntohl(chdr->cpi << 16),
+                        !!(compinfo->invflags & XT_IPCOMP_INV_SPI));
+}
+
+static int comp_mt_check(const struct xt_mtchk_param *par)
+{
+       const struct xt_ipcomp *compinfo = par->matchinfo;
+
+       /* Must specify no unknown invflags */
+       if (compinfo->invflags & ~XT_IPCOMP_INV_MASK) {
+               pr_err("unknown flags %X\n", compinfo->invflags);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static struct xt_match comp_mt_reg[] __read_mostly = {
+       {
+               .name           = "ipcomp",
+               .family         = NFPROTO_IPV4,
+               .match          = comp_mt,
+               .matchsize      = sizeof(struct xt_ipcomp),
+               .proto          = IPPROTO_COMP,
+               .checkentry     = comp_mt_check,
+               .me             = THIS_MODULE,
+       },
+       {
+               .name           = "ipcomp",
+               .family         = NFPROTO_IPV6,
+               .match          = comp_mt,
+               .matchsize      = sizeof(struct xt_ipcomp),
+               .proto          = IPPROTO_COMP,
+               .checkentry     = comp_mt_check,
+               .me             = THIS_MODULE,
+       },
+};
+
+static int __init comp_mt_init(void)
+{
+       return xt_register_matches(comp_mt_reg, ARRAY_SIZE(comp_mt_reg));
+}
+
+static void __exit comp_mt_exit(void)
+{
+       xt_unregister_matches(comp_mt_reg, ARRAY_SIZE(comp_mt_reg));
+}
+
+module_init(comp_mt_init);
+module_exit(comp_mt_exit);
diff --git a/net/netfilter/xt_l2tp.c b/net/netfilter/xt_l2tp.c
new file mode 100644 (file)
index 0000000..8aee572
--- /dev/null
@@ -0,0 +1,354 @@
+/* Kernel module to match L2TP header parameters. */
+
+/* (C) 2013      James Chapman <jchapman@katalix.com>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#include <net/udp.h>
+#include <linux/l2tp.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_tcpudp.h>
+#include <linux/netfilter/xt_l2tp.h>
+
+/* L2TP header masks */
+#define L2TP_HDR_T_BIT 0x8000
+#define L2TP_HDR_L_BIT 0x4000
+#define L2TP_HDR_VER   0x000f
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("Xtables: L2TP header match");
+MODULE_ALIAS("ipt_l2tp");
+MODULE_ALIAS("ip6t_l2tp");
+
+/* The L2TP fields that can be matched */
+struct l2tp_data {
+       u32 tid;
+       u32 sid;
+       u8 type;
+       u8 version;
+};
+
+union l2tp_val {
+       __be16 val16[2];
+       __be32 val32;
+};
+
+static bool l2tp_match(const struct xt_l2tp_info *info, struct l2tp_data *data)
+{
+       if ((info->flags & XT_L2TP_TYPE) && (info->type != data->type))
+               return false;
+
+       if ((info->flags & XT_L2TP_VERSION) && (info->version != data->version))
+               return false;
+
+       /* Check tid only for L2TPv3 control or any L2TPv2 packets */
+       if ((info->flags & XT_L2TP_TID) &&
+           ((data->type == XT_L2TP_TYPE_CONTROL) || (data->version == 2)) &&
+           (info->tid != data->tid))
+               return false;
+
+       /* Check sid only for L2TP data packets */
+       if ((info->flags & XT_L2TP_SID) && (data->type == XT_L2TP_TYPE_DATA) &&
+           (info->sid != data->sid))
+               return false;
+
+       return true;
+}
+
+/* Parse L2TP header fields when UDP encapsulation is used. Handles
+ * L2TPv2 and L2TPv3. Note the L2TPv3 control and data packets have a
+ * different format. See
+ * RFC2661, Section 3.1, L2TPv2 Header Format
+ * RFC3931, Section 3.2.1, L2TPv3 Control Message Header
+ * RFC3931, Section 3.2.2, L2TPv3 Data Message Header
+ * RFC3931, Section 4.1.2.1, L2TPv3 Session Header over UDP
+ */
+static bool l2tp_udp_mt(const struct sk_buff *skb, struct xt_action_param *par, u16 thoff)
+{
+       const struct xt_l2tp_info *info = par->matchinfo;
+       int uhlen = sizeof(struct udphdr);
+       int offs = thoff + uhlen;
+       union l2tp_val *lh;
+       union l2tp_val lhbuf;
+       u16 flags;
+       struct l2tp_data data = { 0, };
+
+       if (par->fragoff != 0)
+               return false;
+
+       /* Extract L2TP header fields. The flags in the first 16 bits
+        * tell us where the other fields are.
+        */
+       lh = skb_header_pointer(skb, offs, 2, &lhbuf);
+       if (lh == NULL)
+               return false;
+
+       flags = ntohs(lh->val16[0]);
+       if (flags & L2TP_HDR_T_BIT)
+               data.type = XT_L2TP_TYPE_CONTROL;
+       else
+               data.type = XT_L2TP_TYPE_DATA;
+       data.version = (u8) flags & L2TP_HDR_VER;
+
+       /* Now extract the L2TP tid/sid. These are in different places
+        * for L2TPv2 (rfc2661) and L2TPv3 (rfc3931). For L2TPv2, we
+        * must also check to see if the length field is present,
+        * since this affects the offsets into the packet of the
+        * tid/sid fields.
+        */
+       if (data.version == 3) {
+               lh = skb_header_pointer(skb, offs + 4, 4, &lhbuf);
+               if (lh == NULL)
+                       return false;
+               if (data.type == XT_L2TP_TYPE_CONTROL)
+                       data.tid = ntohl(lh->val32);
+               else
+                       data.sid = ntohl(lh->val32);
+       } else if (data.version == 2) {
+               if (flags & L2TP_HDR_L_BIT)
+                       offs += 2;
+               lh = skb_header_pointer(skb, offs + 2, 4, &lhbuf);
+               if (lh == NULL)
+                       return false;
+               data.tid = (u32) ntohs(lh->val16[0]);
+               data.sid = (u32) ntohs(lh->val16[1]);
+       } else
+               return false;
+
+       return l2tp_match(info, &data);
+}
+
+/* Parse L2TP header fields for IP encapsulation (no UDP header).
+ * L2TPv3 data packets have a different form with IP encap. See
+ * RC3931, Section 4.1.1.1, L2TPv3 Session Header over IP.
+ * RC3931, Section 4.1.1.2, L2TPv3 Control and Data Traffic over IP.
+ */
+static bool l2tp_ip_mt(const struct sk_buff *skb, struct xt_action_param *par, u16 thoff)
+{
+       const struct xt_l2tp_info *info = par->matchinfo;
+       union l2tp_val *lh;
+       union l2tp_val lhbuf;
+       struct l2tp_data data = { 0, };
+
+       /* For IP encap, the L2TP sid is the first 32-bits. */
+       lh = skb_header_pointer(skb, thoff, sizeof(lhbuf), &lhbuf);
+       if (lh == NULL)
+               return false;
+       if (lh->val32 == 0) {
+               /* Must be a control packet. The L2TP tid is further
+                * into the packet.
+                */
+               data.type = XT_L2TP_TYPE_CONTROL;
+               lh = skb_header_pointer(skb, thoff + 8, sizeof(lhbuf),
+                                       &lhbuf);
+               if (lh == NULL)
+                       return false;
+               data.tid = ntohl(lh->val32);
+       } else {
+               data.sid = ntohl(lh->val32);
+               data.type = XT_L2TP_TYPE_DATA;
+       }
+
+       data.version = 3;
+
+       return l2tp_match(info, &data);
+}
+
+static bool l2tp_mt4(const struct sk_buff *skb, struct xt_action_param *par)
+{
+       struct iphdr *iph = ip_hdr(skb);
+       u8 ipproto = iph->protocol;
+
+       /* l2tp_mt_check4 already restricts the transport protocol */
+       switch (ipproto) {
+       case IPPROTO_UDP:
+               return l2tp_udp_mt(skb, par, par->thoff);
+       case IPPROTO_L2TP:
+               return l2tp_ip_mt(skb, par, par->thoff);
+       }
+
+       return false;
+}
+
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+static bool l2tp_mt6(const struct sk_buff *skb, struct xt_action_param *par)
+{
+       unsigned int thoff = 0;
+       unsigned short fragoff = 0;
+       int ipproto;
+
+       ipproto = ipv6_find_hdr(skb, &thoff, -1, &fragoff, NULL);
+       if (fragoff != 0)
+               return false;
+
+       /* l2tp_mt_check6 already restricts the transport protocol */
+       switch (ipproto) {
+       case IPPROTO_UDP:
+               return l2tp_udp_mt(skb, par, thoff);
+       case IPPROTO_L2TP:
+               return l2tp_ip_mt(skb, par, thoff);
+       }
+
+       return false;
+}
+#endif
+
+static int l2tp_mt_check(const struct xt_mtchk_param *par)
+{
+       const struct xt_l2tp_info *info = par->matchinfo;
+
+       /* Check for invalid flags */
+       if (info->flags & ~(XT_L2TP_TID | XT_L2TP_SID | XT_L2TP_VERSION |
+                           XT_L2TP_TYPE)) {
+               pr_info("unknown flags: %x\n", info->flags);
+               return -EINVAL;
+       }
+
+       /* At least one of tid, sid or type=control must be specified */
+       if ((!(info->flags & XT_L2TP_TID)) &&
+           (!(info->flags & XT_L2TP_SID)) &&
+           ((!(info->flags & XT_L2TP_TYPE)) ||
+            (info->type != XT_L2TP_TYPE_CONTROL))) {
+               pr_info("invalid flags combination: %x\n", info->flags);
+               return -EINVAL;
+       }
+
+       /* If version 2 is specified, check that incompatible params
+        * are not supplied
+        */
+       if (info->flags & XT_L2TP_VERSION) {
+               if ((info->version < 2) || (info->version > 3)) {
+                       pr_info("wrong L2TP version: %u\n", info->version);
+                       return -EINVAL;
+               }
+
+               if (info->version == 2) {
+                       if ((info->flags & XT_L2TP_TID) &&
+                           (info->tid > 0xffff)) {
+                               pr_info("v2 tid > 0xffff: %u\n", info->tid);
+                               return -EINVAL;
+                       }
+                       if ((info->flags & XT_L2TP_SID) &&
+                           (info->sid > 0xffff)) {
+                               pr_info("v2 sid > 0xffff: %u\n", info->sid);
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int l2tp_mt_check4(const struct xt_mtchk_param *par)
+{
+       const struct xt_l2tp_info *info = par->matchinfo;
+       const struct ipt_entry *e = par->entryinfo;
+       const struct ipt_ip *ip = &e->ip;
+       int ret;
+
+       ret = l2tp_mt_check(par);
+       if (ret != 0)
+               return ret;
+
+       if ((ip->proto != IPPROTO_UDP) &&
+           (ip->proto != IPPROTO_L2TP)) {
+               pr_info("missing protocol rule (udp|l2tpip)\n");
+               return -EINVAL;
+       }
+
+       if ((ip->proto == IPPROTO_L2TP) &&
+           (info->version == 2)) {
+               pr_info("v2 doesn't support IP mode\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+static int l2tp_mt_check6(const struct xt_mtchk_param *par)
+{
+       const struct xt_l2tp_info *info = par->matchinfo;
+       const struct ip6t_entry *e = par->entryinfo;
+       const struct ip6t_ip6 *ip = &e->ipv6;
+       int ret;
+
+       ret = l2tp_mt_check(par);
+       if (ret != 0)
+               return ret;
+
+       if ((ip->proto != IPPROTO_UDP) &&
+           (ip->proto != IPPROTO_L2TP)) {
+               pr_info("missing protocol rule (udp|l2tpip)\n");
+               return -EINVAL;
+       }
+
+       if ((ip->proto == IPPROTO_L2TP) &&
+           (info->version == 2)) {
+               pr_info("v2 doesn't support IP mode\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+#endif
+
+static struct xt_match l2tp_mt_reg[] __read_mostly = {
+       {
+               .name      = "l2tp",
+               .revision  = 0,
+               .family    = NFPROTO_IPV4,
+               .match     = l2tp_mt4,
+               .matchsize = XT_ALIGN(sizeof(struct xt_l2tp_info)),
+               .checkentry = l2tp_mt_check4,
+               .hooks     = ((1 << NF_INET_PRE_ROUTING) |
+                             (1 << NF_INET_LOCAL_IN) |
+                             (1 << NF_INET_LOCAL_OUT) |
+                             (1 << NF_INET_FORWARD)),
+               .me        = THIS_MODULE,
+       },
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+       {
+               .name      = "l2tp",
+               .revision  = 0,
+               .family    = NFPROTO_IPV6,
+               .match     = l2tp_mt6,
+               .matchsize = XT_ALIGN(sizeof(struct xt_l2tp_info)),
+               .checkentry = l2tp_mt_check6,
+               .hooks     = ((1 << NF_INET_PRE_ROUTING) |
+                             (1 << NF_INET_LOCAL_IN) |
+                             (1 << NF_INET_LOCAL_OUT) |
+                             (1 << NF_INET_FORWARD)),
+               .me        = THIS_MODULE,
+       },
+#endif
+};
+
+static int __init l2tp_mt_init(void)
+{
+       return xt_register_matches(&l2tp_mt_reg[0], ARRAY_SIZE(l2tp_mt_reg));
+}
+
+static void __exit l2tp_mt_exit(void)
+{
+       xt_unregister_matches(&l2tp_mt_reg[0], ARRAY_SIZE(l2tp_mt_reg));
+}
+
+module_init(l2tp_mt_init);
+module_exit(l2tp_mt_exit);
index bca50b95c182300cbd89f8cfc21b17e9d6e31fe2..34a656d90175b58508b76b795724e0384eb7e11d 100644 (file)
@@ -131,7 +131,7 @@ int netlink_add_tap(struct netlink_tap *nt)
 }
 EXPORT_SYMBOL_GPL(netlink_add_tap);
 
-int __netlink_remove_tap(struct netlink_tap *nt)
+static int __netlink_remove_tap(struct netlink_tap *nt)
 {
        bool found = false;
        struct netlink_tap *tmp;
@@ -155,7 +155,6 @@ out:
 
        return found ? 0 : -ENODEV;
 }
-EXPORT_SYMBOL_GPL(__netlink_remove_tap);
 
 int netlink_remove_tap(struct netlink_tap *nt)
 {
@@ -204,6 +203,8 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb,
        if (nskb) {
                nskb->dev = dev;
                nskb->protocol = htons((u16) sk->sk_protocol);
+               nskb->pkt_type = netlink_is_kernel(sk) ?
+                                PACKET_KERNEL : PACKET_USER;
 
                ret = dev_queue_xmit(nskb);
                if (unlikely(ret > 0))
@@ -239,6 +240,13 @@ static void netlink_deliver_tap(struct sk_buff *skb)
        rcu_read_unlock();
 }
 
+static void netlink_deliver_tap_kernel(struct sock *dst, struct sock *src,
+                                      struct sk_buff *skb)
+{
+       if (!(netlink_is_kernel(dst) && netlink_is_kernel(src)))
+               netlink_deliver_tap(skb);
+}
+
 static void netlink_overrun(struct sock *sk)
 {
        struct netlink_sock *nlk = nlk_sk(sk);
@@ -1697,14 +1705,10 @@ static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb,
 
        ret = -ECONNREFUSED;
        if (nlk->netlink_rcv != NULL) {
-               /* We could do a netlink_deliver_tap(skb) here as well
-                * but since this is intended for the kernel only, we
-                * should rather let it stay under the hood.
-                */
-
                ret = skb->len;
                netlink_skb_set_owner_r(skb, sk);
                NETLINK_CB(skb).sk = ssk;
+               netlink_deliver_tap_kernel(sk, ssk, skb);
                nlk->netlink_rcv(skb);
                consume_skb(skb);
        } else {
@@ -1769,6 +1773,9 @@ struct sk_buff *netlink_alloc_skb(struct sock *ssk, unsigned int size,
        if (ring->pg_vec == NULL)
                goto out_put;
 
+       if (ring->frame_size - NL_MMAP_HDRLEN < size)
+               goto out_put;
+
        skb = alloc_skb_head(gfp_mask);
        if (skb == NULL)
                goto err1;
@@ -1778,6 +1785,7 @@ struct sk_buff *netlink_alloc_skb(struct sock *ssk, unsigned int size,
        if (ring->pg_vec == NULL)
                goto out_free;
 
+       /* check again under lock */
        maxlen = ring->frame_size - NL_MMAP_HDRLEN;
        if (maxlen < size)
                goto out_free;
@@ -2535,21 +2543,6 @@ void __netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
                netlink_update_socket_mc(nlk_sk(sk), group, 0);
 }
 
-/**
- * netlink_clear_multicast_users - kick off multicast listeners
- *
- * This function removes all listeners from the given group.
- * @ksk: The kernel netlink socket, as returned by
- *     netlink_kernel_create().
- * @group: The multicast group to clear.
- */
-void netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
-{
-       netlink_table_grab();
-       __netlink_clear_multicast_users(ksk, group);
-       netlink_table_ungrab();
-}
-
 struct nlmsghdr *
 __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int flags)
 {
index 713671ae45aff688e693d6087ae4d8ce9e986f48..b1dcdb932a86ee919642f47f58dd3b716995ad76 100644 (file)
@@ -460,6 +460,26 @@ int genl_unregister_family(struct genl_family *family)
 }
 EXPORT_SYMBOL(genl_unregister_family);
 
+/**
+ * genlmsg_new_unicast - Allocate generic netlink message for unicast
+ * @payload: size of the message payload
+ * @info: information on destination
+ * @flags: the type of memory to allocate
+ *
+ * Allocates a new sk_buff large enough to cover the specified payload
+ * plus required Netlink headers. Will check receiving socket for
+ * memory mapped i/o capability and use it if enabled. Will fall back
+ * to non-mapped skb if message size exceeds the frame size of the ring.
+ */
+struct sk_buff *genlmsg_new_unicast(size_t payload, struct genl_info *info,
+                                   gfp_t flags)
+{
+       size_t len = nlmsg_total_size(genlmsg_total_size(payload));
+
+       return netlink_alloc_skb(info->dst_sk, len, info->snd_portid, flags);
+}
+EXPORT_SYMBOL_GPL(genlmsg_new_unicast);
+
 /**
  * genlmsg_put - Add generic netlink header to netlink message
  * @skb: socket buffer holding the message
@@ -600,6 +620,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
        info.genlhdr = nlmsg_data(nlh);
        info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
        info.attrs = attrbuf;
+       info.dst_sk = skb->sk;
        genl_info_net_set(&info, net);
        memset(&info.user_ptr, 0, sizeof(info.user_ptr));
 
index 6f5e1dd3be2dbdcfdb591d64323c3558d0636e6d..df4692826ead9ef8b5761f58ef7218bf4b3f5119 100644 (file)
@@ -108,10 +108,9 @@ int lockdep_ovsl_is_held(void)
 #endif
 
 static struct vport *new_vport(const struct vport_parms *);
-static int queue_gso_packets(struct net *, int dp_ifindex, struct sk_buff *,
+static int queue_gso_packets(struct datapath *dp, struct sk_buff *,
                             const struct dp_upcall_info *);
-static int queue_userspace_packet(struct net *, int dp_ifindex,
-                                 struct sk_buff *,
+static int queue_userspace_packet(struct datapath *dp, struct sk_buff *,
                                  const struct dp_upcall_info *);
 
 /* Must be called with rcu_read_lock or ovs_mutex. */
@@ -133,7 +132,7 @@ static struct datapath *get_dp(struct net *net, int dp_ifindex)
 }
 
 /* Must be called with rcu_read_lock or ovs_mutex. */
-const char *ovs_dp_name(const struct datapath *dp)
+static const char *ovs_dp_name(const struct datapath *dp)
 {
        struct vport *vport = ovs_vport_ovsl_rcu(dp, OVSP_LOCAL);
        return vport->ops->get_name(vport);
@@ -234,7 +233,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
        }
 
        /* Look up flow. */
-       flow = ovs_flow_tbl_lookup(&dp->table, &key, &n_mask_hit);
+       flow = ovs_flow_tbl_lookup_stats(&dp->table, &key, &n_mask_hit);
        if (unlikely(!flow)) {
                struct dp_upcall_info upcall;
 
@@ -251,9 +250,9 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
        OVS_CB(skb)->flow = flow;
        OVS_CB(skb)->pkt_key = &key;
 
-       stats_counter = &stats->n_hit;
-       ovs_flow_used(OVS_CB(skb)->flow, skb);
+       ovs_flow_stats_update(OVS_CB(skb)->flow, skb);
        ovs_execute_actions(dp, skb);
+       stats_counter = &stats->n_hit;
 
 out:
        /* Update datapath statistics. */
@@ -277,7 +276,6 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
                  const struct dp_upcall_info *upcall_info)
 {
        struct dp_stats_percpu *stats;
-       int dp_ifindex;
        int err;
 
        if (upcall_info->portid == 0) {
@@ -285,16 +283,10 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
                goto err;
        }
 
-       dp_ifindex = get_dpifindex(dp);
-       if (!dp_ifindex) {
-               err = -ENODEV;
-               goto err;
-       }
-
        if (!skb_is_gso(skb))
-               err = queue_userspace_packet(ovs_dp_get_net(dp), dp_ifindex, skb, upcall_info);
+               err = queue_userspace_packet(dp, skb, upcall_info);
        else
-               err = queue_gso_packets(ovs_dp_get_net(dp), dp_ifindex, skb, upcall_info);
+               err = queue_gso_packets(dp, skb, upcall_info);
        if (err)
                goto err;
 
@@ -310,8 +302,7 @@ err:
        return err;
 }
 
-static int queue_gso_packets(struct net *net, int dp_ifindex,
-                            struct sk_buff *skb,
+static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
                             const struct dp_upcall_info *upcall_info)
 {
        unsigned short gso_type = skb_shinfo(skb)->gso_type;
@@ -320,14 +311,14 @@ static int queue_gso_packets(struct net *net, int dp_ifindex,
        struct sk_buff *segs, *nskb;
        int err;
 
-       segs = __skb_gso_segment(skb, NETIF_F_SG | NETIF_F_HW_CSUM, false);
+       segs = __skb_gso_segment(skb, NETIF_F_SG, false);
        if (IS_ERR(segs))
                return PTR_ERR(segs);
 
        /* Queue all of the segments. */
        skb = segs;
        do {
-               err = queue_userspace_packet(net, dp_ifindex, skb, upcall_info);
+               err = queue_userspace_packet(dp, skb, upcall_info);
                if (err)
                        break;
 
@@ -380,11 +371,11 @@ static size_t key_attr_size(void)
                + nla_total_size(28); /* OVS_KEY_ATTR_ND */
 }
 
-static size_t upcall_msg_size(const struct sk_buff *skb,
-                             const struct nlattr *userdata)
+static size_t upcall_msg_size(const struct nlattr *userdata,
+                             unsigned int hdrlen)
 {
        size_t size = NLMSG_ALIGN(sizeof(struct ovs_header))
-               + nla_total_size(skb->len) /* OVS_PACKET_ATTR_PACKET */
+               + nla_total_size(hdrlen) /* OVS_PACKET_ATTR_PACKET */
                + nla_total_size(key_attr_size()); /* OVS_PACKET_ATTR_KEY */
 
        /* OVS_PACKET_ATTR_USERDATA */
@@ -394,15 +385,24 @@ static size_t upcall_msg_size(const struct sk_buff *skb,
        return size;
 }
 
-static int queue_userspace_packet(struct net *net, int dp_ifindex,
-                                 struct sk_buff *skb,
+static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
                                  const struct dp_upcall_info *upcall_info)
 {
        struct ovs_header *upcall;
        struct sk_buff *nskb = NULL;
        struct sk_buff *user_skb; /* to be queued to userspace */
        struct nlattr *nla;
-       int err;
+       struct genl_info info = {
+               .dst_sk = ovs_dp_get_net(dp)->genl_sock,
+               .snd_portid = upcall_info->portid,
+       };
+       size_t len;
+       unsigned int hlen;
+       int err, dp_ifindex;
+
+       dp_ifindex = get_dpifindex(dp);
+       if (!dp_ifindex)
+               return -ENODEV;
 
        if (vlan_tx_tag_present(skb)) {
                nskb = skb_clone(skb, GFP_ATOMIC);
@@ -422,7 +422,22 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
                goto out;
        }
 
-       user_skb = genlmsg_new(upcall_msg_size(skb, upcall_info->userdata), GFP_ATOMIC);
+       /* Complete checksum if needed */
+       if (skb->ip_summed == CHECKSUM_PARTIAL &&
+           (err = skb_checksum_help(skb)))
+               goto out;
+
+       /* Older versions of OVS user space enforce alignment of the last
+        * Netlink attribute to NLA_ALIGNTO which would require extensive
+        * padding logic. Only perform zerocopy if padding is not required.
+        */
+       if (dp->user_features & OVS_DP_F_UNALIGNED)
+               hlen = skb_zerocopy_headlen(skb);
+       else
+               hlen = skb->len;
+
+       len = upcall_msg_size(upcall_info->userdata, hlen);
+       user_skb = genlmsg_new_unicast(len, &info, GFP_ATOMIC);
        if (!user_skb) {
                err = -ENOMEM;
                goto out;
@@ -441,26 +456,24 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
                          nla_len(upcall_info->userdata),
                          nla_data(upcall_info->userdata));
 
-       nla = __nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, skb->len);
+       /* Only reserve room for attribute header, packet data is added
+        * in skb_zerocopy() */
+       if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) {
+               err = -ENOBUFS;
+               goto out;
+       }
+       nla->nla_len = nla_attr_size(skb->len);
 
-       skb_copy_and_csum_dev(skb, nla_data(nla));
+       skb_zerocopy(user_skb, skb, skb->len, hlen);
 
-       genlmsg_end(user_skb, upcall);
-       err = genlmsg_unicast(net, user_skb, upcall_info->portid);
+       ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len;
 
+       err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid);
 out:
        kfree_skb(nskb);
        return err;
 }
 
-static void clear_stats(struct sw_flow *flow)
-{
-       flow->used = 0;
-       flow->tcp_flags = 0;
-       flow->packet_count = 0;
-       flow->byte_count = 0;
-}
-
 static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 {
        struct ovs_header *ovs_header = info->userhdr;
@@ -499,7 +512,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
                packet->protocol = htons(ETH_P_802_2);
 
        /* Build an sw_flow for sending this packet. */
-       flow = ovs_flow_alloc();
+       flow = ovs_flow_alloc(false);
        err = PTR_ERR(flow);
        if (IS_ERR(flow))
                goto err_kfree_skb;
@@ -635,10 +648,10 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
        const int skb_orig_len = skb->len;
        struct nlattr *start;
        struct ovs_flow_stats stats;
+       __be16 tcp_flags;
+       unsigned long used;
        struct ovs_header *ovs_header;
        struct nlattr *nla;
-       unsigned long used;
-       u8 tcp_flags;
        int err;
 
        ovs_header = genlmsg_put(skb, portid, seq, &dp_flow_genl_family, flags, cmd);
@@ -667,24 +680,17 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
 
        nla_nest_end(skb, nla);
 
-       spin_lock_bh(&flow->lock);
-       used = flow->used;
-       stats.n_packets = flow->packet_count;
-       stats.n_bytes = flow->byte_count;
-       tcp_flags = (u8)ntohs(flow->tcp_flags);
-       spin_unlock_bh(&flow->lock);
-
+       ovs_flow_stats_get(flow, &stats, &used, &tcp_flags);
        if (used &&
            nla_put_u64(skb, OVS_FLOW_ATTR_USED, ovs_flow_used_time(used)))
                goto nla_put_failure;
 
        if (stats.n_packets &&
-           nla_put(skb, OVS_FLOW_ATTR_STATS,
-                   sizeof(struct ovs_flow_stats), &stats))
+           nla_put(skb, OVS_FLOW_ATTR_STATS, sizeof(struct ovs_flow_stats), &stats))
                goto nla_put_failure;
 
-       if (tcp_flags &&
-           nla_put_u8(skb, OVS_FLOW_ATTR_TCP_FLAGS, tcp_flags))
+       if ((u8)ntohs(tcp_flags) &&
+            nla_put_u8(skb, OVS_FLOW_ATTR_TCP_FLAGS, (u8)ntohs(tcp_flags)))
                goto nla_put_failure;
 
        /* If OVS_FLOW_ATTR_ACTIONS doesn't fit, skip dumping the actions if
@@ -701,8 +707,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
        if (start) {
                const struct sw_flow_actions *sf_acts;
 
-               sf_acts = rcu_dereference_check(flow->sf_acts,
-                                               lockdep_ovsl_is_held());
+               sf_acts = rcu_dereference_ovsl(flow->sf_acts);
 
                err = ovs_nla_put_actions(sf_acts->actions,
                                          sf_acts->actions_len, skb);
@@ -726,39 +731,34 @@ error:
        return err;
 }
 
-static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow)
+static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow,
+                                              struct genl_info *info)
 {
-       const struct sw_flow_actions *sf_acts;
+       size_t len;
 
-       sf_acts = ovsl_dereference(flow->sf_acts);
+       len = ovs_flow_cmd_msg_size(ovsl_dereference(flow->sf_acts));
 
-       return genlmsg_new(ovs_flow_cmd_msg_size(sf_acts), GFP_KERNEL);
+       return genlmsg_new_unicast(len, info, GFP_KERNEL);
 }
 
 static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow,
                                               struct datapath *dp,
-                                              u32 portid, u32 seq, u8 cmd)
+                                              struct genl_info *info,
+                                              u8 cmd)
 {
        struct sk_buff *skb;
        int retval;
 
-       skb = ovs_flow_cmd_alloc_info(flow);
+       skb = ovs_flow_cmd_alloc_info(flow, info);
        if (!skb)
                return ERR_PTR(-ENOMEM);
 
-       retval = ovs_flow_cmd_fill_info(flow, dp, skb, portid, seq, 0, cmd);
+       retval = ovs_flow_cmd_fill_info(flow, dp, skb, info->snd_portid,
+                                       info->snd_seq, 0, cmd);
        BUG_ON(retval < 0);
        return skb;
 }
 
-static struct sw_flow *__ovs_flow_tbl_lookup(struct flow_table *tbl,
-                                             const struct sw_flow_key *key)
-{
-       u32 __always_unused n_mask_hit;
-
-       return ovs_flow_tbl_lookup(tbl, key, &n_mask_hit);
-}
-
 static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 {
        struct nlattr **a = info->attrs;
@@ -770,6 +770,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
        struct datapath *dp;
        struct sw_flow_actions *acts = NULL;
        struct sw_flow_match match;
+       bool exact_5tuple;
        int error;
 
        /* Extract key. */
@@ -778,7 +779,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                goto error;
 
        ovs_match_init(&match, &key, &mask);
-       error = ovs_nla_get_match(&match,
+       error = ovs_nla_get_match(&match, &exact_5tuple,
                                  a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]);
        if (error)
                goto error;
@@ -809,7 +810,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                goto err_unlock_ovs;
 
        /* Check if this is a duplicate flow */
-       flow = __ovs_flow_tbl_lookup(&dp->table, &key);
+       flow = ovs_flow_tbl_lookup(&dp->table, &key);
        if (!flow) {
                /* Bail out if we're not allowed to create a new flow. */
                error = -ENOENT;
@@ -817,12 +818,11 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                        goto err_unlock_ovs;
 
                /* Allocate flow. */
-               flow = ovs_flow_alloc();
+               flow = ovs_flow_alloc(!exact_5tuple);
                if (IS_ERR(flow)) {
                        error = PTR_ERR(flow);
                        goto err_unlock_ovs;
                }
-               clear_stats(flow);
 
                flow->key = masked_key;
                flow->unmasked_key = key;
@@ -835,8 +835,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                        goto err_flow_free;
                }
 
-               reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid,
-                                               info->snd_seq, OVS_FLOW_CMD_NEW);
+               reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
        } else {
                /* We found a matching flow. */
                struct sw_flow_actions *old_acts;
@@ -864,15 +863,11 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                rcu_assign_pointer(flow->sf_acts, acts);
                ovs_nla_free_flow_actions(old_acts);
 
-               reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid,
-                                              info->snd_seq, OVS_FLOW_CMD_NEW);
+               reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
 
                /* Clear stats. */
-               if (a[OVS_FLOW_ATTR_CLEAR]) {
-                       spin_lock_bh(&flow->lock);
-                       clear_stats(flow);
-                       spin_unlock_bh(&flow->lock);
-               }
+               if (a[OVS_FLOW_ATTR_CLEAR])
+                       ovs_flow_stats_clear(flow);
        }
        ovs_unlock();
 
@@ -910,7 +905,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
        }
 
        ovs_match_init(&match, &key, NULL);
-       err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL);
+       err = ovs_nla_get_match(&match, NULL, a[OVS_FLOW_ATTR_KEY], NULL);
        if (err)
                return err;
 
@@ -921,14 +916,13 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
                goto unlock;
        }
 
-       flow = __ovs_flow_tbl_lookup(&dp->table, &key);
+       flow = ovs_flow_tbl_lookup(&dp->table, &key);
        if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) {
                err = -ENOENT;
                goto unlock;
        }
 
-       reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid,
-                                       info->snd_seq, OVS_FLOW_CMD_NEW);
+       reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
        if (IS_ERR(reply)) {
                err = PTR_ERR(reply);
                goto unlock;
@@ -965,17 +959,17 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
        }
 
        ovs_match_init(&match, &key, NULL);
-       err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL);
+       err = ovs_nla_get_match(&match, NULL, a[OVS_FLOW_ATTR_KEY], NULL);
        if (err)
                goto unlock;
 
-       flow = __ovs_flow_tbl_lookup(&dp->table, &key);
+       flow = ovs_flow_tbl_lookup(&dp->table, &key);
        if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) {
                err = -ENOENT;
                goto unlock;
        }
 
-       reply = ovs_flow_cmd_alloc_info(flow);
+       reply = ovs_flow_cmd_alloc_info(flow, info);
        if (!reply) {
                err = -ENOMEM;
                goto unlock;
@@ -1061,6 +1055,7 @@ static const struct genl_ops dp_flow_genl_ops[] = {
 static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
        [OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
        [OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 },
+       [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
 };
 
 static struct genl_family dp_datapath_genl_family = {
@@ -1119,6 +1114,9 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
                        &dp_megaflow_stats))
                goto nla_put_failure;
 
+       if (nla_put_u32(skb, OVS_DP_ATTR_USER_FEATURES, dp->user_features))
+               goto nla_put_failure;
+
        return genlmsg_end(skb, ovs_header);
 
 nla_put_failure:
@@ -1127,17 +1125,17 @@ error:
        return -EMSGSIZE;
 }
 
-static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp, u32 portid,
-                                            u32 seq, u8 cmd)
+static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp,
+                                            struct genl_info *info, u8 cmd)
 {
        struct sk_buff *skb;
        int retval;
 
-       skb = genlmsg_new(ovs_dp_cmd_msg_size(), GFP_KERNEL);
+       skb = genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL);
        if (!skb)
                return ERR_PTR(-ENOMEM);
 
-       retval = ovs_dp_cmd_fill_info(dp, skb, portid, seq, 0, cmd);
+       retval = ovs_dp_cmd_fill_info(dp, skb, info->snd_portid, info->snd_seq, 0, cmd);
        if (retval < 0) {
                kfree_skb(skb);
                return ERR_PTR(retval);
@@ -1165,6 +1163,24 @@ static struct datapath *lookup_datapath(struct net *net,
        return dp ? dp : ERR_PTR(-ENODEV);
 }
 
+static void ovs_dp_reset_user_features(struct sk_buff *skb, struct genl_info *info)
+{
+       struct datapath *dp;
+
+       dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
+       if (!dp)
+               return;
+
+       WARN(dp->user_features, "Dropping previously announced user features\n");
+       dp->user_features = 0;
+}
+
+static void ovs_dp_change(struct datapath *dp, struct nlattr **a)
+{
+       if (a[OVS_DP_ATTR_USER_FEATURES])
+               dp->user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]);
+}
+
 static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
 {
        struct nlattr **a = info->attrs;
@@ -1223,17 +1239,27 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
        parms.port_no = OVSP_LOCAL;
        parms.upcall_portid = nla_get_u32(a[OVS_DP_ATTR_UPCALL_PID]);
 
+       ovs_dp_change(dp, a);
+
        vport = new_vport(&parms);
        if (IS_ERR(vport)) {
                err = PTR_ERR(vport);
                if (err == -EBUSY)
                        err = -EEXIST;
 
+               if (err == -EEXIST) {
+                       /* An outdated user space instance that does not understand
+                        * the concept of user_features has attempted to create a new
+                        * datapath and is likely to reuse it. Drop all user features.
+                        */
+                       if (info->genlhdr->version < OVS_DP_VER_FEATURES)
+                               ovs_dp_reset_user_features(skb, info);
+               }
+
                goto err_destroy_ports_array;
        }
 
-       reply = ovs_dp_cmd_build_info(dp, info->snd_portid,
-                                     info->snd_seq, OVS_DP_CMD_NEW);
+       reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW);
        err = PTR_ERR(reply);
        if (IS_ERR(reply))
                goto err_destroy_local_port;
@@ -1299,8 +1325,7 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
        if (IS_ERR(dp))
                goto unlock;
 
-       reply = ovs_dp_cmd_build_info(dp, info->snd_portid,
-                                     info->snd_seq, OVS_DP_CMD_DEL);
+       reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_DEL);
        err = PTR_ERR(reply);
        if (IS_ERR(reply))
                goto unlock;
@@ -1328,8 +1353,9 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
        if (IS_ERR(dp))
                goto unlock;
 
-       reply = ovs_dp_cmd_build_info(dp, info->snd_portid,
-                                     info->snd_seq, OVS_DP_CMD_NEW);
+       ovs_dp_change(dp, info->attrs);
+
+       reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW);
        if (IS_ERR(reply)) {
                err = PTR_ERR(reply);
                genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0,
@@ -1360,8 +1386,7 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
                goto unlock;
        }
 
-       reply = ovs_dp_cmd_build_info(dp, info->snd_portid,
-                                     info->snd_seq, OVS_DP_CMD_NEW);
+       reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW);
        if (IS_ERR(reply)) {
                err = PTR_ERR(reply);
                goto unlock;
@@ -1441,7 +1466,7 @@ struct genl_family dp_vport_genl_family = {
        .parallel_ops = true,
 };
 
-struct genl_multicast_group ovs_dp_vport_multicast_group = {
+static struct genl_multicast_group ovs_dp_vport_multicast_group = {
        .name = OVS_VPORT_MCGROUP
 };
 
index 4067ea41be28d725c1312f2bb995df4e2c2209ab..6be9fbb5e9cbd57e11cce9ebac259d896db5a79c 100644 (file)
@@ -88,6 +88,8 @@ struct datapath {
        /* Network namespace ref. */
        struct net *net;
 #endif
+
+       u32 user_features;
 };
 
 /**
@@ -145,6 +147,8 @@ int lockdep_ovsl_is_held(void);
 #define ASSERT_OVSL()          WARN_ON(unlikely(!lockdep_ovsl_is_held()))
 #define ovsl_dereference(p)                                    \
        rcu_dereference_protected(p, lockdep_ovsl_is_held())
+#define rcu_dereference_ovsl(p)                                        \
+       rcu_dereference_check(p, lockdep_ovsl_is_held())
 
 static inline struct net *ovs_dp_get_net(struct datapath *dp)
 {
@@ -178,14 +182,12 @@ static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_n
 
 extern struct notifier_block ovs_dp_device_notifier;
 extern struct genl_family dp_vport_genl_family;
-extern struct genl_multicast_group ovs_dp_vport_multicast_group;
 
 void ovs_dp_process_received_packet(struct vport *, struct sk_buff *);
 void ovs_dp_detach_port(struct vport *);
 int ovs_dp_upcall(struct datapath *, struct sk_buff *,
                  const struct dp_upcall_info *);
 
-const char *ovs_dp_name(const struct datapath *dp);
 struct sk_buff *ovs_vport_cmd_build_info(struct vport *, u32 pid, u32 seq,
                                         u8 cmd);
 
index b409f527960178bdef6936361952a8d320d85859..16f4b46161d4fe2b806a46e895aa46922e2ce038 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/sctp.h>
+#include <linux/smp.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/icmp.h>
@@ -60,10 +61,16 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
 
 #define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF))
 
-void ovs_flow_used(struct sw_flow *flow, struct sk_buff *skb)
+void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
 {
+       struct flow_stats *stats;
        __be16 tcp_flags = 0;
 
+       if (!flow->stats.is_percpu)
+               stats = flow->stats.stat;
+       else
+               stats = this_cpu_ptr(flow->stats.cpu_stats);
+
        if ((flow->key.eth.type == htons(ETH_P_IP) ||
             flow->key.eth.type == htons(ETH_P_IPV6)) &&
            flow->key.ip.proto == IPPROTO_TCP &&
@@ -71,12 +78,87 @@ void ovs_flow_used(struct sw_flow *flow, struct sk_buff *skb)
                tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb));
        }
 
-       spin_lock(&flow->lock);
-       flow->used = jiffies;
-       flow->packet_count++;
-       flow->byte_count += skb->len;
-       flow->tcp_flags |= tcp_flags;
-       spin_unlock(&flow->lock);
+       spin_lock(&stats->lock);
+       stats->used = jiffies;
+       stats->packet_count++;
+       stats->byte_count += skb->len;
+       stats->tcp_flags |= tcp_flags;
+       spin_unlock(&stats->lock);
+}
+
+static void stats_read(struct flow_stats *stats,
+                      struct ovs_flow_stats *ovs_stats,
+                      unsigned long *used, __be16 *tcp_flags)
+{
+       spin_lock(&stats->lock);
+       if (time_after(stats->used, *used))
+               *used = stats->used;
+       *tcp_flags |= stats->tcp_flags;
+       ovs_stats->n_packets += stats->packet_count;
+       ovs_stats->n_bytes += stats->byte_count;
+       spin_unlock(&stats->lock);
+}
+
+void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats,
+                       unsigned long *used, __be16 *tcp_flags)
+{
+       int cpu, cur_cpu;
+
+       *used = 0;
+       *tcp_flags = 0;
+       memset(ovs_stats, 0, sizeof(*ovs_stats));
+
+       if (!flow->stats.is_percpu) {
+               stats_read(flow->stats.stat, ovs_stats, used, tcp_flags);
+       } else {
+               cur_cpu = get_cpu();
+               for_each_possible_cpu(cpu) {
+                       struct flow_stats *stats;
+
+                       if (cpu == cur_cpu)
+                               local_bh_disable();
+
+                       stats = per_cpu_ptr(flow->stats.cpu_stats, cpu);
+                       stats_read(stats, ovs_stats, used, tcp_flags);
+
+                       if (cpu == cur_cpu)
+                               local_bh_enable();
+               }
+               put_cpu();
+       }
+}
+
+static void stats_reset(struct flow_stats *stats)
+{
+       spin_lock(&stats->lock);
+       stats->used = 0;
+       stats->packet_count = 0;
+       stats->byte_count = 0;
+       stats->tcp_flags = 0;
+       spin_unlock(&stats->lock);
+}
+
+void ovs_flow_stats_clear(struct sw_flow *flow)
+{
+       int cpu, cur_cpu;
+
+       if (!flow->stats.is_percpu) {
+               stats_reset(flow->stats.stat);
+       } else {
+               cur_cpu = get_cpu();
+
+               for_each_possible_cpu(cpu) {
+
+                       if (cpu == cur_cpu)
+                               local_bh_disable();
+
+                       stats_reset(per_cpu_ptr(flow->stats.cpu_stats, cpu));
+
+                       if (cpu == cur_cpu)
+                               local_bh_enable();
+               }
+               put_cpu();
+       }
 }
 
 static int check_header(struct sk_buff *skb, int len)
index 1510f51dbf74b9f3850ac3ef39fc3ec5d31e6dd3..2d770e28a3a396f7da0a4c8e7baf4b29709ceb0c 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef FLOW_H
 #define FLOW_H 1
 
+#include <linux/cache.h>
 #include <linux/kernel.h>
 #include <linux/netlink.h>
 #include <linux/openvswitch.h>
@@ -122,8 +123,8 @@ struct sw_flow_key {
 } __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
 
 struct sw_flow_key_range {
-       size_t start;
-       size_t end;
+       unsigned short int start;
+       unsigned short int end;
 };
 
 struct sw_flow_mask {
@@ -146,6 +147,22 @@ struct sw_flow_actions {
        struct nlattr actions[];
 };
 
+struct flow_stats {
+       u64 packet_count;               /* Number of packets matched. */
+       u64 byte_count;                 /* Number of bytes matched. */
+       unsigned long used;             /* Last used time (in jiffies). */
+       spinlock_t lock;                /* Lock for atomic stats update. */
+       __be16 tcp_flags;               /* Union of seen TCP flags. */
+};
+
+struct sw_flow_stats {
+       bool is_percpu;
+       union {
+               struct flow_stats *stat;
+               struct flow_stats __percpu *cpu_stats;
+       };
+};
+
 struct sw_flow {
        struct rcu_head rcu;
        struct hlist_node hash_node[2];
@@ -155,12 +172,7 @@ struct sw_flow {
        struct sw_flow_key unmasked_key;
        struct sw_flow_mask *mask;
        struct sw_flow_actions __rcu *sf_acts;
-
-       spinlock_t lock;        /* Lock for values below. */
-       unsigned long used;     /* Last used time (in jiffies). */
-       u64 packet_count;       /* Number of packets matched. */
-       u64 byte_count;         /* Number of bytes matched. */
-       __be16 tcp_flags;       /* Union of seen TCP flags. */
+       struct sw_flow_stats stats;
 };
 
 struct arp_eth_header {
@@ -177,7 +189,10 @@ struct arp_eth_header {
        unsigned char       ar_tip[4];          /* target IP address        */
 } __packed;
 
-void ovs_flow_used(struct sw_flow *, struct sk_buff *);
+void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb);
+void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *stats,
+                       unsigned long *used, __be16 *tcp_flags);
+void ovs_flow_stats_clear(struct sw_flow *flow);
 u64 ovs_flow_used_time(unsigned long flow_jiffies);
 
 int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *);
index 2bc1bc1aca3bfc2fd149ba88c86b4eaf88aed00e..4d000acaed0db5cc2052ae55f5b0cb7be6472b79 100644 (file)
@@ -266,6 +266,20 @@ static bool is_all_zero(const u8 *fp, size_t size)
        return true;
 }
 
+static bool is_all_set(const u8 *fp, size_t size)
+{
+       int i;
+
+       if (!fp)
+               return false;
+
+       for (i = 0; i < size; i++)
+               if (fp[i] != 0xff)
+                       return false;
+
+       return true;
+}
+
 static int __parse_flow_nlattrs(const struct nlattr *attr,
                                const struct nlattr *a[],
                                u64 *attrsp, bool nz)
@@ -487,8 +501,9 @@ static int metadata_from_nlattrs(struct sw_flow_match *match,  u64 *attrs,
        return 0;
 }
 
-static int ovs_key_from_nlattrs(struct sw_flow_match *match,  u64 attrs,
-                               const struct nlattr **a, bool is_mask)
+static int ovs_key_from_nlattrs(struct sw_flow_match *match,  bool *exact_5tuple,
+                               u64 attrs, const struct nlattr **a,
+                               bool is_mask)
 {
        int err;
        u64 orig_attrs = attrs;
@@ -545,6 +560,11 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match,  u64 attrs,
                SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
        }
 
+       if (is_mask && exact_5tuple) {
+               if (match->mask->key.eth.type != htons(0xffff))
+                       *exact_5tuple = false;
+       }
+
        if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
                const struct ovs_key_ipv4 *ipv4_key;
 
@@ -567,6 +587,13 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match,  u64 attrs,
                SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
                                ipv4_key->ipv4_dst, is_mask);
                attrs &= ~(1 << OVS_KEY_ATTR_IPV4);
+
+               if (is_mask && exact_5tuple && *exact_5tuple) {
+                       if (ipv4_key->ipv4_proto != 0xff ||
+                           ipv4_key->ipv4_src != htonl(0xffffffff) ||
+                           ipv4_key->ipv4_dst != htonl(0xffffffff))
+                               *exact_5tuple = false;
+               }
        }
 
        if (attrs & (1 << OVS_KEY_ATTR_IPV6)) {
@@ -598,6 +625,13 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match,  u64 attrs,
                                is_mask);
 
                attrs &= ~(1 << OVS_KEY_ATTR_IPV6);
+
+               if (is_mask && exact_5tuple && *exact_5tuple) {
+                       if (ipv6_key->ipv6_proto != 0xff ||
+                           !is_all_set((u8 *)ipv6_key->ipv6_src, sizeof(match->key->ipv6.addr.src)) ||
+                           !is_all_set((u8 *)ipv6_key->ipv6_dst, sizeof(match->key->ipv6.addr.dst)))
+                               *exact_5tuple = false;
+               }
        }
 
        if (attrs & (1 << OVS_KEY_ATTR_ARP)) {
@@ -640,6 +674,11 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match,  u64 attrs,
                                        tcp_key->tcp_dst, is_mask);
                }
                attrs &= ~(1 << OVS_KEY_ATTR_TCP);
+
+               if (is_mask && exact_5tuple && *exact_5tuple &&
+                   (tcp_key->tcp_src != htons(0xffff) ||
+                    tcp_key->tcp_dst != htons(0xffff)))
+                       *exact_5tuple = false;
        }
 
        if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) {
@@ -671,6 +710,11 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match,  u64 attrs,
                                        udp_key->udp_dst, is_mask);
                }
                attrs &= ~(1 << OVS_KEY_ATTR_UDP);
+
+               if (is_mask && exact_5tuple && *exact_5tuple &&
+                   (udp_key->udp_src != htons(0xffff) ||
+                    udp_key->udp_dst != htons(0xffff)))
+                       *exact_5tuple = false;
        }
 
        if (attrs & (1 << OVS_KEY_ATTR_SCTP)) {
@@ -756,6 +800,7 @@ static void sw_flow_mask_set(struct sw_flow_mask *mask,
  * attribute specifies the mask field of the wildcarded flow.
  */
 int ovs_nla_get_match(struct sw_flow_match *match,
+                     bool *exact_5tuple,
                      const struct nlattr *key,
                      const struct nlattr *mask)
 {
@@ -803,10 +848,13 @@ int ovs_nla_get_match(struct sw_flow_match *match,
                }
        }
 
-       err = ovs_key_from_nlattrs(match, key_attrs, a, false);
+       err = ovs_key_from_nlattrs(match, NULL, key_attrs, a, false);
        if (err)
                return err;
 
+       if (exact_5tuple)
+               *exact_5tuple = true;
+
        if (mask) {
                err = parse_flow_mask_nlattrs(mask, a, &mask_attrs);
                if (err)
@@ -844,7 +892,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
                        }
                }
 
-               err = ovs_key_from_nlattrs(match, mask_attrs, a, true);
+               err = ovs_key_from_nlattrs(match, exact_5tuple, mask_attrs, a, true);
                if (err)
                        return err;
        } else {
@@ -1128,19 +1176,11 @@ struct sw_flow_actions *ovs_nla_alloc_flow_actions(int size)
        return sfa;
 }
 
-/* RCU callback used by ovs_nla_free_flow_actions. */
-static void rcu_free_acts_callback(struct rcu_head *rcu)
-{
-       struct sw_flow_actions *sf_acts = container_of(rcu,
-                       struct sw_flow_actions, rcu);
-       kfree(sf_acts);
-}
-
 /* Schedules 'sf_acts' to be freed after the next RCU grace period.
  * The caller must hold rcu_read_lock for this to be sensible. */
 void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
 {
-       call_rcu(&sf_acts->rcu, rcu_free_acts_callback);
+       kfree_rcu(sf_acts, rcu);
 }
 
 static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
index 440151045d3946329bf01e4fd5a1c81f0fd4e906..b31fbe28bc7a81a0640546b6e55be8841c32f8a5 100644 (file)
@@ -45,6 +45,7 @@ int ovs_nla_put_flow(const struct sw_flow_key *,
 int ovs_nla_get_flow_metadata(struct sw_flow *flow,
                              const struct nlattr *attr);
 int ovs_nla_get_match(struct sw_flow_match *match,
+                     bool *exact_5tuple,
                      const struct nlattr *,
                      const struct nlattr *);
 
index 0e720c31607059ec62313b75399dbf77267470e5..c58a0fe3c8892d4e09eb7377b60a06ae469efb09 100644 (file)
@@ -44,8 +44,6 @@
 #include <net/ipv6.h>
 #include <net/ndisc.h>
 
-#include "datapath.h"
-
 #define TBL_MIN_BUCKETS                1024
 #define REHASH_INTERVAL                (10 * 60 * HZ)
 
@@ -72,19 +70,42 @@ void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
                *d++ = *s++ & *m++;
 }
 
-struct sw_flow *ovs_flow_alloc(void)
+struct sw_flow *ovs_flow_alloc(bool percpu_stats)
 {
        struct sw_flow *flow;
+       int cpu;
 
        flow = kmem_cache_alloc(flow_cache, GFP_KERNEL);
        if (!flow)
                return ERR_PTR(-ENOMEM);
 
-       spin_lock_init(&flow->lock);
        flow->sf_acts = NULL;
        flow->mask = NULL;
 
+       flow->stats.is_percpu = percpu_stats;
+
+       if (!percpu_stats) {
+               flow->stats.stat = kzalloc(sizeof(*flow->stats.stat), GFP_KERNEL);
+               if (!flow->stats.stat)
+                       goto err;
+
+               spin_lock_init(&flow->stats.stat->lock);
+       } else {
+               flow->stats.cpu_stats = alloc_percpu(struct flow_stats);
+               if (!flow->stats.cpu_stats)
+                       goto err;
+
+               for_each_possible_cpu(cpu) {
+                       struct flow_stats *cpu_stats;
+
+                       cpu_stats = per_cpu_ptr(flow->stats.cpu_stats, cpu);
+                       spin_lock_init(&cpu_stats->lock);
+               }
+       }
        return flow;
+err:
+       kmem_cache_free(flow_cache, flow);
+       return ERR_PTR(-ENOMEM);
 }
 
 int ovs_flow_tbl_count(struct flow_table *table)
@@ -118,6 +139,10 @@ static struct flex_array *alloc_buckets(unsigned int n_buckets)
 static void flow_free(struct sw_flow *flow)
 {
        kfree((struct sf_flow_acts __force *)flow->sf_acts);
+       if (flow->stats.is_percpu)
+               free_percpu(flow->stats.cpu_stats);
+       else
+               kfree(flow->stats.stat);
        kmem_cache_free(flow_cache, flow);
 }
 
@@ -128,13 +153,6 @@ static void rcu_free_flow_callback(struct rcu_head *rcu)
        flow_free(flow);
 }
 
-static void rcu_free_sw_flow_mask_cb(struct rcu_head *rcu)
-{
-       struct sw_flow_mask *mask = container_of(rcu, struct sw_flow_mask, rcu);
-
-       kfree(mask);
-}
-
 static void flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred)
 {
        if (!mask)
@@ -146,7 +164,7 @@ static void flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred)
        if (!mask->ref_count) {
                list_del_rcu(&mask->list);
                if (deferred)
-                       call_rcu(&mask->rcu, rcu_free_sw_flow_mask_cb);
+                       kfree_rcu(mask, rcu);
                else
                        kfree(mask);
        }
@@ -429,11 +447,11 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
        return NULL;
 }
 
-struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
+struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *tbl,
                                    const struct sw_flow_key *key,
                                    u32 *n_mask_hit)
 {
-       struct table_instance *ti = rcu_dereference(tbl->ti);
+       struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
        struct sw_flow_mask *mask;
        struct sw_flow *flow;
 
@@ -447,6 +465,14 @@ struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
        return NULL;
 }
 
+struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
+                                   const struct sw_flow_key *key)
+{
+       u32 __always_unused n_mask_hit;
+
+       return ovs_flow_tbl_lookup_stats(tbl, key, &n_mask_hit);
+}
+
 int ovs_flow_tbl_num_masks(const struct flow_table *table)
 {
        struct sw_flow_mask *mask;
@@ -514,11 +540,7 @@ static struct sw_flow_mask *flow_mask_find(const struct flow_table *tbl,
        return NULL;
 }
 
-/**
- * add a new mask into the mask list.
- * The caller needs to make sure that 'mask' is not the same
- * as any masks that are already on the list.
- */
+/* Add 'mask' into the mask list, if it is not already there. */
 static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
                            struct sw_flow_mask *new)
 {
index fbe45d5ad07d6eca424dbf04fcd6870539648079..1996e34c0fd85b1a9f88c3e328fe191146be5b51 100644 (file)
@@ -55,7 +55,7 @@ struct flow_table {
 int ovs_flow_init(void);
 void ovs_flow_exit(void);
 
-struct sw_flow *ovs_flow_alloc(void);
+struct sw_flow *ovs_flow_alloc(bool percpu_stats);
 void ovs_flow_free(struct sw_flow *, bool deferred);
 
 int ovs_flow_tbl_init(struct flow_table *);
@@ -69,9 +69,11 @@ void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow);
 int  ovs_flow_tbl_num_masks(const struct flow_table *table);
 struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *table,
                                       u32 *bucket, u32 *idx);
-struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
+struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *,
                                    const struct sw_flow_key *,
                                    u32 *n_mask_hit);
+struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
+                                   const struct sw_flow_key *);
 
 bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
                               struct sw_flow_match *match);
index d830a95f03a4ba65ba755a3ff8dbf638700c9c68..208dd9a26dd16d003a0f49d4288f8704cbe15c8e 100644 (file)
@@ -33,6 +33,9 @@
 #include "vport.h"
 #include "vport-internal_dev.h"
 
+static void ovs_vport_record_error(struct vport *,
+                                  enum vport_err_type err_type);
+
 /* List of statically compiled vport implementations.  Don't forget to also
  * add yours to the list at the bottom of vport.h. */
 static const struct vport_ops *vport_ops_list[] = {
@@ -136,14 +139,14 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
        vport->ops = ops;
        INIT_HLIST_NODE(&vport->dp_hash_node);
 
-       vport->percpu_stats = alloc_percpu(struct pcpu_tstats);
+       vport->percpu_stats = alloc_percpu(struct pcpu_sw_netstats);
        if (!vport->percpu_stats) {
                kfree(vport);
                return ERR_PTR(-ENOMEM);
        }
 
        for_each_possible_cpu(i) {
-               struct pcpu_tstats *vport_stats;
+               struct pcpu_sw_netstats *vport_stats;
                vport_stats = per_cpu_ptr(vport->percpu_stats, i);
                u64_stats_init(&vport_stats->syncp);
        }
@@ -275,8 +278,8 @@ void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
        spin_unlock_bh(&vport->stats_lock);
 
        for_each_possible_cpu(i) {
-               const struct pcpu_tstats *percpu_stats;
-               struct pcpu_tstats local_stats;
+               const struct pcpu_sw_netstats *percpu_stats;
+               struct pcpu_sw_netstats local_stats;
                unsigned int start;
 
                percpu_stats = per_cpu_ptr(vport->percpu_stats, i);
@@ -344,7 +347,7 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
 void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
                       struct ovs_key_ipv4_tunnel *tun_key)
 {
-       struct pcpu_tstats *stats;
+       struct pcpu_sw_netstats *stats;
 
        stats = this_cpu_ptr(vport->percpu_stats);
        u64_stats_update_begin(&stats->syncp);
@@ -370,7 +373,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
        int sent = vport->ops->send(vport, skb);
 
        if (likely(sent > 0)) {
-               struct pcpu_tstats *stats;
+               struct pcpu_sw_netstats *stats;
 
                stats = this_cpu_ptr(vport->percpu_stats);
 
@@ -396,7 +399,8 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
  * If using the vport generic stats layer indicate that an error of the given
  * type has occurred.
  */
-void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type)
+static void ovs_vport_record_error(struct vport *vport,
+                                  enum vport_err_type err_type)
 {
        spin_lock(&vport->stats_lock);
 
index 1a9fbcec6e1bf9c1d9bc95a3ec9d711c02865a82..d7e50a17396c5563c778ca9e0e07f9c9a730b56a 100644 (file)
@@ -87,7 +87,7 @@ struct vport {
        struct hlist_node dp_hash_node;
        const struct vport_ops *ops;
 
-       struct pcpu_tstats __percpu *percpu_stats;
+       struct pcpu_sw_netstats __percpu *percpu_stats;
 
        spinlock_t stats_lock;
        struct vport_err_stats err_stats;
@@ -192,7 +192,6 @@ static inline struct vport *vport_from_priv(const void *priv)
 
 void ovs_vport_receive(struct vport *, struct sk_buff *,
                       struct ovs_key_ipv4_tunnel *);
-void ovs_vport_record_error(struct vport *, enum vport_err_type err_type);
 
 /* List of statically compiled vport implementations.  Don't forget to also
  * add yours to the list at the top of vport.c. */
index dd3840846ce2746ec6b1a0b9bc23005430e03433..279467b74eb70499586e21528842bc99efa1676e 100644 (file)
@@ -1356,9 +1356,9 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
        spin_unlock(&f->lock);
 }
 
-static bool match_fanout_group(struct packet_type *ptype, struct sock * sk)
+static bool match_fanout_group(struct packet_type *ptype, struct sock *sk)
 {
-       if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout)
+       if (ptype->af_packet_priv == (void *)((struct packet_sock *)sk)->fanout)
                return true;
 
        return false;
index b4c8b0022feeebea1aec424542e37a8391d87297..ba2dffeff60876ca669993d1863dcbb6cb76a740 100644 (file)
@@ -338,7 +338,8 @@ static int rds_ib_laddr_check(__be32 addr)
        ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
        /* due to this, we will claim to support iWARP devices unless we
           check node_type. */
-       if (ret || cm_id->device->node_type != RDMA_NODE_IB_CA)
+       if (ret || !cm_id->device ||
+           cm_id->device->node_type != RDMA_NODE_IB_CA)
                ret = -EADDRNOTAVAIL;
 
        rdsdebug("addr %pI4 ret %d node type %d\n",
index 33af77246bfeb90c6b31bfe6163dc2c9cfbda787..d080eb4b0d29c2ba81740ca1bacb16f6a25e063a 100644 (file)
@@ -1012,7 +1012,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
        make_rose->source_call   = facilities.source_call;
        make_rose->source_ndigis = facilities.source_ndigis;
        for (n = 0 ; n < facilities.source_ndigis ; n++)
-               make_rose->source_digis[n]= facilities.source_digis[n];
+               make_rose->source_digis[n] = facilities.source_digis[n];
        make_rose->neighbour     = neigh;
        make_rose->device        = dev;
        make_rose->facilities    = facilities;
@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (msg->msg_name) {
                struct sockaddr_rose *srose;
+               struct full_sockaddr_rose *full_srose = msg->msg_name;
 
                memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));
                srose = msg->msg_name;
@@ -1260,18 +1261,9 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
                srose->srose_addr   = rose->dest_addr;
                srose->srose_call   = rose->dest_call;
                srose->srose_ndigis = rose->dest_ndigis;
-               if (msg->msg_namelen >= sizeof(struct full_sockaddr_rose)) {
-                       struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)msg->msg_name;
-                       for (n = 0 ; n < rose->dest_ndigis ; n++)
-                               full_srose->srose_digis[n] = rose->dest_digis[n];
-                       msg->msg_namelen = sizeof(struct full_sockaddr_rose);
-               } else {
-                       if (rose->dest_ndigis >= 1) {
-                               srose->srose_ndigis = 1;
-                               srose->srose_digi = rose->dest_digis[0];
-                       }
-                       msg->msg_namelen = sizeof(struct sockaddr_rose);
-               }
+               for (n = 0 ; n < rose->dest_ndigis ; n++)
+                       full_srose->srose_digis[n] = rose->dest_digis[n];
+               msg->msg_namelen = sizeof(struct full_sockaddr_rose);
        }
 
        skb_free_datagram(sk, skb);
index 28dbdb911b85bf32909e822a27cb50a0edc67d82..50005888be573245fc1d30b8f38bc90b10c89698 100644 (file)
@@ -146,7 +146,7 @@ static netdev_tx_t rose_xmit(struct sk_buff *skb, struct net_device *dev)
 
 static const struct header_ops rose_header_ops = {
        .create = rose_header,
-       .rebuild= rose_rebuild_header,
+       .rebuild = rose_rebuild_header,
 };
 
 static const struct net_device_ops rose_netdev_ops = {
index 919847beec393c2eca68339cc2d48bb0f8e41fb5..a1a8e29e5fc995abdda1fe817ca40e12c85a8ecd 100644 (file)
@@ -295,6 +295,19 @@ config NET_SCH_HHF
          To compile this driver as a module, choose M here: the module
          will be called sch_hhf.
 
+config NET_SCH_PIE
+       tristate "Proportional Integral controller Enhanced (PIE) scheduler"
+       help
+         Say Y here if you want to use the Proportional Integral controller
+         Enhanced scheduler packet scheduling algorithm.
+         For more information, please see
+         http://tools.ietf.org/html/draft-pan-tsvwg-pie-00
+
+         To compile this driver as a module, choose M here: the module
+         will be called sch_pie.
+
+         If unsure, say N.
+
 config NET_SCH_INGRESS
        tristate "Ingress Qdisc"
        depends on NET_CLS_ACT
@@ -444,6 +457,7 @@ config NET_CLS_FLOW
 config NET_CLS_CGROUP
        tristate "Control Group Classifier"
        select NET_CLS
+       select CGROUP_NET_CLASSID
        depends on CGROUPS
        ---help---
          Say Y here if you want to classify packets based on the control
index 3442e5fbc4d776fa5b502877635901c8bdc04936..0a869a11f3e66cdd9c200541925e95cb311121ab 100644 (file)
@@ -41,6 +41,7 @@ obj-$(CONFIG_NET_SCH_CODEL)   += sch_codel.o
 obj-$(CONFIG_NET_SCH_FQ_CODEL) += sch_fq_codel.o
 obj-$(CONFIG_NET_SCH_FQ)       += sch_fq.o
 obj-$(CONFIG_NET_SCH_HHF)      += sch_hhf.o
+obj-$(CONFIG_NET_SCH_PIE)      += sch_pie.o
 
 obj-$(CONFIG_NET_CLS_U32)      += cls_u32.o
 obj-$(CONFIG_NET_CLS_ROUTE4)   += cls_route.o
index 8114fef308d97c9d05f7a0107f202fee47b9d55a..35f89e9ce49c2f9300c38a03ca0348e726331d29 100644 (file)
@@ -126,9 +126,10 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
        for (i = 0; i < (hinfo->hmask + 1); i++) {
                head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
                hlist_for_each_entry_safe(p, n, head, tcfc_head) {
-                       if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo))
+                       if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo)) {
                                module_put(a->ops->owner);
-                       n_i++;
+                               n_i++;
+                       }
                }
        }
        if (nla_put_u32(skb, TCA_FCNT, n_i))
@@ -141,8 +142,8 @@ nla_put_failure:
        return -EINVAL;
 }
 
-int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
-                      int type, struct tc_action *a)
+static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
+                             int type, struct tc_action *a)
 {
        struct tcf_hashinfo *hinfo = a->ops->hinfo;
 
@@ -155,7 +156,6 @@ int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
                return -EINVAL;
        }
 }
-EXPORT_SYMBOL(tcf_generic_walker);
 
 struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo)
 {
@@ -173,21 +173,21 @@ struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo)
 }
 EXPORT_SYMBOL(tcf_hash_lookup);
 
-u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo)
+u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo)
 {
-       u32 val = *idx_gen;
+       u32 val = hinfo->index;
 
        do {
                if (++val == 0)
                        val = 1;
        } while (tcf_hash_lookup(val, hinfo));
 
-       *idx_gen = val;
+       hinfo->index = val;
        return val;
 }
 EXPORT_SYMBOL(tcf_hash_new_index);
 
-int tcf_hash_search(struct tc_action *a, u32 index)
+static int tcf_hash_search(struct tc_action *a, u32 index)
 {
        struct tcf_hashinfo *hinfo = a->ops->hinfo;
        struct tcf_common *p = tcf_hash_lookup(index, hinfo);
@@ -198,7 +198,6 @@ int tcf_hash_search(struct tc_action *a, u32 index)
        }
        return 0;
 }
-EXPORT_SYMBOL(tcf_hash_search);
 
 struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind,
                                  struct tcf_hashinfo *hinfo)
@@ -216,7 +215,7 @@ EXPORT_SYMBOL(tcf_hash_check);
 
 struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
                                   struct tc_action *a, int size, int bind,
-                                  u32 *idx_gen, struct tcf_hashinfo *hinfo)
+                                  struct tcf_hashinfo *hinfo)
 {
        struct tcf_common *p = kzalloc(size, GFP_KERNEL);
 
@@ -228,7 +227,7 @@ struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
 
        spin_lock_init(&p->tcfc_lock);
        INIT_HLIST_NODE(&p->tcfc_head);
-       p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo);
+       p->tcfc_index = index ? index : tcf_hash_new_index(hinfo);
        p->tcfc_tm.install = jiffies;
        p->tcfc_tm.lastuse = jiffies;
        if (est) {
@@ -291,12 +290,12 @@ int tcf_unregister_action(struct tc_action_ops *act)
        int err = -ENOENT;
 
        write_lock(&act_mod_lock);
-       list_for_each_entry(a, &act_base, head)
-               if (a == act)
+       list_for_each_entry(a, &act_base, head) {
+               if (a == act) {
+                       list_del(&act->head);
+                       err = 0;
                        break;
-       if (a) {
-               list_del(&act->head);
-               err = 0;
+               }
        }
        write_unlock(&act_mod_lock);
        return err;
@@ -306,68 +305,41 @@ EXPORT_SYMBOL(tcf_unregister_action);
 /* lookup by name */
 static struct tc_action_ops *tc_lookup_action_n(char *kind)
 {
-       struct tc_action_ops *a = NULL;
+       struct tc_action_ops *a, *res = NULL;
 
        if (kind) {
                read_lock(&act_mod_lock);
                list_for_each_entry(a, &act_base, head) {
                        if (strcmp(kind, a->kind) == 0) {
-                               if (!try_module_get(a->owner)) {
-                                       read_unlock(&act_mod_lock);
-                                       return NULL;
-                               }
+                               if (try_module_get(a->owner))
+                                       res = a;
                                break;
                        }
                }
                read_unlock(&act_mod_lock);
        }
-       return a;
+       return res;
 }
 
 /* lookup by nlattr */
 static struct tc_action_ops *tc_lookup_action(struct nlattr *kind)
 {
-       struct tc_action_ops *a = NULL;
+       struct tc_action_ops *a, *res = NULL;
 
        if (kind) {
                read_lock(&act_mod_lock);
                list_for_each_entry(a, &act_base, head) {
                        if (nla_strcmp(kind, a->kind) == 0) {
-                               if (!try_module_get(a->owner)) {
-                                       read_unlock(&act_mod_lock);
-                                       return NULL;
-                               }
+                               if (try_module_get(a->owner))
+                                       res = a;
                                break;
                        }
                }
                read_unlock(&act_mod_lock);
        }
-       return a;
+       return res;
 }
 
-#if 0
-/* lookup by id */
-static struct tc_action_ops *tc_lookup_action_id(u32 type)
-{
-       struct tc_action_ops *a = NULL;
-
-       if (type) {
-               read_lock(&act_mod_lock);
-               for (a = act_base; a; a = a->next) {
-                       if (a->type == type) {
-                               if (!try_module_get(a->owner)) {
-                                       read_unlock(&act_mod_lock);
-                                       return NULL;
-                               }
-                               break;
-                       }
-               }
-               read_unlock(&act_mod_lock);
-       }
-       return a;
-}
-#endif
-
 int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
                    struct tcf_result *res)
 {
@@ -381,18 +353,16 @@ int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
        }
        list_for_each_entry(a, actions, list) {
 repeat:
-               if (a->ops) {
-                       ret = a->ops->act(skb, a, res);
-                       if (TC_MUNGED & skb->tc_verd) {
-                               /* copied already, allow trampling */
-                               skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
-                               skb->tc_verd = CLR_TC_MUNGED(skb->tc_verd);
-                       }
-                       if (ret == TC_ACT_REPEAT)
-                               goto repeat;    /* we need a ttl - JHS */
-                       if (ret != TC_ACT_PIPE)
-                               goto exec_done;
+               ret = a->ops->act(skb, a, res);
+               if (TC_MUNGED & skb->tc_verd) {
+                       /* copied already, allow trampling */
+                       skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
+                       skb->tc_verd = CLR_TC_MUNGED(skb->tc_verd);
                }
+               if (ret == TC_ACT_REPEAT)
+                       goto repeat;    /* we need a ttl - JHS */
+               if (ret != TC_ACT_PIPE)
+                       goto exec_done;
        }
 exec_done:
        return ret;
@@ -404,27 +374,16 @@ void tcf_action_destroy(struct list_head *actions, int bind)
        struct tc_action *a, *tmp;
 
        list_for_each_entry_safe(a, tmp, actions, list) {
-               if (a->ops) {
-                       if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
-                               module_put(a->ops->owner);
-                       list_del(&a->list);
-                       kfree(a);
-               } else {
-                       /*FIXME: Remove later - catch insertion bugs*/
-                       WARN(1, "tcf_action_destroy: BUG? destroying NULL ops\n");
-                       list_del(&a->list);
-                       kfree(a);
-               }
+               if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
+                       module_put(a->ops->owner);
+               list_del(&a->list);
+               kfree(a);
        }
 }
 
 int
 tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
-       int err = -EINVAL;
-
-       if (a->ops == NULL)
-               return err;
        return a->ops->dump(skb, a, bind, ref);
 }
 
@@ -435,9 +394,6 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
        unsigned char *b = skb_tail_pointer(skb);
        struct nlattr *nest;
 
-       if (a->ops == NULL)
-               return err;
-
        if (nla_put_string(skb, TCA_KIND, a->ops->kind))
                goto nla_put_failure;
        if (tcf_action_copy_stats(skb, a, 0))
@@ -600,9 +556,9 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
 {
        int err = 0;
        struct gnet_dump d;
-       struct tcf_act_hdr *h = a->priv;
+       struct tcf_common *p = a->priv;
 
-       if (h == NULL)
+       if (p == NULL)
                goto errout;
 
        /* compat_mode being true specifies a call that is supposed
@@ -611,20 +567,20 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
        if (compat_mode) {
                if (a->type == TCA_OLD_COMPAT)
                        err = gnet_stats_start_copy_compat(skb, 0,
-                               TCA_STATS, TCA_XSTATS, &h->tcf_lock, &d);
+                               TCA_STATS, TCA_XSTATS, &p->tcfc_lock, &d);
                else
                        return 0;
        } else
                err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
-                                           &h->tcf_lock, &d);
+                                           &p->tcfc_lock, &d);
 
        if (err < 0)
                goto errout;
 
-       if (gnet_stats_copy_basic(&d, &h->tcf_bstats) < 0 ||
-           gnet_stats_copy_rate_est(&d, &h->tcf_bstats,
-                                    &h->tcf_rate_est) < 0 ||
-           gnet_stats_copy_queue(&d, &h->tcf_qstats) < 0)
+       if (gnet_stats_copy_basic(&d, &p->tcfc_bstats) < 0 ||
+           gnet_stats_copy_rate_est(&d, &p->tcfc_bstats,
+                                    &p->tcfc_rate_est) < 0 ||
+           gnet_stats_copy_queue(&d, &p->tcfc_qstats) < 0)
                goto errout;
 
        if (gnet_stats_finish_copy(&d) < 0)
@@ -713,7 +669,7 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid)
        INIT_LIST_HEAD(&a->list);
        err = -EINVAL;
        a->ops = tc_lookup_action(tb[TCA_ACT_KIND]);
-       if (a->ops == NULL)
+       if (a->ops == NULL) /* could happen in batch of actions */
                goto err_free;
        err = -ENOENT;
        if (a->ops->lookup(a, index) == 0)
@@ -789,7 +745,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
        err = -EINVAL;
        kind = tb[TCA_ACT_KIND];
        a->ops = tc_lookup_action(kind);
-       if (a->ops == NULL)
+       if (a->ops == NULL) /*some idjot trying to flush unknown action */
                goto err_out;
 
        nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, sizeof(*t), 0);
@@ -832,6 +788,33 @@ noflush_out:
        return err;
 }
 
+static int
+tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
+              u32 portid)
+{
+       int ret;
+       struct sk_buff *skb;
+
+       skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+       if (!skb)
+               return -ENOBUFS;
+
+       if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
+                        0, 1) <= 0) {
+               kfree_skb(skb);
+               return -EINVAL;
+       }
+
+       /* now do the delete */
+       tcf_action_destroy(actions, 0);
+
+       ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
+                            n->nlmsg_flags & NLM_F_ECHO);
+       if (ret > 0)
+               return 0;
+       return ret;
+}
+
 static int
 tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
              u32 portid, int event)
@@ -865,27 +848,9 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
        if (event == RTM_GETACTION)
                ret = act_get_notify(net, portid, n, &actions, event);
        else { /* delete */
-               struct sk_buff *skb;
-
-               skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
-               if (!skb) {
-                       ret = -ENOBUFS;
+               ret = tcf_del_notify(net, n, &actions, portid);
+               if (ret)
                        goto err;
-               }
-
-               if (tca_get_fill(skb, &actions, portid, n->nlmsg_seq, 0, event,
-                                0, 1) <= 0) {
-                       kfree_skb(skb);
-                       ret = -EINVAL;
-                       goto err;
-               }
-
-               /* now do the delete */
-               tcf_action_destroy(&actions, 0);
-               ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
-                                    n->nlmsg_flags & NLM_F_ECHO);
-               if (ret > 0)
-                       return 0;
                return ret;
        }
 err:
@@ -893,60 +858,36 @@ err:
        return ret;
 }
 
-static int tcf_add_notify(struct net *net, struct list_head *actions,
-                         u32 portid, u32 seq, int event, u16 flags)
+static int
+tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
+              u32 portid)
 {
-       struct tcamsg *t;
-       struct nlmsghdr *nlh;
        struct sk_buff *skb;
-       struct nlattr *nest;
-       unsigned char *b;
        int err = 0;
 
        skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
        if (!skb)
                return -ENOBUFS;
 
-       b = skb_tail_pointer(skb);
-
-       nlh = nlmsg_put(skb, portid, seq, event, sizeof(*t), flags);
-       if (!nlh)
-               goto out_kfree_skb;
-       t = nlmsg_data(nlh);
-       t->tca_family = AF_UNSPEC;
-       t->tca__pad1 = 0;
-       t->tca__pad2 = 0;
-
-       nest = nla_nest_start(skb, TCA_ACT_TAB);
-       if (nest == NULL)
-               goto out_kfree_skb;
-
-       if (tcf_action_dump(skb, actions, 0, 0) < 0)
-               goto out_kfree_skb;
-
-       nla_nest_end(skb, nest);
-
-       nlh->nlmsg_len = skb_tail_pointer(skb) - b;
-       NETLINK_CB(skb).dst_group = RTNLGRP_TC;
+       if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
+                        RTM_NEWACTION, 0, 0) <= 0) {
+               kfree_skb(skb);
+               return -EINVAL;
+       }
 
-       err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, flags & NLM_F_ECHO);
+       err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
+                            n->nlmsg_flags & NLM_F_ECHO);
        if (err > 0)
                err = 0;
        return err;
-
-out_kfree_skb:
-       kfree_skb(skb);
-       return -1;
 }
 
-
 static int
 tcf_action_add(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
               u32 portid, int ovr)
 {
        int ret = 0;
        LIST_HEAD(actions);
-       u32 seq = n->nlmsg_seq;
 
        ret = tcf_action_init(net, nla, NULL, NULL, ovr, 0, &actions);
        if (ret)
@@ -955,7 +896,7 @@ tcf_action_add(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
        /* dump then free all the actions after update; inserted policy
         * stays intact
         */
-       ret = tcf_add_notify(net, &actions, portid, seq, RTM_NEWACTION, n->nlmsg_flags);
+       ret = tcf_add_notify(net, n, &actions, portid);
        cleanup_a(&actions);
 done:
        return ret;
index 5d350c57af3f2e24da0b48643613024382544ea4..ee28e1ccbbd5c50e43d57bd0d2feb3ee21e4a7a0 100644 (file)
@@ -37,7 +37,6 @@
 #include <net/tc_act/tc_csum.h>
 
 #define CSUM_TAB_MASK 15
-static u32 csum_idx_gen;
 static struct tcf_hashinfo csum_hash_info;
 
 static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
@@ -67,19 +66,19 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
        pc = tcf_hash_check(parm->index, a, bind, &csum_hash_info);
        if (!pc) {
                pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
-                                    &csum_idx_gen, &csum_hash_info);
+                                    &csum_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_csum(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_csum(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &csum_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &csum_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
+       p = to_tcf_csum(pc);
        spin_lock_bh(&p->tcf_lock);
        p->tcf_action = parm->action;
        p->update_flags = parm->update_flags;
@@ -586,7 +585,7 @@ MODULE_LICENSE("GPL");
 
 static int __init csum_init_module(void)
 {
-       int err = tcf_hashinfo_init(&csum_hash_info, CSUM_TAB_MASK+1);
+       int err = tcf_hashinfo_init(&csum_hash_info, CSUM_TAB_MASK);
        if (err)
                return err;
 
index 1e6e0e76524355f133ba1ae983d59d7b7b7e7dfc..f26e6b890cc7aefb35a4844f994e0a1a2d908fed 100644 (file)
@@ -24,7 +24,6 @@
 #include <net/tc_act/tc_gact.h>
 
 #define GACT_TAB_MASK  15
-static u32 gact_idx_gen;
 static struct tcf_hashinfo gact_hash_info;
 
 #ifdef CONFIG_GACT_PROB
@@ -90,15 +89,16 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
        pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info);
        if (!pc) {
                pc = tcf_hash_create(parm->index, est, a, sizeof(*gact),
-                                    bind, &gact_idx_gen, &gact_hash_info);
+                                    bind, &gact_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &gact_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &gact_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        gact = to_gact(pc);
@@ -208,7 +208,7 @@ MODULE_LICENSE("GPL");
 
 static int __init gact_init_module(void)
 {
-       int err = tcf_hashinfo_init(&gact_hash_info, GACT_TAB_MASK+1);
+       int err = tcf_hashinfo_init(&gact_hash_info, GACT_TAB_MASK);
        if (err)
                return err;
 #ifdef CONFIG_GACT_PROB
index 8344380ebaf1379a5d90d655c8ef8e0ee31e7555..484bd19601e36fdaa9df1d4e5c37d1b702ab5be6 100644 (file)
@@ -29,7 +29,6 @@
 
 
 #define IPT_TAB_MASK     15
-static u32 ipt_idx_gen;
 static struct tcf_hashinfo ipt_hash_info;
 
 static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int hook)
@@ -129,15 +128,17 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
        pc = tcf_hash_check(index, a, bind, &ipt_hash_info);
        if (!pc) {
                pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind,
-                                    &ipt_idx_gen, &ipt_hash_info);
+                                    &ipt_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_ipt_release(to_ipt(pc), bind);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_ipt_release(to_ipt(pc), bind);
+
+               if (!ovr)
                        return -EEXIST;
-               }
        }
        ipt = to_ipt(pc);
 
@@ -314,7 +315,7 @@ MODULE_ALIAS("act_xt");
 static int __init ipt_init_module(void)
 {
        int ret1, ret2, err;
-       err = tcf_hashinfo_init(&ipt_hash_info, IPT_TAB_MASK+1);
+       err = tcf_hashinfo_init(&ipt_hash_info, IPT_TAB_MASK);
        if (err)
                return err;
 
index 199fc9838af34022517996ed93fe182078412adb..5d05b573a6222fb4142af8120eb1276101101d4f 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/if_arp.h>
 
 #define MIRRED_TAB_MASK     7
-static u32 mirred_idx_gen;
 static LIST_HEAD(mirred_list);
 static struct tcf_hashinfo mirred_hash_info;
 
@@ -107,7 +106,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                if (dev == NULL)
                        return -EINVAL;
                pc = tcf_hash_create(parm->index, est, a, sizeof(*m), bind,
-                                    &mirred_idx_gen, &mirred_hash_info);
+                                    &mirred_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
@@ -276,7 +275,7 @@ static int __init mirred_init_module(void)
        if (err)
                return err;
 
-       err = tcf_hashinfo_init(&mirred_hash_info, MIRRED_TAB_MASK+1);
+       err = tcf_hashinfo_init(&mirred_hash_info, MIRRED_TAB_MASK);
        if (err) {
                unregister_netdevice_notifier(&mirred_device_notifier);
                return err;
@@ -287,9 +286,9 @@ static int __init mirred_init_module(void)
 
 static void __exit mirred_cleanup_module(void)
 {
-       unregister_netdevice_notifier(&mirred_device_notifier);
-       tcf_hashinfo_destroy(&mirred_hash_info);
        tcf_unregister_action(&act_mirred_ops);
+       tcf_hashinfo_destroy(&mirred_hash_info);
+       unregister_netdevice_notifier(&mirred_device_notifier);
 }
 
 module_init(mirred_init_module);
index 409fe7181c5fdaead8b868afaa769134f0d8bed1..a49fa23b49dd9f45e63dfccc6f64ac5f2077b4f4 100644 (file)
@@ -30,7 +30,6 @@
 
 
 #define NAT_TAB_MASK   15
-static u32 nat_idx_gen;
 
 static struct tcf_hashinfo nat_hash_info;
 
@@ -61,18 +60,18 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
        pc = tcf_hash_check(parm->index, a, bind, &nat_hash_info);
        if (!pc) {
                pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
-                                    &nat_idx_gen, &nat_hash_info);
+                                    &nat_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_nat(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_nat(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &nat_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &nat_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
+       p = to_tcf_nat(pc);
 
        spin_lock_bh(&p->tcf_lock);
        p->old_addr = parm->old_addr;
@@ -310,7 +309,7 @@ MODULE_LICENSE("GPL");
 
 static int __init nat_init_module(void)
 {
-       int err = tcf_hashinfo_init(&nat_hash_info, NAT_TAB_MASK+1);
+       int err = tcf_hashinfo_init(&nat_hash_info, NAT_TAB_MASK);
        if (err)
                return err;
        return tcf_register_action(&act_nat_ops);
index aa5347c1b9f179190e69c33558b0913c73e49be4..f361e4e3c314150e7b9eac377be80540c8a799bb 100644 (file)
@@ -24,7 +24,6 @@
 #include <net/tc_act/tc_pedit.h>
 
 #define PEDIT_TAB_MASK 15
-static u32 pedit_idx_gen;
 
 static struct tcf_hashinfo pedit_hash_info;
 
@@ -63,7 +62,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                if (!parm->nkeys)
                        return -EINVAL;
                pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
-                                    &pedit_idx_gen, &pedit_hash_info);
+                                    &pedit_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
                p = to_pedit(pc);
@@ -78,10 +77,12 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                p = to_pedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &pedit_hash_info);
+               tcf_hash_release(pc, bind, &pedit_hash_info);
+               if (bind)
+                       return 0;
+               if (!ovr)
                        return -EEXIST;
-               }
+
                if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
                        keys = kmalloc(ksize, GFP_KERNEL);
                        if (keys == NULL)
@@ -246,7 +247,7 @@ MODULE_LICENSE("GPL");
 
 static int __init pedit_init_module(void)
 {
-       int err = tcf_hashinfo_init(&pedit_hash_info, PEDIT_TAB_MASK+1);
+       int err = tcf_hashinfo_init(&pedit_hash_info, PEDIT_TAB_MASK);
        if (err)
                return err;
        return tcf_register_action(&act_pedit_ops);
index 7b23ab07c6cc19bfb3d3fa0e028f50bbda3cdbc8..a719fdff575eaa0917f06ceec76237c50f78175e 100644 (file)
@@ -41,7 +41,6 @@ struct tcf_police {
        container_of(pc, struct tcf_police, common)
 
 #define POL_TAB_MASK     15
-static u32 police_idx_gen;
 static struct tcf_hashinfo police_hash_info;
 
 /* old policer structure from before tc actions */
@@ -162,10 +161,12 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
                        if (bind) {
                                police->tcf_bindcnt += 1;
                                police->tcf_refcnt += 1;
+                               return 0;
                        }
                        if (ovr)
                                goto override;
-                       return ret;
+                       /* not replacing */
+                       return -EEXIST;
                }
        }
 
@@ -249,7 +250,7 @@ override:
 
        police->tcfp_t_c = ktime_to_ns(ktime_get());
        police->tcf_index = parm->index ? parm->index :
-               tcf_hash_new_index(&police_idx_gen, &police_hash_info);
+               tcf_hash_new_index(&police_hash_info);
        h = tcf_hash(police->tcf_index, POL_TAB_MASK);
        spin_lock_bh(&police_hash_info.lock);
        hlist_add_head(&police->tcf_head, &police_hash_info.htab[h]);
@@ -396,7 +397,7 @@ static struct tc_action_ops act_police_ops = {
 static int __init
 police_init_module(void)
 {
-       int err = tcf_hashinfo_init(&police_hash_info, POL_TAB_MASK+1);
+       int err = tcf_hashinfo_init(&police_hash_info, POL_TAB_MASK);
        if (err)
                return err;
        err = tcf_register_action(&act_police_ops);
index 2d7a0eb11c6935f20c89be58da18d4871dfa0bbf..f7d5406c1fe27a3b871af63983d10a6f461ce77c 100644 (file)
@@ -25,7 +25,6 @@
 #include <net/tc_act/tc_defact.h>
 
 #define SIMP_TAB_MASK     7
-static u32 simp_idx_gen;
 static struct tcf_hashinfo simp_hash_info;
 
 #define SIMP_MAX_DATA  32
@@ -118,7 +117,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
        pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info);
        if (!pc) {
                pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind,
-                                    &simp_idx_gen, &simp_hash_info);
+                                    &simp_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
 
@@ -135,10 +134,13 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_defact(pc);
-               if (!ovr) {
-                       tcf_simp_release(d, bind);
+
+               if (bind)
+                       return 0;
+               tcf_simp_release(d, bind);
+               if (!ovr)
                        return -EEXIST;
-               }
+
                reset_policy(d, defdata, parm);
        }
 
@@ -203,7 +205,7 @@ MODULE_LICENSE("GPL");
 static int __init simp_init_module(void)
 {
        int err, ret;
-       err = tcf_hashinfo_init(&simp_hash_info, SIMP_TAB_MASK+1);
+       err = tcf_hashinfo_init(&simp_hash_info, SIMP_TAB_MASK);
        if (err)
                return err;
 
index 90ed04a83cf30d0f51b7b65562825a43d7c99d66..74af4612706000940f2210e9b01ed53990691844 100644 (file)
@@ -28,7 +28,6 @@
 #include <net/tc_act/tc_skbedit.h>
 
 #define SKBEDIT_TAB_MASK     15
-static u32 skbedit_idx_gen;
 static struct tcf_hashinfo skbedit_hash_info;
 
 static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
@@ -104,7 +103,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
        pc = tcf_hash_check(parm->index, a, bind, &skbedit_hash_info);
        if (!pc) {
                pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind,
-                                    &skbedit_idx_gen, &skbedit_hash_info);
+                                    &skbedit_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
 
@@ -112,10 +111,11 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_skbedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        spin_lock_bh(&d->tcf_lock);
@@ -203,7 +203,7 @@ MODULE_LICENSE("GPL");
 
 static int __init skbedit_init_module(void)
 {
-       int err = tcf_hashinfo_init(&skbedit_hash_info, SKBEDIT_TAB_MASK+1);
+       int err = tcf_hashinfo_init(&skbedit_hash_info, SKBEDIT_TAB_MASK);
        if (err)
                return err;
        return tcf_register_action(&act_skbedit_ops);
index 6b085cf27a65cfbbdcf319c061ce23c174ac4fbe..29a30a14c31596cc51028be8db46eb4df9756f6e 100644 (file)
@@ -40,20 +40,20 @@ static DEFINE_RWLOCK(cls_mod_lock);
 
 static const struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind)
 {
-       const struct tcf_proto_ops *t = NULL;
+       const struct tcf_proto_ops *t, *res = NULL;
 
        if (kind) {
                read_lock(&cls_mod_lock);
                list_for_each_entry(t, &tcf_proto_base, head) {
                        if (nla_strcmp(kind, t->kind) == 0) {
-                               if (!try_module_get(t->owner))
-                                       t = NULL;
+                               if (try_module_get(t->owner))
+                                       res = t;
                                break;
                        }
                }
                read_unlock(&cls_mod_lock);
        }
-       return t;
+       return res;
 }
 
 /* Register(unregister) new classifier type */
@@ -82,15 +82,13 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops)
        int rc = -ENOENT;
 
        write_lock(&cls_mod_lock);
-       list_for_each_entry(t, &tcf_proto_base, head)
-               if (t == ops)
+       list_for_each_entry(t, &tcf_proto_base, head) {
+               if (t == ops) {
+                       list_del(&t->head);
+                       rc = 0;
                        break;
-
-       if (!t)
-               goto out;
-       list_del(&t->head);
-       rc = 0;
-out:
+               }
+       }
        write_unlock(&cls_mod_lock);
        return rc;
 }
@@ -342,7 +340,7 @@ errout:
        return err;
 }
 
-static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
+static int tcf_fill_node(struct net *net, struct sk_buff *skb, struct tcf_proto *tp,
                         unsigned long fh, u32 portid, u32 seq, u16 flags, int event)
 {
        struct tcmsg *tcm;
@@ -364,7 +362,7 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
        tcm->tcm_handle = fh;
        if (RTM_DELTFILTER != event) {
                tcm->tcm_handle = 0;
-               if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0)
+               if (tp->ops->dump && tp->ops->dump(net, tp, fh, skb, tcm) < 0)
                        goto nla_put_failure;
        }
        nlh->nlmsg_len = skb_tail_pointer(skb) - b;
@@ -387,7 +385,7 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb,
        if (!skb)
                return -ENOBUFS;
 
-       if (tcf_fill_node(skb, tp, fh, portid, n->nlmsg_seq, 0, event) <= 0) {
+       if (tcf_fill_node(net, skb, tp, fh, portid, n->nlmsg_seq, 0, event) <= 0) {
                kfree_skb(skb);
                return -EINVAL;
        }
@@ -406,8 +404,9 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n,
                         struct tcf_walker *arg)
 {
        struct tcf_dump_args *a = (void *)arg;
+       struct net *net = sock_net(a->skb->sk);
 
-       return tcf_fill_node(a->skb, tp, n, NETLINK_CB(a->cb->skb).portid,
+       return tcf_fill_node(net, a->skb, tp, n, NETLINK_CB(a->cb->skb).portid,
                             a->cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWTFILTER);
 }
 
@@ -465,7 +464,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
                if (t > s_t)
                        memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
                if (cb->args[1] == 0) {
-                       if (tcf_fill_node(skb, tp, 0, NETLINK_CB(cb->skb).portid,
+                       if (tcf_fill_node(net, skb, tp, 0, NETLINK_CB(cb->skb).portid,
                                          cb->nlh->nlmsg_seq, NLM_F_MULTI,
                                          RTM_NEWTFILTER) <= 0)
                                break;
@@ -579,7 +578,7 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts)
                } else if (exts->police) {
                        struct tc_action *act = tcf_exts_first_act(exts);
                        nest = nla_nest_start(skb, exts->police);
-                       if (nest == NULL)
+                       if (nest == NULL || !act)
                                goto nla_put_failure;
                        if (tcf_action_dump_old(skb, act, 0, 0) < 0)
                                goto nla_put_failure;
index b6552035d1f4947ca88754b727d8930b6ead35de..e98ca99c202bb5af6db77260f0996e6cacb098cf 100644 (file)
@@ -38,7 +38,7 @@ static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                          struct tcf_result *res)
 {
        int r;
-       struct basic_head *head = (struct basic_head *) tp->root;
+       struct basic_head *head = tp->root;
        struct basic_filter *f;
 
        list_for_each_entry(f, &head->flist, link) {
@@ -56,7 +56,7 @@ static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 static unsigned long basic_get(struct tcf_proto *tp, u32 handle)
 {
        unsigned long l = 0UL;
-       struct basic_head *head = (struct basic_head *) tp->root;
+       struct basic_head *head = tp->root;
        struct basic_filter *f;
 
        if (head == NULL)
@@ -107,7 +107,7 @@ static void basic_destroy(struct tcf_proto *tp)
 
 static int basic_delete(struct tcf_proto *tp, unsigned long arg)
 {
-       struct basic_head *head = (struct basic_head *) tp->root;
+       struct basic_head *head = tp->root;
        struct basic_filter *t, *f = (struct basic_filter *) arg;
 
        list_for_each_entry(t, &head->flist, link)
@@ -164,7 +164,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
                        struct nlattr **tca, unsigned long *arg)
 {
        int err;
-       struct basic_head *head = (struct basic_head *) tp->root;
+       struct basic_head *head = tp->root;
        struct nlattr *tb[TCA_BASIC_MAX + 1];
        struct basic_filter *f = (struct basic_filter *) *arg;
 
@@ -225,7 +225,7 @@ errout:
 
 static void basic_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 {
-       struct basic_head *head = (struct basic_head *) tp->root;
+       struct basic_head *head = tp->root;
        struct basic_filter *f;
 
        list_for_each_entry(f, &head->flist, link) {
@@ -241,7 +241,7 @@ skip:
        }
 }
 
-static int basic_dump(struct tcf_proto *tp, unsigned long fh,
+static int basic_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
                      struct sk_buff *skb, struct tcmsg *t)
 {
        struct basic_filter *f = (struct basic_filter *) fh;
index 00a5a585e5f1b6a26572bc21cd5b05221470ac49..8e3cf49118e3a2297214de12313bb499cbfe9054 100644 (file)
@@ -295,7 +295,7 @@ errout:
        return ret;
 }
 
-static int cls_bpf_dump(struct tcf_proto *tp, unsigned long fh,
+static int cls_bpf_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
                        struct sk_buff *skb, struct tcmsg *tm)
 {
        struct cls_bpf_prog *prog = (struct cls_bpf_prog *) fh;
index f9d212583ea2a3f9d4bf4f30df6a0b3c9ecd5036..8e2158ab551c0c9d7258ffae3e474788bfc64565 100644 (file)
 
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/errno.h>
 #include <linux/skbuff.h>
-#include <linux/cgroup.h>
 #include <linux/rcupdate.h>
-#include <linux/fdtable.h>
 #include <net/rtnetlink.h>
 #include <net/pkt_cls.h>
 #include <net/sock.h>
 #include <net/cls_cgroup.h>
 
-static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css)
-{
-       return css ? container_of(css, struct cgroup_cls_state, css) : NULL;
-}
-
-static inline struct cgroup_cls_state *task_cls_state(struct task_struct *p)
-{
-       return css_cls_state(task_css(p, net_cls_subsys_id));
-}
-
-static struct cgroup_subsys_state *
-cgrp_css_alloc(struct cgroup_subsys_state *parent_css)
-{
-       struct cgroup_cls_state *cs;
-
-       cs = kzalloc(sizeof(*cs), GFP_KERNEL);
-       if (!cs)
-               return ERR_PTR(-ENOMEM);
-       return &cs->css;
-}
-
-static int cgrp_css_online(struct cgroup_subsys_state *css)
-{
-       struct cgroup_cls_state *cs = css_cls_state(css);
-       struct cgroup_cls_state *parent = css_cls_state(css_parent(css));
-
-       if (parent)
-               cs->classid = parent->classid;
-       return 0;
-}
-
-static void cgrp_css_free(struct cgroup_subsys_state *css)
-{
-       kfree(css_cls_state(css));
-}
-
-static int update_classid(const void *v, struct file *file, unsigned n)
-{
-       int err;
-       struct socket *sock = sock_from_file(file, &err);
-       if (sock)
-               sock->sk->sk_classid = (u32)(unsigned long)v;
-       return 0;
-}
-
-static void cgrp_attach(struct cgroup_subsys_state *css,
-                       struct cgroup_taskset *tset)
-{
-       struct task_struct *p;
-       struct cgroup_cls_state *cs = css_cls_state(css);
-       void *v = (void *)(unsigned long)cs->classid;
-
-       cgroup_taskset_for_each(p, css, tset) {
-               task_lock(p);
-               iterate_fd(p->files, 0, update_classid, v);
-               task_unlock(p);
-       }
-}
-
-static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
-{
-       return css_cls_state(css)->classid;
-}
-
-static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
-                        u64 value)
-{
-       css_cls_state(css)->classid = (u32) value;
-       return 0;
-}
-
-static struct cftype ss_files[] = {
-       {
-               .name = "classid",
-               .read_u64 = read_classid,
-               .write_u64 = write_classid,
-       },
-       { }     /* terminate */
-};
-
-struct cgroup_subsys net_cls_subsys = {
-       .name           = "net_cls",
-       .css_alloc      = cgrp_css_alloc,
-       .css_online     = cgrp_css_online,
-       .css_free       = cgrp_css_free,
-       .attach         = cgrp_attach,
-       .subsys_id      = net_cls_subsys_id,
-       .base_cftypes   = ss_files,
-       .module         = THIS_MODULE,
-};
-
 struct cls_cgroup_head {
        u32                     handle;
        struct tcf_exts         exts;
@@ -260,7 +164,7 @@ skip:
        arg->count++;
 }
 
-static int cls_cgroup_dump(struct tcf_proto *tp, unsigned long fh,
+static int cls_cgroup_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
                           struct sk_buff *skb, struct tcmsg *t)
 {
        struct cls_cgroup_head *head = tp->root;
@@ -305,25 +209,12 @@ static struct tcf_proto_ops cls_cgroup_ops __read_mostly = {
 
 static int __init init_cgroup_cls(void)
 {
-       int ret;
-
-       ret = cgroup_load_subsys(&net_cls_subsys);
-       if (ret)
-               goto out;
-
-       ret = register_tcf_proto_ops(&cls_cgroup_ops);
-       if (ret)
-               cgroup_unload_subsys(&net_cls_subsys);
-
-out:
-       return ret;
+       return register_tcf_proto_ops(&cls_cgroup_ops);
 }
 
 static void __exit exit_cgroup_cls(void)
 {
        unregister_tcf_proto_ops(&cls_cgroup_ops);
-
-       cgroup_unload_subsys(&net_cls_subsys);
 }
 
 module_init(init_cgroup_cls);
index dfd18a5c3e817037a50f3a5de92e3ac04e34095b..257029c5433298f62101533ada3a81c246eb0d7a 100644 (file)
@@ -563,7 +563,7 @@ static void flow_put(struct tcf_proto *tp, unsigned long f)
 {
 }
 
-static int flow_dump(struct tcf_proto *tp, unsigned long fh,
+static int flow_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
                     struct sk_buff *skb, struct tcmsg *t)
 {
        struct flow_filter *f = (struct flow_filter *)fh;
index 3f9cece13807992ca2faf56252beb14d0d42bdbf..ed00e8c21ceaa8bb0f2fb1c8d44ba872b5d2e9d1 100644 (file)
@@ -41,7 +41,7 @@ struct fw_filter {
        u32                     id;
        struct tcf_result       res;
 #ifdef CONFIG_NET_CLS_IND
-       char                    indev[IFNAMSIZ];
+       int                     ifindex;
 #endif /* CONFIG_NET_CLS_IND */
        struct tcf_exts         exts;
 };
@@ -75,7 +75,7 @@ static inline int fw_hash(u32 handle)
 static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                          struct tcf_result *res)
 {
-       struct fw_head *head = (struct fw_head *)tp->root;
+       struct fw_head *head = tp->root;
        struct fw_filter *f;
        int r;
        u32 id = skb->mark;
@@ -86,7 +86,7 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                        if (f->id == id) {
                                *res = f->res;
 #ifdef CONFIG_NET_CLS_IND
-                               if (!tcf_match_indev(skb, f->indev))
+                               if (!tcf_match_indev(skb, f->ifindex))
                                        continue;
 #endif /* CONFIG_NET_CLS_IND */
                                r = tcf_exts_exec(skb, &f->exts, res);
@@ -111,7 +111,7 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 
 static unsigned long fw_get(struct tcf_proto *tp, u32 handle)
 {
-       struct fw_head *head = (struct fw_head *)tp->root;
+       struct fw_head *head = tp->root;
        struct fw_filter *f;
 
        if (head == NULL)
@@ -160,7 +160,7 @@ static void fw_destroy(struct tcf_proto *tp)
 
 static int fw_delete(struct tcf_proto *tp, unsigned long arg)
 {
-       struct fw_head *head = (struct fw_head *)tp->root;
+       struct fw_head *head = tp->root;
        struct fw_filter *f = (struct fw_filter *)arg;
        struct fw_filter **fp;
 
@@ -190,7 +190,7 @@ static int
 fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
        struct nlattr **tb, struct nlattr **tca, unsigned long base)
 {
-       struct fw_head *head = (struct fw_head *)tp->root;
+       struct fw_head *head = tp->root;
        struct tcf_exts e;
        u32 mask;
        int err;
@@ -207,9 +207,11 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
 
 #ifdef CONFIG_NET_CLS_IND
        if (tb[TCA_FW_INDEV]) {
-               err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV]);
-               if (err < 0)
+               int ret;
+               ret = tcf_change_indev(net, tb[TCA_FW_INDEV]);
+               if (ret < 0)
                        goto errout;
+               f->ifindex = ret;
        }
 #endif /* CONFIG_NET_CLS_IND */
 
@@ -235,7 +237,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
                     struct nlattr **tca,
                     unsigned long *arg)
 {
-       struct fw_head *head = (struct fw_head *)tp->root;
+       struct fw_head *head = tp->root;
        struct fw_filter *f = (struct fw_filter *) *arg;
        struct nlattr *opt = tca[TCA_OPTIONS];
        struct nlattr *tb[TCA_FW_MAX + 1];
@@ -298,7 +300,7 @@ errout:
 
 static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 {
-       struct fw_head *head = (struct fw_head *)tp->root;
+       struct fw_head *head = tp->root;
        int h;
 
        if (head == NULL)
@@ -324,10 +326,10 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
        }
 }
 
-static int fw_dump(struct tcf_proto *tp, unsigned long fh,
+static int fw_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
                   struct sk_buff *skb, struct tcmsg *t)
 {
-       struct fw_head *head = (struct fw_head *)tp->root;
+       struct fw_head *head = tp->root;
        struct fw_filter *f = (struct fw_filter *)fh;
        unsigned char *b = skb_tail_pointer(skb);
        struct nlattr *nest;
@@ -348,9 +350,12 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
            nla_put_u32(skb, TCA_FW_CLASSID, f->res.classid))
                goto nla_put_failure;
 #ifdef CONFIG_NET_CLS_IND
-       if (strlen(f->indev) &&
-           nla_put_string(skb, TCA_FW_INDEV, f->indev))
-               goto nla_put_failure;
+       if (f->ifindex) {
+               struct net_device *dev;
+               dev = __dev_get_by_index(net, f->ifindex);
+               if (dev && nla_put_string(skb, TCA_FW_INDEV, dev->name))
+                       goto nla_put_failure;
+       }
 #endif /* CONFIG_NET_CLS_IND */
        if (head->mask != 0xFFFFFFFF &&
            nla_put_u32(skb, TCA_FW_MASK, head->mask))
index 2473953a5948b3877f7a215373fe558b8a63112c..1ad3068f2ce16e2c6ba15985c40cf899a7030ba7 100644 (file)
@@ -123,7 +123,7 @@ static inline int route4_hash_wild(void)
 static int route4_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                           struct tcf_result *res)
 {
-       struct route4_head *head = (struct route4_head *)tp->root;
+       struct route4_head *head = tp->root;
        struct dst_entry *dst;
        struct route4_bucket *b;
        struct route4_filter *f;
@@ -213,7 +213,7 @@ static inline u32 from_hash(u32 id)
 
 static unsigned long route4_get(struct tcf_proto *tp, u32 handle)
 {
-       struct route4_head *head = (struct route4_head *)tp->root;
+       struct route4_head *head = tp->root;
        struct route4_bucket *b;
        struct route4_filter *f;
        unsigned int h1, h2;
@@ -284,7 +284,7 @@ static void route4_destroy(struct tcf_proto *tp)
 
 static int route4_delete(struct tcf_proto *tp, unsigned long arg)
 {
-       struct route4_head *head = (struct route4_head *)tp->root;
+       struct route4_head *head = tp->root;
        struct route4_filter **fp, *f = (struct route4_filter *)arg;
        unsigned int h = 0;
        struct route4_bucket *b;
@@ -551,7 +551,7 @@ static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg)
        }
 }
 
-static int route4_dump(struct tcf_proto *tp, unsigned long fh,
+static int route4_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
                       struct sk_buff *skb, struct tcmsg *t)
 {
        struct route4_filter *f = (struct route4_filter *)fh;
index 4f25c2ac825b706b8275106f904180295fcce7ed..19f8e5dfa8bdaebcd9ab903050047e7e49690530 100644 (file)
@@ -594,7 +594,7 @@ static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg)
        }
 }
 
-static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
+static int rsvp_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
                     struct sk_buff *skb, struct tcmsg *t)
 {
        struct rsvp_filter *f = (struct rsvp_filter *)fh;
index ffad18791c930dd8e2f34624ce0ce35d82a95bc0..eed8404443d8f0145942c3e459b79934ada9c48d 100644 (file)
@@ -24,9 +24,6 @@
 #define DEFAULT_HASH_SIZE      64      /* optimized for diffserv */
 
 
-#define        PRIV(tp)        ((struct tcindex_data *) (tp)->root)
-
-
 struct tcindex_filter_result {
        struct tcf_exts         exts;
        struct tcf_result       res;
@@ -77,7 +74,7 @@ tcindex_lookup(struct tcindex_data *p, u16 key)
 static int tcindex_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                            struct tcf_result *res)
 {
-       struct tcindex_data *p = PRIV(tp);
+       struct tcindex_data *p = tp->root;
        struct tcindex_filter_result *f;
        int key = (skb->tc_index & p->mask) >> p->shift;
 
@@ -102,7 +99,7 @@ static int tcindex_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 
 static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
 {
-       struct tcindex_data *p = PRIV(tp);
+       struct tcindex_data *p = tp->root;
        struct tcindex_filter_result *r;
 
        pr_debug("tcindex_get(tp %p,handle 0x%08x)\n", tp, handle);
@@ -140,7 +137,7 @@ static int tcindex_init(struct tcf_proto *tp)
 static int
 __tcindex_delete(struct tcf_proto *tp, unsigned long arg, int lock)
 {
-       struct tcindex_data *p = PRIV(tp);
+       struct tcindex_data *p = tp->root;
        struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg;
        struct tcindex_filter *f = NULL;
 
@@ -338,7 +335,7 @@ tcindex_change(struct net *net, struct sk_buff *in_skb,
 {
        struct nlattr *opt = tca[TCA_OPTIONS];
        struct nlattr *tb[TCA_TCINDEX_MAX + 1];
-       struct tcindex_data *p = PRIV(tp);
+       struct tcindex_data *p = tp->root;
        struct tcindex_filter_result *r = (struct tcindex_filter_result *) *arg;
        int err;
 
@@ -360,7 +357,7 @@ tcindex_change(struct net *net, struct sk_buff *in_skb,
 
 static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
 {
-       struct tcindex_data *p = PRIV(tp);
+       struct tcindex_data *p = tp->root;
        struct tcindex_filter *f, *next;
        int i;
 
@@ -407,7 +404,7 @@ static int tcindex_destroy_element(struct tcf_proto *tp,
 
 static void tcindex_destroy(struct tcf_proto *tp)
 {
-       struct tcindex_data *p = PRIV(tp);
+       struct tcindex_data *p = tp->root;
        struct tcf_walker walker;
 
        pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p);
@@ -422,10 +419,10 @@ static void tcindex_destroy(struct tcf_proto *tp)
 }
 
 
-static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
+static int tcindex_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
     struct sk_buff *skb, struct tcmsg *t)
 {
-       struct tcindex_data *p = PRIV(tp);
+       struct tcindex_data *p = tp->root;
        struct tcindex_filter_result *r = (struct tcindex_filter_result *) fh;
        unsigned char *b = skb_tail_pointer(skb);
        struct nlattr *nest;
index 20f2fb79c74746ea0ce2d31b2b65290d2064420b..84c28daff8484f643e5bed4176f6b225eec34e66 100644 (file)
@@ -48,7 +48,7 @@ struct tc_u_knode {
        struct tc_u_hnode       *ht_up;
        struct tcf_exts         exts;
 #ifdef CONFIG_NET_CLS_IND
-       char                     indev[IFNAMSIZ];
+       int                     ifindex;
 #endif
        u8                      fshift;
        struct tcf_result       res;
@@ -95,7 +95,7 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct
                unsigned int      off;
        } stack[TC_U32_MAXDEPTH];
 
-       struct tc_u_hnode *ht = (struct tc_u_hnode *)tp->root;
+       struct tc_u_hnode *ht = tp->root;
        unsigned int off = skb_network_offset(skb);
        struct tc_u_knode *n;
        int sdepth = 0;
@@ -152,7 +152,7 @@ check_terminal:
 
                                *res = n->res;
 #ifdef CONFIG_NET_CLS_IND
-                               if (!tcf_match_indev(skb, n->indev)) {
+                               if (!tcf_match_indev(skb, n->ifindex)) {
                                        n = n->next;
                                        goto next_knode;
                                }
@@ -527,9 +527,11 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
 
 #ifdef CONFIG_NET_CLS_IND
        if (tb[TCA_U32_INDEV]) {
-               err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV]);
-               if (err < 0)
+               int ret;
+               ret = tcf_change_indev(net, tb[TCA_U32_INDEV]);
+               if (ret < 0)
                        goto errout;
+               n->ifindex = ret;
        }
 #endif
        tcf_exts_change(tp, &n->exts, &e);
@@ -712,7 +714,7 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg)
        }
 }
 
-static int u32_dump(struct tcf_proto *tp, unsigned long fh,
+static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
                     struct sk_buff *skb, struct tcmsg *t)
 {
        struct tc_u_knode *n = (struct tc_u_knode *)fh;
@@ -760,9 +762,12 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
                        goto nla_put_failure;
 
 #ifdef CONFIG_NET_CLS_IND
-               if (strlen(n->indev) &&
-                   nla_put_string(skb, TCA_U32_INDEV, n->indev))
-                       goto nla_put_failure;
+               if (n->ifindex) {
+                       struct net_device *dev;
+                       dev = __dev_get_by_index(net, n->ifindex);
+                       if (dev && nla_put_string(skb, TCA_U32_INDEV, dev->name))
+                               goto nla_put_failure;
+               }
 #endif
 #ifdef CONFIG_CLS_U32_PERF
                if (nla_put(skb, TCA_U32_PCNT,
index c31190e29b90212d8fe48fe3725692ae75b08af2..1313145e3b8650853514552a0ddb371b4000b788 100644 (file)
@@ -135,7 +135,7 @@ static DEFINE_RWLOCK(qdisc_mod_lock);
 
 static struct Qdisc_ops *qdisc_base;
 
-/* Register/uregister queueing discipline */
+/* Register/unregister queueing discipline */
 
 int register_qdisc(struct Qdisc_ops *qops)
 {
index e25183333807143eafe86e4f0f55c94bcf8571b8..2f80d01d42a6d8b971345229d407f062df921b04 100644 (file)
@@ -1060,8 +1060,8 @@ static void cbq_normalize_quanta(struct cbq_sched_data *q, int prio)
                        }
                        if (cl->quantum <= 0 ||
                            cl->quantum > 32*qdisc_dev(cl->qdisc)->mtu) {
-                               pr_warning("CBQ: class %08x has bad quantum==%ld, repaired.\n",
-                                          cl->common.classid, cl->quantum);
+                               pr_warn("CBQ: class %08x has bad quantum==%ld, repaired.\n",
+                                       cl->common.classid, cl->quantum);
                                cl->quantum = qdisc_dev(cl->qdisc)->mtu/2 + 1;
                        }
                }
index 0952fd2684e4894f3d5b11902d4e7e7f1fb3556d..49d6ef338b558ee338163826b1a8a8966093637b 100644 (file)
@@ -57,8 +57,8 @@ static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
 {
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
 
-       pr_debug("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",
-               sch, p, new, old);
+       pr_debug("%s(sch %p,[qdisc %p],new %p,old %p)\n",
+                __func__, sch, p, new, old);
 
        if (new == NULL) {
                new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
@@ -85,8 +85,8 @@ static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
 
 static unsigned long dsmark_get(struct Qdisc *sch, u32 classid)
 {
-       pr_debug("dsmark_get(sch %p,[qdisc %p],classid %x)\n",
-               sch, qdisc_priv(sch), classid);
+       pr_debug("%s(sch %p,[qdisc %p],classid %x)\n",
+                __func__, sch, qdisc_priv(sch), classid);
 
        return TC_H_MIN(classid) + 1;
 }
@@ -118,8 +118,8 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
        int err = -EINVAL;
        u8 mask = 0;
 
-       pr_debug("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
-               "arg 0x%lx\n", sch, p, classid, parent, *arg);
+       pr_debug("%s(sch %p,[qdisc %p],classid %x,parent %x), arg 0x%lx\n",
+                __func__, sch, p, classid, parent, *arg);
 
        if (!dsmark_valid_index(p, *arg)) {
                err = -ENOENT;
@@ -166,7 +166,8 @@ static void dsmark_walk(struct Qdisc *sch, struct qdisc_walker *walker)
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
        int i;
 
-       pr_debug("dsmark_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
+       pr_debug("%s(sch %p,[qdisc %p],walker %p)\n",
+                __func__, sch, p, walker);
 
        if (walker->stop)
                return;
@@ -199,7 +200,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
        int err;
 
-       pr_debug("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+       pr_debug("%s(skb %p,sch %p,[qdisc %p])\n", __func__, skb, sch, p);
 
        if (p->set_tc_index) {
                switch (skb->protocol) {
@@ -275,7 +276,7 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
        struct sk_buff *skb;
        u32 index;
 
-       pr_debug("dsmark_dequeue(sch %p,[qdisc %p])\n", sch, p);
+       pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
 
        skb = p->q->ops->dequeue(p->q);
        if (skb == NULL)
@@ -303,8 +304,8 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
                 * and don't need yet another qdisc as a bypass.
                 */
                if (p->mask[index] != 0xff || p->value[index])
-                       pr_warning("dsmark_dequeue: unsupported protocol %d\n",
-                                  ntohs(skb->protocol));
+                       pr_warn("%s: unsupported protocol %d\n",
+                               __func__, ntohs(skb->protocol));
                break;
        }
 
@@ -315,7 +316,7 @@ static struct sk_buff *dsmark_peek(struct Qdisc *sch)
 {
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
 
-       pr_debug("dsmark_peek(sch %p,[qdisc %p])\n", sch, p);
+       pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
 
        return p->q->ops->peek(p->q);
 }
@@ -325,7 +326,7 @@ static unsigned int dsmark_drop(struct Qdisc *sch)
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
        unsigned int len;
 
-       pr_debug("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
+       pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
 
        if (p->q->ops->drop == NULL)
                return 0;
@@ -346,7 +347,7 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
        u16 indices;
        u8 *mask;
 
-       pr_debug("dsmark_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
+       pr_debug("%s(sch %p,[qdisc %p],opt %p)\n", __func__, sch, p, opt);
 
        if (!opt)
                goto errout;
@@ -384,7 +385,7 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
        if (p->q == NULL)
                p->q = &noop_qdisc;
 
-       pr_debug("dsmark_init: qdisc %p\n", p->q);
+       pr_debug("%s: qdisc %p\n", __func__, p->q);
 
        err = 0;
 errout:
@@ -395,7 +396,7 @@ static void dsmark_reset(struct Qdisc *sch)
 {
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
 
-       pr_debug("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
+       pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
        qdisc_reset(p->q);
        sch->q.qlen = 0;
 }
@@ -404,7 +405,7 @@ static void dsmark_destroy(struct Qdisc *sch)
 {
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
 
-       pr_debug("dsmark_destroy(sch %p,[qdisc %p])\n", sch, p);
+       pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
 
        tcf_destroy_chain(&p->filter_list);
        qdisc_destroy(p->q);
@@ -417,7 +418,7 @@ static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
        struct nlattr *opts = NULL;
 
-       pr_debug("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n", sch, p, cl);
+       pr_debug("%s(sch %p,[qdisc %p],class %ld\n", __func__, sch, p, cl);
 
        if (!dsmark_valid_index(p, cl))
                return -EINVAL;
index d42234c0f13bf4d4829930e0f6bcb30681ad4782..12cbc09157fcce67c314076e3cf0ed690f6f8818 100644 (file)
@@ -370,8 +370,8 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps)
 
        for (i = table->DPs; i < MAX_DPs; i++) {
                if (table->tab[i]) {
-                       pr_warning("GRED: Warning: Destroying "
-                                  "shadowed VQ 0x%x\n", i);
+                       pr_warn("GRED: Warning: Destroying shadowed VQ 0x%x\n",
+                               i);
                        gred_destroy_vq(table->tab[i]);
                        table->tab[i] = NULL;
                }
index 97aa33dbb90f269ecb969fad08ada1f3034cffe9..1cf84a9e13aa80f5be0d1410018d773163a0d238 100644 (file)
@@ -574,18 +574,18 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt)
                q->hh_flows_limit = nla_get_u32(tb[TCA_HHF_HH_FLOWS_LIMIT]);
 
        if (tb[TCA_HHF_RESET_TIMEOUT]) {
-               u32 ms = nla_get_u32(tb[TCA_HHF_RESET_TIMEOUT]);
+               u32 us = nla_get_u32(tb[TCA_HHF_RESET_TIMEOUT]);
 
-               q->hhf_reset_timeout = msecs_to_jiffies(ms);
+               q->hhf_reset_timeout = usecs_to_jiffies(us);
        }
 
        if (tb[TCA_HHF_ADMIT_BYTES])
                q->hhf_admit_bytes = nla_get_u32(tb[TCA_HHF_ADMIT_BYTES]);
 
        if (tb[TCA_HHF_EVICT_TIMEOUT]) {
-               u32 ms = nla_get_u32(tb[TCA_HHF_EVICT_TIMEOUT]);
+               u32 us = nla_get_u32(tb[TCA_HHF_EVICT_TIMEOUT]);
 
-               q->hhf_evict_timeout = msecs_to_jiffies(ms);
+               q->hhf_evict_timeout = usecs_to_jiffies(us);
        }
 
        qlen = sch->q.qlen;
@@ -684,10 +684,10 @@ static int hhf_dump(struct Qdisc *sch, struct sk_buff *skb)
            nla_put_u32(skb, TCA_HHF_QUANTUM, q->quantum) ||
            nla_put_u32(skb, TCA_HHF_HH_FLOWS_LIMIT, q->hh_flows_limit) ||
            nla_put_u32(skb, TCA_HHF_RESET_TIMEOUT,
-                       jiffies_to_msecs(q->hhf_reset_timeout)) ||
+                       jiffies_to_usecs(q->hhf_reset_timeout)) ||
            nla_put_u32(skb, TCA_HHF_ADMIT_BYTES, q->hhf_admit_bytes) ||
            nla_put_u32(skb, TCA_HHF_EVICT_TIMEOUT,
-                       jiffies_to_msecs(q->hhf_evict_timeout)) ||
+                       jiffies_to_usecs(q->hhf_evict_timeout)) ||
            nla_put_u32(skb, TCA_HHF_NON_HH_WEIGHT, q->hhf_non_hh_weight))
                goto nla_put_failure;
 
@@ -711,7 +711,7 @@ static int hhf_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
        return gnet_stats_copy_app(d, &st, sizeof(st));
 }
 
-struct Qdisc_ops hhf_qdisc_ops __read_mostly = {
+static struct Qdisc_ops hhf_qdisc_ops __read_mostly = {
        .id             =       "hhf",
        .priv_size      =       sizeof(struct hhf_sched_data),
 
@@ -727,7 +727,6 @@ struct Qdisc_ops hhf_qdisc_ops __read_mostly = {
        .dump_stats     =       hhf_dump_stats,
        .owner          =       THIS_MODULE,
 };
-EXPORT_SYMBOL(hhf_qdisc_ops);
 
 static int __init hhf_module_init(void)
 {
index 6b0e854b0115170a209a1d2a96a92ae867309716..0db5a6eae87ff243628cf963bd36fc07bb0f3e93 100644 (file)
@@ -712,7 +712,7 @@ static s64 htb_do_events(struct htb_sched *q, const int level,
 
        /* too much load - let's continue after a break for scheduling */
        if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) {
-               pr_warning("htb: too many events!\n");
+               pr_warn("htb: too many events!\n");
                q->warned |= HTB_WARN_TOOMANYEVENTS;
        }
 
@@ -1276,9 +1276,10 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
        struct Qdisc *new_q = NULL;
        int last_child = 0;
 
-       // TODO: why don't allow to delete subtree ? references ? does
-       // tc subsys quarantee us that in htb_destroy it holds no class
-       // refs so that we can remove children safely there ?
+       /* TODO: why don't allow to delete subtree ? references ? does
+        * tc subsys guarantee us that in htb_destroy it holds no class
+        * refs so that we can remove children safely there ?
+        */
        if (cl->children || cl->filter_cnt)
                return -EBUSY;
 
@@ -1488,15 +1489,13 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                cl->quantum = min_t(u64, quantum, INT_MAX);
 
                if (!hopt->quantum && cl->quantum < 1000) {
-                       pr_warning(
-                              "HTB: quantum of class %X is small. Consider r2q change.\n",
-                              cl->common.classid);
+                       pr_warn("HTB: quantum of class %X is small. Consider r2q change.\n",
+                               cl->common.classid);
                        cl->quantum = 1000;
                }
                if (!hopt->quantum && cl->quantum > 200000) {
-                       pr_warning(
-                              "HTB: quantum of class %X is big. Consider r2q change.\n",
-                              cl->common.classid);
+                       pr_warn("HTB: quantum of class %X is big. Consider r2q change.\n",
+                               cl->common.classid);
                        cl->quantum = 200000;
                }
                if (hopt->quantum)
index f3befd6b4781bde74547f9b60b9b3733dba78bcd..090a4e3ecd0dc76b79d916eef416554fd41651d5 100644 (file)
@@ -88,7 +88,7 @@ struct netem_sched_data {
        u32 duplicate;
        u32 reorder;
        u32 corrupt;
-       u32 rate;
+       u64 rate;
        s32 packet_overhead;
        u32 cell_size;
        u32 cell_size_reciprocal;
@@ -495,7 +495,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                                now = netem_skb_cb(last)->time_to_send;
                        }
 
-                       delay += packet_len_2_sched_time(skb->len, q);
+                       delay += packet_len_2_sched_time(qdisc_pkt_len(skb), q);
                }
 
                cb->time_to_send = now + delay;
@@ -782,6 +782,7 @@ static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
        [TCA_NETEM_RATE]        = { .len = sizeof(struct tc_netem_rate) },
        [TCA_NETEM_LOSS]        = { .type = NLA_NESTED },
        [TCA_NETEM_ECN]         = { .type = NLA_U32 },
+       [TCA_NETEM_RATE64]      = { .type = NLA_U64 },
 };
 
 static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
@@ -852,6 +853,10 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
        if (tb[TCA_NETEM_RATE])
                get_rate(sch, tb[TCA_NETEM_RATE]);
 
+       if (tb[TCA_NETEM_RATE64])
+               q->rate = max_t(u64, q->rate,
+                               nla_get_u64(tb[TCA_NETEM_RATE64]));
+
        if (tb[TCA_NETEM_ECN])
                q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]);
 
@@ -974,7 +979,13 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
        if (nla_put(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt))
                goto nla_put_failure;
 
-       rate.rate = q->rate;
+       if (q->rate >= (1ULL << 32)) {
+               if (nla_put_u64(skb, TCA_NETEM_RATE64, q->rate))
+                       goto nla_put_failure;
+               rate.rate = ~0U;
+       } else {
+               rate.rate = q->rate;
+       }
        rate.packet_overhead = q->packet_overhead;
        rate.cell_size = q->cell_size;
        rate.cell_overhead = q->cell_overhead;
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c
new file mode 100644 (file)
index 0000000..fe65340
--- /dev/null
@@ -0,0 +1,555 @@
+/* Copyright (C) 2013 Cisco Systems, Inc, 2013.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Author: Vijay Subramanian <vijaynsu@cisco.com>
+ * Author: Mythili Prabhu <mysuryan@cisco.com>
+ *
+ * ECN support is added by Naeem Khademi <naeemk@ifi.uio.no>
+ * University of Oslo, Norway.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <net/pkt_sched.h>
+#include <net/inet_ecn.h>
+
+#define QUEUE_THRESHOLD 10000
+#define DQCOUNT_INVALID -1
+#define MAX_PROB  0xffffffff
+#define PIE_SCALE 8
+
+/* parameters used */
+struct pie_params {
+       psched_time_t target;   /* user specified target delay in pschedtime */
+       u32 tupdate;            /* timer frequency (in jiffies) */
+       u32 limit;              /* number of packets that can be enqueued */
+       u32 alpha;              /* alpha and beta are between -4 and 4 */
+       u32 beta;               /* and are used for shift relative to 1 */
+       bool ecn;               /* true if ecn is enabled */
+       bool bytemode;          /* to scale drop early prob based on pkt size */
+};
+
+/* variables used */
+struct pie_vars {
+       u32 prob;               /* probability but scaled by u32 limit. */
+       psched_time_t burst_time;
+       psched_time_t qdelay;
+       psched_time_t qdelay_old;
+       u64 dq_count;           /* measured in bytes */
+       psched_time_t dq_tstamp;        /* drain rate */
+       u32 avg_dq_rate;        /* bytes per pschedtime tick,scaled */
+       u32 qlen_old;           /* in bytes */
+};
+
+/* statistics gathering */
+struct pie_stats {
+       u32 packets_in;         /* total number of packets enqueued */
+       u32 dropped;            /* packets dropped due to pie_action */
+       u32 overlimit;          /* dropped due to lack of space in queue */
+       u32 maxq;               /* maximum queue size */
+       u32 ecn_mark;           /* packets marked with ECN */
+};
+
+/* private data for the Qdisc */
+struct pie_sched_data {
+       struct pie_params params;
+       struct pie_vars vars;
+       struct pie_stats stats;
+       struct timer_list adapt_timer;
+};
+
+static void pie_params_init(struct pie_params *params)
+{
+       params->alpha = 2;
+       params->beta = 20;
+       params->tupdate = usecs_to_jiffies(30 * USEC_PER_MSEC); /* 30 ms */
+       params->limit = 1000;   /* default of 1000 packets */
+       params->target = PSCHED_NS2TICKS(20 * NSEC_PER_MSEC);   /* 20 ms */
+       params->ecn = false;
+       params->bytemode = false;
+}
+
+static void pie_vars_init(struct pie_vars *vars)
+{
+       vars->dq_count = DQCOUNT_INVALID;
+       vars->avg_dq_rate = 0;
+       /* default of 100 ms in pschedtime */
+       vars->burst_time = PSCHED_NS2TICKS(100 * NSEC_PER_MSEC);
+}
+
+static bool drop_early(struct Qdisc *sch, u32 packet_size)
+{
+       struct pie_sched_data *q = qdisc_priv(sch);
+       u32 rnd;
+       u32 local_prob = q->vars.prob;
+       u32 mtu = psched_mtu(qdisc_dev(sch));
+
+       /* If there is still burst allowance left skip random early drop */
+       if (q->vars.burst_time > 0)
+               return false;
+
+       /* If current delay is less than half of target, and
+        * if drop prob is low already, disable early_drop
+        */
+       if ((q->vars.qdelay < q->params.target / 2)
+           && (q->vars.prob < MAX_PROB / 5))
+               return false;
+
+       /* If we have fewer than 2 mtu-sized packets, disable drop_early,
+        * similar to min_th in RED
+        */
+       if (sch->qstats.backlog < 2 * mtu)
+               return false;
+
+       /* If bytemode is turned on, use packet size to compute new
+        * probablity. Smaller packets will have lower drop prob in this case
+        */
+       if (q->params.bytemode && packet_size <= mtu)
+               local_prob = (local_prob / mtu) * packet_size;
+       else
+               local_prob = q->vars.prob;
+
+       rnd = net_random();
+       if (rnd < local_prob)
+               return true;
+
+       return false;
+}
+
+static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+       struct pie_sched_data *q = qdisc_priv(sch);
+       bool enqueue = false;
+
+       if (unlikely(qdisc_qlen(sch) >= sch->limit)) {
+               q->stats.overlimit++;
+               goto out;
+       }
+
+       if (!drop_early(sch, skb->len)) {
+               enqueue = true;
+       } else if (q->params.ecn && (q->vars.prob <= MAX_PROB / 10) &&
+                  INET_ECN_set_ce(skb)) {
+               /* If packet is ecn capable, mark it if drop probability
+                * is lower than 10%, else drop it.
+                */
+               q->stats.ecn_mark++;
+               enqueue = true;
+       }
+
+       /* we can enqueue the packet */
+       if (enqueue) {
+               q->stats.packets_in++;
+               if (qdisc_qlen(sch) > q->stats.maxq)
+                       q->stats.maxq = qdisc_qlen(sch);
+
+               return qdisc_enqueue_tail(skb, sch);
+       }
+
+out:
+       q->stats.dropped++;
+       return qdisc_drop(skb, sch);
+}
+
+static const struct nla_policy pie_policy[TCA_PIE_MAX + 1] = {
+       [TCA_PIE_TARGET] = {.type = NLA_U32},
+       [TCA_PIE_LIMIT] = {.type = NLA_U32},
+       [TCA_PIE_TUPDATE] = {.type = NLA_U32},
+       [TCA_PIE_ALPHA] = {.type = NLA_U32},
+       [TCA_PIE_BETA] = {.type = NLA_U32},
+       [TCA_PIE_ECN] = {.type = NLA_U32},
+       [TCA_PIE_BYTEMODE] = {.type = NLA_U32},
+};
+
+static int pie_change(struct Qdisc *sch, struct nlattr *opt)
+{
+       struct pie_sched_data *q = qdisc_priv(sch);
+       struct nlattr *tb[TCA_PIE_MAX + 1];
+       unsigned int qlen;
+       int err;
+
+       if (!opt)
+               return -EINVAL;
+
+       err = nla_parse_nested(tb, TCA_PIE_MAX, opt, pie_policy);
+       if (err < 0)
+               return err;
+
+       sch_tree_lock(sch);
+
+       /* convert from microseconds to pschedtime */
+       if (tb[TCA_PIE_TARGET]) {
+               /* target is in us */
+               u32 target = nla_get_u32(tb[TCA_PIE_TARGET]);
+
+               /* convert to pschedtime */
+               q->params.target = PSCHED_NS2TICKS((u64)target * NSEC_PER_USEC);
+       }
+
+       /* tupdate is in jiffies */
+       if (tb[TCA_PIE_TUPDATE])
+               q->params.tupdate = usecs_to_jiffies(nla_get_u32(tb[TCA_PIE_TUPDATE]));
+
+       if (tb[TCA_PIE_LIMIT]) {
+               u32 limit = nla_get_u32(tb[TCA_PIE_LIMIT]);
+
+               q->params.limit = limit;
+               sch->limit = limit;
+       }
+
+       if (tb[TCA_PIE_ALPHA])
+               q->params.alpha = nla_get_u32(tb[TCA_PIE_ALPHA]);
+
+       if (tb[TCA_PIE_BETA])
+               q->params.beta = nla_get_u32(tb[TCA_PIE_BETA]);
+
+       if (tb[TCA_PIE_ECN])
+               q->params.ecn = nla_get_u32(tb[TCA_PIE_ECN]);
+
+       if (tb[TCA_PIE_BYTEMODE])
+               q->params.bytemode = nla_get_u32(tb[TCA_PIE_BYTEMODE]);
+
+       /* Drop excess packets if new limit is lower */
+       qlen = sch->q.qlen;
+       while (sch->q.qlen > sch->limit) {
+               struct sk_buff *skb = __skb_dequeue(&sch->q);
+
+               sch->qstats.backlog -= qdisc_pkt_len(skb);
+               qdisc_drop(skb, sch);
+       }
+       qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
+
+       sch_tree_unlock(sch);
+       return 0;
+}
+
+static void pie_process_dequeue(struct Qdisc *sch, struct sk_buff *skb)
+{
+
+       struct pie_sched_data *q = qdisc_priv(sch);
+       int qlen = sch->qstats.backlog; /* current queue size in bytes */
+
+       /* If current queue is about 10 packets or more and dq_count is unset
+        * we have enough packets to calculate the drain rate. Save
+        * current time as dq_tstamp and start measurement cycle.
+        */
+       if (qlen >= QUEUE_THRESHOLD && q->vars.dq_count == DQCOUNT_INVALID) {
+               q->vars.dq_tstamp = psched_get_time();
+               q->vars.dq_count = 0;
+       }
+
+       /* Calculate the average drain rate from this value.  If queue length
+        * has receded to a small value viz., <= QUEUE_THRESHOLD bytes,reset
+        * the dq_count to -1 as we don't have enough packets to calculate the
+        * drain rate anymore The following if block is entered only when we
+        * have a substantial queue built up (QUEUE_THRESHOLD bytes or more)
+        * and we calculate the drain rate for the threshold here.  dq_count is
+        * in bytes, time difference in psched_time, hence rate is in
+        * bytes/psched_time.
+        */
+       if (q->vars.dq_count != DQCOUNT_INVALID) {
+               q->vars.dq_count += skb->len;
+
+               if (q->vars.dq_count >= QUEUE_THRESHOLD) {
+                       psched_time_t now = psched_get_time();
+                       u32 dtime = now - q->vars.dq_tstamp;
+                       u32 count = q->vars.dq_count << PIE_SCALE;
+
+                       if (dtime == 0)
+                               return;
+
+                       count = count / dtime;
+
+                       if (q->vars.avg_dq_rate == 0)
+                               q->vars.avg_dq_rate = count;
+                       else
+                               q->vars.avg_dq_rate =
+                                   (q->vars.avg_dq_rate -
+                                    (q->vars.avg_dq_rate >> 3)) + (count >> 3);
+
+                       /* If the queue has receded below the threshold, we hold
+                        * on to the last drain rate calculated, else we reset
+                        * dq_count to 0 to re-enter the if block when the next
+                        * packet is dequeued
+                        */
+                       if (qlen < QUEUE_THRESHOLD)
+                               q->vars.dq_count = DQCOUNT_INVALID;
+                       else {
+                               q->vars.dq_count = 0;
+                               q->vars.dq_tstamp = psched_get_time();
+                       }
+
+                       if (q->vars.burst_time > 0) {
+                               if (q->vars.burst_time > dtime)
+                                       q->vars.burst_time -= dtime;
+                               else
+                                       q->vars.burst_time = 0;
+                       }
+               }
+       }
+}
+
+static void calculate_probability(struct Qdisc *sch)
+{
+       struct pie_sched_data *q = qdisc_priv(sch);
+       u32 qlen = sch->qstats.backlog; /* queue size in bytes */
+       psched_time_t qdelay = 0;       /* in pschedtime */
+       psched_time_t qdelay_old = q->vars.qdelay;      /* in pschedtime */
+       s32 delta = 0;          /* determines the change in probability */
+       u32 oldprob;
+       u32 alpha, beta;
+       bool update_prob = true;
+
+       q->vars.qdelay_old = q->vars.qdelay;
+
+       if (q->vars.avg_dq_rate > 0)
+               qdelay = (qlen << PIE_SCALE) / q->vars.avg_dq_rate;
+       else
+               qdelay = 0;
+
+       /* If qdelay is zero and qlen is not, it means qlen is very small, less
+        * than dequeue_rate, so we do not update probabilty in this round
+        */
+       if (qdelay == 0 && qlen != 0)
+               update_prob = false;
+
+       /* Add ranges for alpha and beta, more aggressive for high dropping
+        * mode and gentle steps for light dropping mode
+        * In light dropping mode, take gentle steps; in medium dropping mode,
+        * take medium steps; in high dropping mode, take big steps.
+        */
+       if (q->vars.prob < MAX_PROB / 100) {
+               alpha =
+                   (q->params.alpha * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 7;
+               beta =
+                   (q->params.beta * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 7;
+       } else if (q->vars.prob < MAX_PROB / 10) {
+               alpha =
+                   (q->params.alpha * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 5;
+               beta =
+                   (q->params.beta * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 5;
+       } else {
+               alpha =
+                   (q->params.alpha * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 4;
+               beta =
+                   (q->params.beta * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 4;
+       }
+
+       /* alpha and beta should be between 0 and 32, in multiples of 1/16 */
+       delta += alpha * ((qdelay - q->params.target));
+       delta += beta * ((qdelay - qdelay_old));
+
+       oldprob = q->vars.prob;
+
+       /* to ensure we increase probability in steps of no more than 2% */
+       if (delta > (s32) (MAX_PROB / (100 / 2)) &&
+           q->vars.prob >= MAX_PROB / 10)
+               delta = (MAX_PROB / 100) * 2;
+
+       /* Non-linear drop:
+        * Tune drop probability to increase quickly for high delays(>= 250ms)
+        * 250ms is derived through experiments and provides error protection
+        */
+
+       if (qdelay > (PSCHED_NS2TICKS(250 * NSEC_PER_MSEC)))
+               delta += MAX_PROB / (100 / 2);
+
+       q->vars.prob += delta;
+
+       if (delta > 0) {
+               /* prevent overflow */
+               if (q->vars.prob < oldprob) {
+                       q->vars.prob = MAX_PROB;
+                       /* Prevent normalization error. If probability is at
+                        * maximum value already, we normalize it here, and
+                        * skip the check to do a non-linear drop in the next
+                        * section.
+                        */
+                       update_prob = false;
+               }
+       } else {
+               /* prevent underflow */
+               if (q->vars.prob > oldprob)
+                       q->vars.prob = 0;
+       }
+
+       /* Non-linear drop in probability: Reduce drop probability quickly if
+        * delay is 0 for 2 consecutive Tupdate periods.
+        */
+
+       if ((qdelay == 0) && (qdelay_old == 0) && update_prob)
+               q->vars.prob = (q->vars.prob * 98) / 100;
+
+       q->vars.qdelay = qdelay;
+       q->vars.qlen_old = qlen;
+
+       /* We restart the measurement cycle if the following conditions are met
+        * 1. If the delay has been low for 2 consecutive Tupdate periods
+        * 2. Calculated drop probability is zero
+        * 3. We have atleast one estimate for the avg_dq_rate ie.,
+        *    is a non-zero value
+        */
+       if ((q->vars.qdelay < q->params.target / 2) &&
+           (q->vars.qdelay_old < q->params.target / 2) &&
+           (q->vars.prob == 0) &&
+           (q->vars.avg_dq_rate > 0))
+               pie_vars_init(&q->vars);
+}
+
+static void pie_timer(unsigned long arg)
+{
+       struct Qdisc *sch = (struct Qdisc *)arg;
+       struct pie_sched_data *q = qdisc_priv(sch);
+       spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch));
+
+       spin_lock(root_lock);
+       calculate_probability(sch);
+
+       /* reset the timer to fire after 'tupdate'. tupdate is in jiffies. */
+       if (q->params.tupdate)
+               mod_timer(&q->adapt_timer, jiffies + q->params.tupdate);
+       spin_unlock(root_lock);
+
+}
+
+static int pie_init(struct Qdisc *sch, struct nlattr *opt)
+{
+       struct pie_sched_data *q = qdisc_priv(sch);
+
+       pie_params_init(&q->params);
+       pie_vars_init(&q->vars);
+       sch->limit = q->params.limit;
+
+       setup_timer(&q->adapt_timer, pie_timer, (unsigned long)sch);
+       mod_timer(&q->adapt_timer, jiffies + HZ / 2);
+
+       if (opt) {
+               int err = pie_change(sch, opt);
+
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int pie_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+       struct pie_sched_data *q = qdisc_priv(sch);
+       struct nlattr *opts;
+
+       opts = nla_nest_start(skb, TCA_OPTIONS);
+       if (opts == NULL)
+               goto nla_put_failure;
+
+       /* convert target from pschedtime to us */
+       if (nla_put_u32(skb, TCA_PIE_TARGET,
+                       ((u32) PSCHED_TICKS2NS(q->params.target)) /
+                       NSEC_PER_USEC) ||
+           nla_put_u32(skb, TCA_PIE_LIMIT, sch->limit) ||
+           nla_put_u32(skb, TCA_PIE_TUPDATE, jiffies_to_usecs(q->params.tupdate)) ||
+           nla_put_u32(skb, TCA_PIE_ALPHA, q->params.alpha) ||
+           nla_put_u32(skb, TCA_PIE_BETA, q->params.beta) ||
+           nla_put_u32(skb, TCA_PIE_ECN, q->params.ecn) ||
+           nla_put_u32(skb, TCA_PIE_BYTEMODE, q->params.bytemode))
+               goto nla_put_failure;
+
+       return nla_nest_end(skb, opts);
+
+nla_put_failure:
+       nla_nest_cancel(skb, opts);
+       return -1;
+
+}
+
+static int pie_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
+{
+       struct pie_sched_data *q = qdisc_priv(sch);
+       struct tc_pie_xstats st = {
+               .prob           = q->vars.prob,
+               .delay          = ((u32) PSCHED_TICKS2NS(q->vars.qdelay)) /
+                                  NSEC_PER_USEC,
+               /* unscale and return dq_rate in bytes per sec */
+               .avg_dq_rate    = q->vars.avg_dq_rate *
+                                 (PSCHED_TICKS_PER_SEC) >> PIE_SCALE,
+               .packets_in     = q->stats.packets_in,
+               .overlimit      = q->stats.overlimit,
+               .maxq           = q->stats.maxq,
+               .dropped        = q->stats.dropped,
+               .ecn_mark       = q->stats.ecn_mark,
+       };
+
+       return gnet_stats_copy_app(d, &st, sizeof(st));
+}
+
+static struct sk_buff *pie_qdisc_dequeue(struct Qdisc *sch)
+{
+       struct sk_buff *skb;
+       skb = __qdisc_dequeue_head(sch, &sch->q);
+
+       if (!skb)
+               return NULL;
+
+       pie_process_dequeue(sch, skb);
+       return skb;
+}
+
+static void pie_reset(struct Qdisc *sch)
+{
+       struct pie_sched_data *q = qdisc_priv(sch);
+       qdisc_reset_queue(sch);
+       pie_vars_init(&q->vars);
+}
+
+static void pie_destroy(struct Qdisc *sch)
+{
+       struct pie_sched_data *q = qdisc_priv(sch);
+       q->params.tupdate = 0;
+       del_timer_sync(&q->adapt_timer);
+}
+
+static struct Qdisc_ops pie_qdisc_ops __read_mostly = {
+       .id = "pie",
+       .priv_size      = sizeof(struct pie_sched_data),
+       .enqueue        = pie_qdisc_enqueue,
+       .dequeue        = pie_qdisc_dequeue,
+       .peek           = qdisc_peek_dequeued,
+       .init           = pie_init,
+       .destroy        = pie_destroy,
+       .reset          = pie_reset,
+       .change         = pie_change,
+       .dump           = pie_dump,
+       .dump_stats     = pie_dump_stats,
+       .owner          = THIS_MODULE,
+};
+
+static int __init pie_module_init(void)
+{
+       return register_qdisc(&pie_qdisc_ops);
+}
+
+static void __exit pie_module_exit(void)
+{
+       unregister_qdisc(&pie_qdisc_ops);
+}
+
+module_init(pie_module_init);
+module_exit(pie_module_exit);
+
+MODULE_DESCRIPTION("Proportional Integral controller Enhanced (PIE) scheduler");
+MODULE_AUTHOR("Vijay Subramanian");
+MODULE_AUTHOR("Mythili Prabhu");
+MODULE_LICENSE("GPL");
index 887e672f9d7d4b185542957bcb7e10b7d8a70cec..fbba5b0ec1215be171d17c70fa5be3a7c79314b9 100644 (file)
@@ -307,6 +307,8 @@ static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = {
        [TCA_TBF_PTAB]  = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
        [TCA_TBF_RATE64]        = { .type = NLA_U64 },
        [TCA_TBF_PRATE64]       = { .type = NLA_U64 },
+       [TCA_TBF_BURST] = { .type = NLA_U32 },
+       [TCA_TBF_PBURST] = { .type = NLA_U32 },
 };
 
 static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
@@ -358,7 +360,12 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                rate64 = nla_get_u64(tb[TCA_TBF_RATE64]);
        psched_ratecfg_precompute(&rate, &qopt->rate, rate64);
 
-       max_size = min_t(u64, psched_ns_t2l(&rate, buffer), ~0U);
+       if (tb[TCA_TBF_BURST]) {
+               max_size = nla_get_u32(tb[TCA_TBF_BURST]);
+               buffer = psched_l2t_ns(&rate, max_size);
+       } else {
+               max_size = min_t(u64, psched_ns_t2l(&rate, buffer), ~0U);
+       }
 
        if (qopt->peakrate.rate) {
                if (tb[TCA_TBF_PRATE64])
@@ -366,12 +373,18 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                psched_ratecfg_precompute(&peak, &qopt->peakrate, prate64);
                if (peak.rate_bytes_ps <= rate.rate_bytes_ps) {
                        pr_warn_ratelimited("sch_tbf: peakrate %llu is lower than or equals to rate %llu !\n",
-                                           peak.rate_bytes_ps, rate.rate_bytes_ps);
+                                       peak.rate_bytes_ps, rate.rate_bytes_ps);
                        err = -EINVAL;
                        goto done;
                }
 
-               max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu));
+               if (tb[TCA_TBF_PBURST]) {
+                       u32 pburst = nla_get_u32(tb[TCA_TBF_PBURST]);
+                       max_size = min_t(u32, max_size, pburst);
+                       mtu = psched_l2t_ns(&peak, pburst);
+               } else {
+                       max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu));
+               }
        }
 
        if (max_size < psched_mtu(qdisc_dev(sch)))
@@ -391,9 +404,15 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                q->qdisc = child;
        }
        q->limit = qopt->limit;
-       q->mtu = PSCHED_TICKS2NS(qopt->mtu);
+       if (tb[TCA_TBF_PBURST])
+               q->mtu = mtu;
+       else
+               q->mtu = PSCHED_TICKS2NS(qopt->mtu);
        q->max_size = max_size;
-       q->buffer = PSCHED_TICKS2NS(qopt->buffer);
+       if (tb[TCA_TBF_BURST])
+               q->buffer = buffer;
+       else
+               q->buffer = PSCHED_TICKS2NS(qopt->buffer);
        q->tokens = q->buffer;
        q->ptokens = q->mtu;
 
index 5c9f64c1c906fc4cecd154a843c90e1efe56858c..683c7d1b13060adb328b683b3b3d608d9dde5834 100644 (file)
@@ -41,7 +41,7 @@ static struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = {
        },
        {
                .hmac_id = SCTP_AUTH_HMAC_ID_SHA1,
-               .hmac_name="hmac(sha1)",
+               .hmac_name = "hmac(sha1)",
                .hmac_len = SCTP_SHA1_SIG_SIZE,
        },
        {
@@ -51,7 +51,7 @@ static struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = {
 #if defined (CONFIG_CRYPTO_SHA256) || defined (CONFIG_CRYPTO_SHA256_MODULE)
        {
                .hmac_id = SCTP_AUTH_HMAC_ID_SHA256,
-               .hmac_name="hmac(sha256)",
+               .hmac_name = "hmac(sha256)",
                .hmac_len = SCTP_SHA256_SIG_SIZE,
        }
 #endif
@@ -163,7 +163,7 @@ static int sctp_auth_compare_vectors(struct sctp_auth_bytes *vector1,
                 * lead-zero padded.  If it is not, it
                 * is automatically larger numerically.
                 */
-               for (i = 0; i < abs(diff); i++ ) {
+               for (i = 0; i < abs(diff); i++) {
                        if (longer[i] != 0)
                                return diff;
                }
@@ -226,9 +226,9 @@ static struct sctp_auth_bytes *sctp_auth_make_local_vector(
                                    gfp_t gfp)
 {
        return sctp_auth_make_key_vector(
-                                   (sctp_random_param_t*)asoc->c.auth_random,
-                                   (sctp_chunks_param_t*)asoc->c.auth_chunks,
-                                   (sctp_hmac_algo_param_t*)asoc->c.auth_hmacs,
+                                   (sctp_random_param_t *)asoc->c.auth_random,
+                                   (sctp_chunks_param_t *)asoc->c.auth_chunks,
+                                   (sctp_hmac_algo_param_t *)asoc->c.auth_hmacs,
                                    gfp);
 }
 
@@ -499,8 +499,7 @@ void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[])
        if (!auth_hmacs)
                return;
 
-       for (i = 0; i < SCTP_AUTH_NUM_HMACS; i++)
-       {
+       for (i = 0; i < SCTP_AUTH_NUM_HMACS; i++) {
                if (auth_hmacs[i])
                        crypto_free_hash(auth_hmacs[i]);
        }
@@ -647,15 +646,15 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param)
         */
        for (i = 0; !found && i < len; i++) {
                switch (param->chunks[i]) {
-                   case SCTP_CID_INIT:
-                   case SCTP_CID_INIT_ACK:
-                   case SCTP_CID_SHUTDOWN_COMPLETE:
-                   case SCTP_CID_AUTH:
+               case SCTP_CID_INIT:
+               case SCTP_CID_INIT_ACK:
+               case SCTP_CID_SHUTDOWN_COMPLETE:
+               case SCTP_CID_AUTH:
                        break;
 
-                   default:
+               default:
                        if (param->chunks[i] == chunk)
-                           found = 1;
+                               found = 1;
                        break;
                }
        }
index 5573e425b0c0cc9ecc257994f98127be7ee24c3e..158701da2d31c8c862fcffd59404b7c08d3b610a 100644 (file)
@@ -254,7 +254,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
                SCTP_INC_STATS_USER(sock_net(asoc->base.sk), SCTP_MIB_FRAGUSRMSGS);
 
        /* Create chunks for all the full sized DATA chunks. */
-       for (i=0, len=first_len; i < whole; i++) {
+       for (i = 0, len = first_len; i < whole; i++) {
                frag = SCTP_DATA_MIDDLE_FRAG;
 
                if (0 == i)
@@ -317,7 +317,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
                        goto errout;
                }
 
-               err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
+               err = sctp_user_addto_chunk(chunk, offset, over, msgh->msg_iov);
 
                /* Put the chunk->skb back into the form expected by send.  */
                __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
index 042ec6c9ae24a6106aba1d7c345e3d653359dbfe..1f4eeb43fbd60e4bde0c9afb93110c9e62056ad3 100644 (file)
@@ -119,7 +119,7 @@ int sctp_rcv(struct sk_buff *skb)
        struct sctp_af *af;
        struct net *net = dev_net(skb->dev);
 
-       if (skb->pkt_type!=PACKET_HOST)
+       if (skb->pkt_type != PACKET_HOST)
                goto discard_it;
 
        SCTP_INC_STATS_BH(net, SCTP_MIB_INSCTPPACKS);
@@ -180,8 +180,7 @@ int sctp_rcv(struct sk_buff *skb)
         * If a frame arrives on an interface and the receiving socket is
         * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
         */
-       if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb)))
-       {
+       if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) {
                if (asoc) {
                        sctp_association_put(asoc);
                        asoc = NULL;
@@ -389,9 +388,6 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
        if (!t || (t->pathmtu <= pmtu))
                return;
 
-       if (!ip6_sk_accept_pmtu(sk))
-               return;
-
        if (sock_owned_by_user(sk)) {
                asoc->pmtu_pending = 1;
                t->pmtu_pending = 1;
@@ -613,8 +609,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
                if (ICMP_FRAG_NEEDED == code) {
                        sctp_icmp_frag_needed(sk, asoc, transport, info);
                        goto out_unlock;
-               }
-               else {
+               } else {
                        if (ICMP_PROT_UNREACH == code) {
                                sctp_icmp_proto_unreachable(sk, asoc,
                                                            transport);
@@ -1058,31 +1053,31 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
                if (ch_end > skb_tail_pointer(skb))
                        break;
 
-               switch(ch->type) {
-                   case SCTP_CID_AUTH:
-                           have_auth = chunk_num;
-                           break;
-
-                   case SCTP_CID_COOKIE_ECHO:
-                           /* If a packet arrives containing an AUTH chunk as
-                            * a first chunk, a COOKIE-ECHO chunk as the second
-                            * chunk, and possibly more chunks after them, and
-                            * the receiver does not have an STCB for that
-                            * packet, then authentication is based on
-                            * the contents of the COOKIE- ECHO chunk.
-                            */
-                           if (have_auth == 1 && chunk_num == 2)
-                                   return NULL;
-                           break;
-
-                   case SCTP_CID_ASCONF:
-                           if (have_auth || net->sctp.addip_noauth)
-                                   asoc = __sctp_rcv_asconf_lookup(
-                                                       net, ch, laddr,
-                                                       sctp_hdr(skb)->source,
-                                                       transportp);
-                   default:
-                           break;
+               switch (ch->type) {
+               case SCTP_CID_AUTH:
+                       have_auth = chunk_num;
+                       break;
+
+               case SCTP_CID_COOKIE_ECHO:
+                       /* If a packet arrives containing an AUTH chunk as
+                        * a first chunk, a COOKIE-ECHO chunk as the second
+                        * chunk, and possibly more chunks after them, and
+                        * the receiver does not have an STCB for that
+                        * packet, then authentication is based on
+                        * the contents of the COOKIE- ECHO chunk.
+                        */
+                       if (have_auth == 1 && chunk_num == 2)
+                               return NULL;
+                       break;
+
+               case SCTP_CID_ASCONF:
+                       if (have_auth || net->sctp.addip_noauth)
+                               asoc = __sctp_rcv_asconf_lookup(
+                                               net, ch, laddr,
+                                               sctp_hdr(skb)->source,
+                                               transportp);
+               default:
+                       break;
                }
 
                if (asoc)
@@ -1119,19 +1114,10 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
                return NULL;
 
        /* If this is INIT/INIT-ACK look inside the chunk too. */
-       switch (ch->type) {
-       case SCTP_CID_INIT:
-       case SCTP_CID_INIT_ACK:
+       if (ch->type == SCTP_CID_INIT || ch->type == SCTP_CID_INIT_ACK)
                return __sctp_rcv_init_lookup(net, skb, laddr, transportp);
-               break;
-
-       default:
-               return __sctp_rcv_walk_lookup(net, skb, laddr, transportp);
-               break;
-       }
 
-
-       return NULL;
+       return __sctp_rcv_walk_lookup(net, skb, laddr, transportp);
 }
 
 /* Lookup an association for an inbound skb. */
index 317e13eb2c568ea91d75874a2a545d0c2d0cb8b9..0f6259a6a932c583f4450a6fe79ef46b7d184996 100644 (file)
@@ -172,7 +172,8 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        switch (type) {
        case ICMPV6_PKT_TOOBIG:
-               sctp_icmp_frag_needed(sk, asoc, transport, ntohl(info));
+               if (ip6_sk_accept_pmtu(sk))
+                       sctp_icmp_frag_needed(sk, asoc, transport, ntohl(info));
                goto out_unlock;
        case ICMPV6_PARAMPROB:
                if (ICMPV6_UNK_NEXTHDR == code) {
@@ -401,7 +402,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
 }
 
 /* Initialize a sockaddr_storage from in incoming skb. */
-static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
+static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
                             int is_saddr)
 {
        __be16 *port;
index 0c28e8a55324a69fd675dc1377187697d08cc365..40e7fac96c41123eef4c1197b472f0a1051752cd 100644 (file)
@@ -97,7 +97,7 @@ static void sctp_objcnt_seq_stop(struct seq_file *seq, void *v)
 {
 }
 
-static void * sctp_objcnt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *sctp_objcnt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        ++*pos;
        return (*pos >= ARRAY_SIZE(sctp_dbg_objcnt)) ? NULL : (void *)pos;
index 3f55823279d9d67bdda9e3628b86efeff7b740a2..0f4d15fc2627bcccb546ee2da883f812daa4e4a1 100644 (file)
@@ -280,7 +280,7 @@ static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet,
 
        /* We believe that this chunk is OK to add to the packet */
        switch (chunk->chunk_hdr->type) {
-           case SCTP_CID_DATA:
+       case SCTP_CID_DATA:
                /* Account for the data being in the packet */
                sctp_packet_append_data(packet, chunk);
                /* Disallow SACK bundling after DATA. */
@@ -292,17 +292,17 @@ static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet,
                /* timestamp the chunk for rtx purposes */
                chunk->sent_at = jiffies;
                break;
-           case SCTP_CID_COOKIE_ECHO:
+       case SCTP_CID_COOKIE_ECHO:
                packet->has_cookie_echo = 1;
                break;
 
-           case SCTP_CID_SACK:
+       case SCTP_CID_SACK:
                packet->has_sack = 1;
                if (chunk->asoc)
                        chunk->asoc->stats.osacks++;
                break;
 
-           case SCTP_CID_AUTH:
+       case SCTP_CID_AUTH:
                packet->has_auth = 1;
                packet->auth = chunk;
                break;
@@ -387,7 +387,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        int err = 0;
        int padding;            /* How much padding do we need?  */
        __u8 has_data = 0;
-       struct dst_entry *dst = tp->dst;
+       struct dst_entry *dst;
        unsigned char *auth = NULL;     /* pointer to auth in skb data */
 
        pr_debug("%s: packet:%p\n", __func__, packet);
@@ -420,9 +420,9 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                }
        }
        dst = dst_clone(tp->dst);
-       skb_dst_set(nskb, dst);
        if (!dst)
                goto no_route;
+       skb_dst_set(nskb, dst);
 
        /* Build the SCTP header.  */
        sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
@@ -540,8 +540,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                } else {
                        /* no need to seed pseudo checksum for SCTP */
                        nskb->ip_summed = CHECKSUM_PARTIAL;
-                       nskb->csum_start = (skb_transport_header(nskb) -
-                                           nskb->head);
+                       nskb->csum_start = skb_transport_header(nskb) - nskb->head;
                        nskb->csum_offset = offsetof(struct sctphdr, checksum);
                }
        }
@@ -558,7 +557,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
         * Note: The works for IPv6 layer checks this bit too later
         * in transmission.  See IP6_ECN_flow_xmit().
         */
-       (*tp->af_specific->ecn_capable)(nskb->sk);
+       tp->af_specific->ecn_capable(nskb->sk);
 
        /* Set up the IP options.  */
        /* BUG: not implemented
@@ -593,7 +592,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        pr_debug("***sctp_transmit_packet*** skb->len:%d\n", nskb->len);
 
        nskb->local_df = packet->ipfragok;
-       (*tp->af_specific->sctp_xmit)(nskb, tp);
+       tp->af_specific->sctp_xmit(nskb, tp);
 
 out:
        sctp_packet_reset(packet);
index b6b09f3f1a81f8f9fc6837cd79bb9749f6857cca..9c77947c0597c1c2f646214584a8480e038105e9 100644 (file)
@@ -110,7 +110,7 @@ static inline int sctp_cacc_skip_3_1_d(struct sctp_transport *primary,
                                       struct sctp_transport *transport,
                                       int count_of_newacks)
 {
-       if (count_of_newacks >=2 && transport != primary)
+       if (count_of_newacks >= 2 && transport != primary)
                return 1;
        return 0;
 }
@@ -207,8 +207,6 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
        INIT_LIST_HEAD(&q->retransmit);
        INIT_LIST_HEAD(&q->sacked);
        INIT_LIST_HEAD(&q->abandoned);
-
-       q->empty = 1;
 }
 
 /* Free the outqueue structure and any related pending chunks.
@@ -331,7 +329,6 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
                                SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
                        else
                                SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS);
-                       q->empty = 0;
                        break;
                }
        } else {
@@ -470,7 +467,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
        struct net *net = sock_net(q->asoc->base.sk);
        int error = 0;
 
-       switch(reason) {
+       switch (reason) {
        case SCTP_RTXR_T3_RTX:
                SCTP_INC_STATS(net, SCTP_MIB_T3_RETRANSMITS);
                sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX);
@@ -653,7 +650,6 @@ redo:
                        if (chunk->fast_retransmit == SCTP_NEED_FRTX)
                                chunk->fast_retransmit = SCTP_DONT_FRTX;
 
-                       q->empty = 0;
                        q->asoc->stats.rtxchunks++;
                        break;
                }
@@ -1064,8 +1060,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 
                        sctp_transport_reset_timers(transport);
 
-                       q->empty = 0;
-
                        /* Only let one DATA chunk get bundled with a
                         * COOKIE-ECHO chunk.
                         */
@@ -1088,7 +1082,7 @@ sctp_flush_out:
         *
         * --xguo
         */
-       while ((ltransport = sctp_list_dequeue(&transport_list)) != NULL ) {
+       while ((ltransport = sctp_list_dequeue(&transport_list)) != NULL) {
                struct sctp_transport *t = list_entry(ltransport,
                                                      struct sctp_transport,
                                                      send_ready);
@@ -1217,7 +1211,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
                 * destinations for which cacc_saw_newack is set.
                 */
                if (transport->cacc.cacc_saw_newack)
-                       count_of_newacks ++;
+                       count_of_newacks++;
        }
 
        /* Move the Cumulative TSN Ack Point if appropriate.  */
@@ -1274,29 +1268,17 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
                 "advertised peer ack point:0x%x\n", __func__, asoc, ctsn,
                 asoc->adv_peer_ack_point);
 
-       /* See if all chunks are acked.
-        * Make sure the empty queue handler will get run later.
-        */
-       q->empty = (list_empty(&q->out_chunk_list) &&
-                   list_empty(&q->retransmit));
-       if (!q->empty)
-               goto finish;
-
-       list_for_each_entry(transport, transport_list, transports) {
-               q->empty = q->empty && list_empty(&transport->transmitted);
-               if (!q->empty)
-                       goto finish;
-       }
-
-       pr_debug("%s: sack queue is empty\n", __func__);
-finish:
-       return q->empty;
+       return sctp_outq_is_empty(q);
 }
 
-/* Is the outqueue empty?  */
+/* Is the outqueue empty?
+ * The queue is empty when we have not pending data, no in-flight data
+ * and nothing pending retransmissions.
+ */
 int sctp_outq_is_empty(const struct sctp_outq *q)
 {
-       return q->empty;
+       return q->out_qlen == 0 && q->outstanding_bytes == 0 &&
+              list_empty(&q->retransmit);
 }
 
 /********************************************************************
index de32e14f73980e9e498eca8667942db1e49f7793..63ba0bdc867a4abcd306b8c9b60204244c7bfc11 100644 (file)
@@ -177,7 +177,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
        rcu_read_unlock();
 }
 
-static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
+static void *sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
 {
        if (*pos >= sctp_ep_hashsize)
                return NULL;
@@ -196,7 +196,7 @@ static void sctp_eps_seq_stop(struct seq_file *seq, void *v)
 }
 
 
-static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        if (++*pos >= sctp_ep_hashsize)
                return NULL;
@@ -282,7 +282,7 @@ void sctp_eps_proc_exit(struct net *net)
 }
 
 
-static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
+static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
 {
        if (*pos >= sctp_assoc_hashsize)
                return NULL;
@@ -305,7 +305,7 @@ static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
 }
 
 
-static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        if (++*pos >= sctp_assoc_hashsize)
                return NULL;
index 19bd4c5bdae9c55658ed1a99758691a6948a13f6..7c161084f2414b61abbf10a35937d15e460d9f66 100644 (file)
@@ -1030,6 +1030,7 @@ static const struct net_protocol sctp_protocol = {
        .err_handler = sctp_v4_err,
        .no_policy   = 1,
        .netns_ok    = 1,
+       .icmp_strict_tag_validation = 1,
 };
 
 /* IPv4 address related functions.  */
@@ -1065,8 +1066,8 @@ static struct sctp_af sctp_af_inet = {
 #endif
 };
 
-struct sctp_pf *sctp_get_pf_specific(sa_family_t family) {
-
+struct sctp_pf *sctp_get_pf_specific(sa_family_t family)
+{
        switch (family) {
        case PF_INET:
                return sctp_pf_inet_specific;
index d9aaf9641aaa37ee234fb2be6c7339fc1f4eaca1..632090b961c331b78efa79664392c7626451926d 100644 (file)
@@ -78,6 +78,8 @@ static int sctp_process_param(struct sctp_association *asoc,
                              gfp_t gfp);
 static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
                              const void *data);
+static void  *sctp_addto_chunk_fixed(struct sctp_chunk *, int len,
+                                    const void *data);
 
 /* Control chunk destructor */
 static void sctp_control_release_owner(struct sk_buff *skb)
@@ -1475,8 +1477,8 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
 /* Append bytes to the end of a chunk. Returns NULL if there isn't sufficient
  * space in the chunk
  */
-void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk,
-                            int len, const void *data)
+static void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk,
+                                   int len, const void *data)
 {
        if (skb_tailroom(chunk->skb) >= len)
                return sctp_addto_chunk(chunk, len, data);
@@ -1967,13 +1969,13 @@ static int sctp_verify_ext_param(struct net *net, union sctp_params param)
 
        for (i = 0; i < num_ext; i++) {
                switch (param.ext->chunks[i]) {
-                   case SCTP_CID_AUTH:
-                           have_auth = 1;
-                           break;
-                   case SCTP_CID_ASCONF:
-                   case SCTP_CID_ASCONF_ACK:
-                           have_asconf = 1;
-                           break;
+               case SCTP_CID_AUTH:
+                       have_auth = 1;
+                       break;
+               case SCTP_CID_ASCONF:
+               case SCTP_CID_ASCONF_ACK:
+                       have_asconf = 1;
+                       break;
                }
        }
 
@@ -2000,25 +2002,24 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
 
        for (i = 0; i < num_ext; i++) {
                switch (param.ext->chunks[i]) {
-                   case SCTP_CID_FWD_TSN:
-                           if (net->sctp.prsctp_enable &&
-                               !asoc->peer.prsctp_capable)
+               case SCTP_CID_FWD_TSN:
+                       if (net->sctp.prsctp_enable && !asoc->peer.prsctp_capable)
                                    asoc->peer.prsctp_capable = 1;
-                           break;
-                   case SCTP_CID_AUTH:
-                           /* if the peer reports AUTH, assume that he
-                            * supports AUTH.
-                            */
-                           if (net->sctp.auth_enable)
-                                   asoc->peer.auth_capable = 1;
-                           break;
-                   case SCTP_CID_ASCONF:
-                   case SCTP_CID_ASCONF_ACK:
-                           if (net->sctp.addip_enable)
-                                   asoc->peer.asconf_capable = 1;
-                           break;
-                   default:
-                           break;
+                       break;
+               case SCTP_CID_AUTH:
+                       /* if the peer reports AUTH, assume that he
+                        * supports AUTH.
+                        */
+                       if (net->sctp.auth_enable)
+                               asoc->peer.auth_capable = 1;
+                       break;
+               case SCTP_CID_ASCONF:
+               case SCTP_CID_ASCONF_ACK:
+                       if (net->sctp.addip_enable)
+                               asoc->peer.asconf_capable = 1;
+                       break;
+               default:
+                       break;
                }
        }
 }
@@ -2251,7 +2252,7 @@ int sctp_verify_init(struct net *net, const struct sctp_association *asoc,
         * VIOLATION error.  We build the ERROR chunk here and let the normal
         * error handling code build and send the packet.
         */
-       if (param.v != (void*)chunk->chunk_end)
+       if (param.v != (void *)chunk->chunk_end)
                return sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
 
        /* The only missing mandatory param possible today is
@@ -2266,14 +2267,14 @@ int sctp_verify_init(struct net *net, const struct sctp_association *asoc,
 
                result = sctp_verify_param(net, asoc, param, cid, chunk, errp);
                switch (result) {
-                   case SCTP_IERROR_ABORT:
-                   case SCTP_IERROR_NOMEM:
-                               return 0;
-                   case SCTP_IERROR_ERROR:
-                               return 1;
-                   case SCTP_IERROR_NO_ERROR:
-                   default:
-                               break;
+               case SCTP_IERROR_ABORT:
+               case SCTP_IERROR_NOMEM:
+                       return 0;
+               case SCTP_IERROR_ERROR:
+                       return 1;
+               case SCTP_IERROR_NO_ERROR:
+               default:
+                       break;
                }
 
        } /* for (loop through all parameters) */
@@ -2308,7 +2309,7 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
         * added as the primary transport.  The source address seems to
         * be a a better choice than any of the embedded addresses.
         */
-       if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
+       if (!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
                goto nomem;
 
        if (sctp_cmp_addr_exact(sctp_source(chunk), peer_addr))
@@ -3334,7 +3335,7 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
 
        while (asconf_ack_len > 0) {
                if (asconf_ack_param->crr_id == asconf_param->crr_id) {
-                       switch(asconf_ack_param->param_hdr.type) {
+                       switch (asconf_ack_param->param_hdr.type) {
                        case SCTP_PARAM_SUCCESS_REPORT:
                                return SCTP_ERROR_NO_ERROR;
                        case SCTP_PARAM_ERR_CAUSE:
index 02b7ad1ff467cef05301f8f6818f1e5bba91b0e7..ded6db66fb245f1fb96be8910fb2ad9e06bfbd95 100644 (file)
@@ -404,7 +404,7 @@ void sctp_generate_proto_unreach_event(unsigned long data)
        struct sctp_transport *transport = (struct sctp_transport *) data;
        struct sctp_association *asoc = transport->asoc;
        struct net *net = sock_net(asoc->base.sk);
-       
+
        sctp_bh_lock_sock(asoc->base.sk);
        if (sock_owned_by_user(asoc->base.sk)) {
                pr_debug("%s: sock is busy\n", __func__);
@@ -543,7 +543,7 @@ static void sctp_cmd_init_failed(sctp_cmd_seq_t *commands,
 {
        struct sctp_ulpevent *event;
 
-       event = sctp_ulpevent_make_assoc_change(asoc,0, SCTP_CANT_STR_ASSOC,
+       event = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_CANT_STR_ASSOC,
                                                (__u16)error, 0, 0, NULL,
                                                GFP_ATOMIC);
 
@@ -1115,7 +1115,7 @@ int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype,
        sctp_init_cmd_seq(&commands);
 
        debug_pre_sfn();
-       status = (*state_fn->fn)(net, ep, asoc, subtype, event_arg, &commands);
+       status = state_fn->fn(net, ep, asoc, subtype, event_arg, &commands);
        debug_post_sfn();
 
        error = sctp_side_effects(event_type, subtype, state,
index ee02771d8b9c3da7205d160b89897b33a9479e54..483dcd71b3c5f76a17dc66aee156c0b6caf60bac 100644 (file)
@@ -2945,7 +2945,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net,
                return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
                                                  commands);
 
-       error = sctp_eat_data(asoc, chunk, commands );
+       error = sctp_eat_data(asoc, chunk, commands);
        switch (error) {
        case SCTP_IERROR_NO_ERROR:
                break;
@@ -3066,7 +3066,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(struct net *net,
                return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
                                                  commands);
 
-       error = sctp_eat_data(asoc, chunk, commands );
+       error = sctp_eat_data(asoc, chunk, commands);
        switch (error) {
        case SCTP_IERROR_NO_ERROR:
        case SCTP_IERROR_HIGH_TSN:
@@ -3681,8 +3681,7 @@ sctp_disposition_t sctp_sf_do_asconf(struct net *net,
        asconf_ack->dest = chunk->source;
        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack));
        if (asoc->new_transport) {
-               sctp_sf_heartbeat(ep, asoc, type, asoc->new_transport,
-                    commands);
+               sctp_sf_heartbeat(ep, asoc, type, asoc->new_transport, commands);
                ((struct sctp_association *)asoc)->new_transport = NULL;
        }
 
@@ -3765,7 +3764,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net,
                 */
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
-               sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+               sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ECONNABORTED));
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
@@ -3799,7 +3798,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net,
                /* We are going to ABORT, so we might as well stop
                 * processing the rest of the chunks in the packet.
                 */
-               sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+               sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ECONNABORTED));
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
@@ -4451,7 +4450,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
                                     void *arg,
                                     sctp_cmd_seq_t *commands)
 {
-       static const char err_str[]="The following chunk had invalid length:";
+       static const char err_str[] = "The following chunk had invalid length:";
 
        return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str,
                                        sizeof(err_str));
@@ -4514,7 +4513,7 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
                                     void *arg,
                                     sctp_cmd_seq_t *commands)
 {
-       static const char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:";
+       static const char err_str[] = "The cumulative tsn ack beyond the max tsn currently sent:";
 
        return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str,
                                        sizeof(err_str));
@@ -4534,7 +4533,7 @@ static sctp_disposition_t sctp_sf_violation_chunk(
                                     void *arg,
                                     sctp_cmd_seq_t *commands)
 {
-       static const char err_str[]="The following chunk violates protocol:";
+       static const char err_str[] = "The following chunk violates protocol:";
 
        if (!asoc)
                return sctp_sf_violation(net, ep, asoc, type, arg, commands);
@@ -4610,7 +4609,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(struct net *net,
                                       sctp_cmd_seq_t *commands)
 {
        struct sctp_chunk *repl;
-       struct sctp_associationmy_asoc;
+       struct sctp_association *my_asoc;
 
        /* The comment below says that we enter COOKIE-WAIT AFTER
         * sending the INIT, but that doesn't actually work in our
@@ -6000,7 +5999,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
                /* Special case the INIT-ACK as there is no peer's vtag
                 * yet.
                 */
-               switch(chunk->chunk_hdr->type) {
+               switch (chunk->chunk_hdr->type) {
                case SCTP_CID_INIT_ACK:
                {
                        sctp_initack_chunk_t *initack;
@@ -6017,7 +6016,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
                /* Special case the INIT and stale COOKIE_ECHO as there is no
                 * vtag yet.
                 */
-               switch(chunk->chunk_hdr->type) {
+               switch (chunk->chunk_hdr->type) {
                case SCTP_CID_INIT:
                {
                        sctp_init_chunk_t *init;
@@ -6207,7 +6206,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
         */
        if (*sk->sk_prot_creator->memory_pressure) {
                if (sctp_tsnmap_has_gap(map) &&
-                  (sctp_tsnmap_get_ctsn(map) + 1) == tsn) {
+                   (sctp_tsnmap_get_ctsn(map) + 1) == tsn) {
                        pr_debug("%s: under pressure, reneging for tsn:%u\n",
                                 __func__, tsn);
                        deliver = SCTP_CMD_RENEGE;
@@ -6231,7 +6230,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
                /* We are going to ABORT, so we might as well stop
                 * processing the rest of the chunks in the packet.
                 */
-               sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+               sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ECONNABORTED));
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
index a4f17437fb220ca9c1ac50fd89dffd25a644c091..a987d54b379c5c57513ef2f0fac046c8cae2bf75 100644 (file)
@@ -69,7 +69,7 @@ static const sctp_sm_table_entry_t bug = {
        if ((event_subtype._type > (_max))) {                           \
                pr_warn("table %p possible attack: event %d exceeds max %d\n", \
                        _table, event_subtype._type, _max);             \
-               rtn = &bug;                                             \
+               rtn = &bug;                                             \
        } else                                                          \
                rtn = &_table[event_subtype._type][(int)state];         \
                                                                        \
index d39fd0c2c4cf98a80ad4c9a81e72f8d9e40501f8..d32dae78a4868439646dbe3b6d418a90ae5b4305 100644 (file)
@@ -82,7 +82,7 @@ static int sctp_writeable(struct sock *sk);
 static void sctp_wfree(struct sk_buff *skb);
 static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p,
                                size_t msg_len);
-static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p);
+static int sctp_wait_for_packet(struct sock *sk, int *err, long *timeo_p);
 static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);
 static int sctp_wait_for_accept(struct sock *sk, long timeo);
 static void sctp_wait_for_close(struct sock *sk, long timeo);
@@ -952,7 +952,7 @@ int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw)
  *
  * Returns 0 if ok, <0 errno code on error.
  */
-static int sctp_setsockopt_bindx(struct socksk,
+static int sctp_setsockopt_bindx(struct sock *sk,
                                 struct sockaddr __user *addrs,
                                 int addrs_size, int op)
 {
@@ -1039,7 +1039,7 @@ out:
  * Common routine for handling connect() and sctp_connectx().
  * Connect will come in with just a single address.
  */
-static int __sctp_connect(struct socksk,
+static int __sctp_connect(struct sock *sk,
                          struct sockaddr *kaddrs,
                          int addrs_size,
                          sctp_assoc_t *assoc_id)
@@ -1299,7 +1299,7 @@ out_free:
  *
  * Returns >=0 if ok, <0 errno code on error.
  */
-static int __sctp_setsockopt_connectx(struct socksk,
+static int __sctp_setsockopt_connectx(struct sock *sk,
                                      struct sockaddr __user *addrs,
                                      int addrs_size,
                                      sctp_assoc_t *assoc_id)
@@ -1337,7 +1337,7 @@ static int __sctp_setsockopt_connectx(struct sock* sk,
  * This is an older interface.  It's kept for backward compatibility
  * to the option that doesn't provide association id.
  */
-static int sctp_setsockopt_connectx_old(struct socksk,
+static int sctp_setsockopt_connectx_old(struct sock *sk,
                                        struct sockaddr __user *addrs,
                                        int addrs_size)
 {
@@ -1350,7 +1350,7 @@ static int sctp_setsockopt_connectx_old(struct sock* sk,
  * indication to the call.  Error is always negative and association id is
  * always positive.
  */
-static int sctp_setsockopt_connectx(struct socksk,
+static int sctp_setsockopt_connectx(struct sock *sk,
                                    struct sockaddr __user *addrs,
                                    int addrs_size)
 {
@@ -1373,7 +1373,7 @@ static int sctp_setsockopt_connectx(struct sock* sk,
  * addrs_num structure member.  That way we can re-use the existing
  * code.
  */
-static int sctp_getsockopt_connectx3(struct socksk, int len,
+static int sctp_getsockopt_connectx3(struct sock *sk, int len,
                                     char __user *optval,
                                     int __user *optlen)
 {
@@ -1568,7 +1568,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
        struct net *net = sock_net(sk);
        struct sctp_sock *sp;
        struct sctp_endpoint *ep;
-       struct sctp_association *new_asoc=NULL, *asoc=NULL;
+       struct sctp_association *new_asoc = NULL, *asoc = NULL;
        struct sctp_transport *transport, *chunk_tp;
        struct sctp_chunk *chunk;
        union sctp_addr to;
@@ -2462,7 +2462,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
        int hb_change, pmtud_change, sackdelay_change;
 
        if (optlen != sizeof(struct sctp_paddrparams))
-               return - EINVAL;
+               return -EINVAL;
 
        if (copy_from_user(&params, optval, optlen))
                return -EFAULT;
@@ -2483,7 +2483,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
        /* If an address other than INADDR_ANY is specified, and
         * no transport is found, then the request is invalid.
         */
-       if (!sctp_is_any(sk, ( union sctp_addr *)&params.spp_address)) {
+       if (!sctp_is_any(sk, (union sctp_addr *)&params.spp_address)) {
                trans = sctp_addr_id2transport(sk, &params.spp_address,
                                               params.spp_assoc_id);
                if (!trans)
@@ -2578,8 +2578,11 @@ static int sctp_setsockopt_delayed_ack(struct sock *sk,
                if (params.sack_delay == 0 && params.sack_freq == 0)
                        return 0;
        } else if (optlen == sizeof(struct sctp_assoc_value)) {
-               pr_warn("Use of struct sctp_assoc_value in delayed_ack socket option deprecated\n");
-               pr_warn("Use struct sctp_sack_info instead\n");
+               pr_warn_ratelimited(DEPRECATED
+                                   "%s (pid %d) "
+                                   "Use of struct sctp_assoc_value in delayed_ack socket option.\n"
+                                   "Use struct sctp_sack_info instead\n",
+                                   current->comm, task_pid_nr(current));
                if (copy_from_user(&params, optval, optlen))
                        return -EFAULT;
 
@@ -2588,7 +2591,7 @@ static int sctp_setsockopt_delayed_ack(struct sock *sk,
                else
                        params.sack_freq = 0;
        } else
-               return - EINVAL;
+               return -EINVAL;
 
        /* Validate value parameter. */
        if (params.sack_delay > 500)
@@ -2994,8 +2997,11 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
        int val;
 
        if (optlen == sizeof(int)) {
-               pr_warn("Use of int in maxseg socket option deprecated\n");
-               pr_warn("Use struct sctp_assoc_value instead\n");
+               pr_warn_ratelimited(DEPRECATED
+                                   "%s (pid %d) "
+                                   "Use of int in maxseg socket option.\n"
+                                   "Use struct sctp_assoc_value instead\n",
+                                   current->comm, task_pid_nr(current));
                if (copy_from_user(&val, optval, optlen))
                        return -EFAULT;
                params.assoc_id = 0;
@@ -3252,8 +3258,11 @@ static int sctp_setsockopt_maxburst(struct sock *sk,
        int assoc_id = 0;
 
        if (optlen == sizeof(int)) {
-               pr_warn("Use of int in max_burst socket option deprecated\n");
-               pr_warn("Use struct sctp_assoc_value instead\n");
+               pr_warn_ratelimited(DEPRECATED
+                                   "%s (pid %d) "
+                                   "Use of int in max_burst socket option deprecated.\n"
+                                   "Use struct sctp_assoc_value instead\n",
+                                   current->comm, task_pid_nr(current));
                if (copy_from_user(&val, optval, optlen))
                        return -EFAULT;
        } else if (optlen == sizeof(struct sctp_assoc_value)) {
@@ -3332,7 +3341,7 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk,
        if (optlen < sizeof(struct sctp_hmacalgo))
                return -EINVAL;
 
-       hmacs= memdup_user(optval, optlen);
+       hmacs = memdup_user(optval, optlen);
        if (IS_ERR(hmacs))
                return PTR_ERR(hmacs);
 
@@ -3370,7 +3379,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
        if (optlen <= sizeof(struct sctp_authkey))
                return -EINVAL;
 
-       authkey= memdup_user(optval, optlen);
+       authkey = memdup_user(optval, optlen);
        if (IS_ERR(authkey))
                return PTR_ERR(authkey);
 
@@ -3924,7 +3933,7 @@ static int sctp_init_sock(struct sock *sk)
         */
        sp->hbinterval  = net->sctp.hb_interval;
        sp->pathmaxrxt  = net->sctp.max_retrans_path;
-       sp->pathmtu     = 0; // allow default discovery
+       sp->pathmtu     = 0; /* allow default discovery */
        sp->sackdelay   = net->sctp.sack_timeout;
        sp->sackfreq    = 2;
        sp->param_flags = SPP_HB_ENABLE |
@@ -4467,7 +4476,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
        /* If an address other than INADDR_ANY is specified, and
         * no transport is found, then the request is invalid.
         */
-       if (!sctp_is_any(sk, ( union sctp_addr *)&params.spp_address)) {
+       if (!sctp_is_any(sk, (union sctp_addr *)&params.spp_address)) {
                trans = sctp_addr_id2transport(sk, &params.spp_address,
                                               params.spp_assoc_id);
                if (!trans) {
@@ -4573,12 +4582,15 @@ static int sctp_getsockopt_delayed_ack(struct sock *sk, int len,
                if (copy_from_user(&params, optval, len))
                        return -EFAULT;
        } else if (len == sizeof(struct sctp_assoc_value)) {
-               pr_warn("Use of struct sctp_assoc_value in delayed_ack socket option deprecated\n");
-               pr_warn("Use struct sctp_sack_info instead\n");
+               pr_warn_ratelimited(DEPRECATED
+                                   "%s (pid %d) "
+                                   "Use of struct sctp_assoc_value in delayed_ack socket option.\n"
+                                   "Use struct sctp_sack_info instead\n",
+                                   current->comm, task_pid_nr(current));
                if (copy_from_user(&params, optval, len))
                        return -EFAULT;
        } else
-               return - EINVAL;
+               return -EINVAL;
 
        /* Get association, if sack_assoc_id != 0 and the socket is a one
         * to many style socket, and an association was not found, then
@@ -4668,8 +4680,8 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
        if (!asoc)
                return -EINVAL;
 
-       to = optval + offsetof(struct sctp_getaddrs,addrs);
-       space_left = len - offsetof(struct sctp_getaddrs,addrs);
+       to = optval + offsetof(struct sctp_getaddrs, addrs);
+       space_left = len - offsetof(struct sctp_getaddrs, addrs);
 
        list_for_each_entry(from, &asoc->peer.transport_addr_list,
                                transports) {
@@ -4729,7 +4741,7 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
                memcpy(to, &temp, addrlen);
 
                to += addrlen;
-               cnt ++;
+               cnt++;
                space_left -= addrlen;
                *bytes_copied += addrlen;
        }
@@ -4778,8 +4790,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
                bp = &asoc->base.bind_addr;
        }
 
-       to = optval + offsetof(struct sctp_getaddrs,addrs);
-       space_left = len - offsetof(struct sctp_getaddrs,addrs);
+       to = optval + offsetof(struct sctp_getaddrs, addrs);
+       space_left = len - offsetof(struct sctp_getaddrs, addrs);
 
        addrs = kmalloc(space_left, GFP_KERNEL);
        if (!addrs)
@@ -4818,7 +4830,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
                memcpy(buf, &temp, addrlen);
                buf += addrlen;
                bytes_copied += addrlen;
-               cnt ++;
+               cnt++;
                space_left -= addrlen;
        }
 
@@ -5090,7 +5102,7 @@ static int sctp_getsockopt_associnfo(struct sock *sk, int len,
                assocparams.sasoc_cookie_life = ktime_to_ms(asoc->cookie_life);
 
                list_for_each(pos, &asoc->peer.transport_addr_list) {
-                       cnt ++;
+                       cnt++;
                }
 
                assocparams.sasoc_number_peer_destinations = cnt;
@@ -5218,8 +5230,11 @@ static int sctp_getsockopt_maxseg(struct sock *sk, int len,
        struct sctp_association *asoc;
 
        if (len == sizeof(int)) {
-               pr_warn("Use of int in maxseg socket option deprecated\n");
-               pr_warn("Use struct sctp_assoc_value instead\n");
+               pr_warn_ratelimited(DEPRECATED
+                                   "%s (pid %d) "
+                                   "Use of int in maxseg socket option.\n"
+                                   "Use struct sctp_assoc_value instead\n",
+                                   current->comm, task_pid_nr(current));
                params.assoc_id = 0;
        } else if (len >= sizeof(struct sctp_assoc_value)) {
                len = sizeof(struct sctp_assoc_value);
@@ -5310,8 +5325,11 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
        struct sctp_association *asoc;
 
        if (len == sizeof(int)) {
-               pr_warn("Use of int in max_burst socket option deprecated\n");
-               pr_warn("Use struct sctp_assoc_value instead\n");
+               pr_warn_ratelimited(DEPRECATED
+                                   "%s (pid %d) "
+                                   "Use of int in max_burst socket option.\n"
+                                   "Use struct sctp_assoc_value instead\n",
+                                   current->comm, task_pid_nr(current));
                params.assoc_id = 0;
        } else if (len >= sizeof(struct sctp_assoc_value)) {
                len = sizeof(struct sctp_assoc_value);
@@ -5443,7 +5461,8 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
                return -EFAULT;
 num:
        len = sizeof(struct sctp_authchunks) + num_chunks;
-       if (put_user(len, optlen)) return -EFAULT;
+       if (put_user(len, optlen))
+               return -EFAULT;
        if (put_user(num_chunks, &p->gauth_number_of_chunks))
                return -EFAULT;
        return 0;
@@ -5475,7 +5494,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
                return -EINVAL;
 
        if (asoc)
-               ch = (struct sctp_chunks_param*)asoc->c.auth_chunks;
+               ch = (struct sctp_chunks_param *)asoc->c.auth_chunks;
        else
                ch = sctp_sk(sk)->ep->auth_chunk_list;
 
@@ -6417,7 +6436,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs)
  * Note: This function is the same function as in core/datagram.c
  * with a few modifications to make lksctp work.
  */
-static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p)
+static int sctp_wait_for_packet(struct sock *sk, int *err, long *timeo_p)
 {
        int error;
        DEFINE_WAIT(wait);
index 9dd5ac084663b79619b54271cbc1b44c72267db0..7135e617ab0ffa7343a2d698e94c6a71d5334d9d 100644 (file)
@@ -424,7 +424,7 @@ void sctp_sysctl_net_unregister(struct net *net)
        kfree(table);
 }
 
-static struct ctl_table_header * sctp_sysctl_header;
+static struct ctl_table_header *sctp_sysctl_header;
 
 /* Sysctl registration.  */
 void sctp_sysctl_register(void)
index a67470083be8a42de0ce6a7c22a1ece650fa3290..5dc94117e9d42d7e1eb24be6d8015c89feae7b6d 100644 (file)
@@ -43,9 +43,9 @@
 #include <net/sctp/sm.h>
 
 /* Forward declarations for internal helpers.  */
-static struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
+static struct sctp_ulpevent *sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
                                              struct sctp_ulpevent *);
-static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *,
+static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *,
                                              struct sctp_ulpevent *);
 static void sctp_ulpq_reasm_drain(struct sctp_ulpq *ulpq);
 
@@ -107,7 +107,7 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
        event = sctp_ulpq_reasm(ulpq, event);
 
        /* Do ordering if needed.  */
-       if ((event) && (event->msg_flags & MSG_EOR)){
+       if ((event) && (event->msg_flags & MSG_EOR)) {
                /* Create a temporary list to collect chunks on.  */
                skb_queue_head_init(&temp);
                __skb_queue_tail(&temp, sctp_event2skb(event));
@@ -336,7 +336,8 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct net *net,
                pos = f_frag->next;
 
        /* Get the last skb in the f_frag's frag_list if present. */
-       for (last = list; list; last = list, list = list->next);
+       for (last = list; list; last = list, list = list->next)
+               ;
 
        /* Add the list of remaining fragments to the first fragments
         * frag_list.
@@ -726,7 +727,7 @@ static void sctp_ulpq_reasm_drain(struct sctp_ulpq *ulpq)
 
        while ((event = sctp_ulpq_retrieve_reassembled(ulpq)) != NULL) {
                /* Do ordering if needed.  */
-               if ((event) && (event->msg_flags & MSG_EOR)){
+               if ((event) && (event->msg_flags & MSG_EOR)) {
                        skb_queue_head_init(&temp);
                        __skb_queue_tail(&temp, sctp_event2skb(event));
 
index 4c2a80b3c01e102dfe7e17d6d17378f51b9b929d..bf860d9e75af2363e6538ee525c60bf7c0821b6c 100644 (file)
@@ -794,7 +794,7 @@ void tipc_bclink_init(void)
 void tipc_bclink_stop(void)
 {
        spin_lock_bh(&bc_lock);
-       tipc_link_stop(bcl);
+       tipc_link_purge_queues(bcl);
        spin_unlock_bh(&bc_lock);
 
        memset(bclink, 0, sizeof(*bclink));
index 3bb5f266b0eb4fe803ca6de5f42ade2e11673b6b..2d456ab0e843af28b83e698cbd5d1b4ad8b5b404 100644 (file)
@@ -184,25 +184,6 @@ struct tipc_bearer *tipc_bearer_find(const char *name)
        return NULL;
 }
 
-/**
- * tipc_bearer_find_interface - locates bearer object with matching interface name
- */
-struct tipc_bearer *tipc_bearer_find_interface(const char *if_name)
-{
-       struct tipc_bearer *b_ptr;
-       char *b_if_name;
-       u32 i;
-
-       for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
-               if (!b_ptr->active)
-                       continue;
-               b_if_name = strchr(b_ptr->name, ':') + 1;
-               if (!strcmp(b_if_name, if_name))
-                       return b_ptr;
-       }
-       return NULL;
-}
-
 /**
  * tipc_bearer_get_names - record names of bearers in buffer
  */
@@ -560,7 +541,7 @@ static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
        if (likely(b_ptr)) {
                if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
                        buf->next = NULL;
-                       tipc_recv_msg(buf, b_ptr);
+                       tipc_rcv(buf, b_ptr);
                        rcu_read_unlock();
                        return NET_RX_SUCCESS;
                }
index fa95c34ca92648633679cc43692e7cfd6a03bc86..4f5db9ad5bf639056bc56f1284d7400e87095dcc 100644 (file)
@@ -161,8 +161,7 @@ extern struct tipc_bearer tipc_bearers[];
  * TIPC routines available to supported media types
  */
 
-void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
-
+void tipc_rcv(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
 int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);
 int tipc_disable_bearer(const char *name);
 
@@ -190,7 +189,6 @@ struct sk_buff *tipc_bearer_get_names(void);
 void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest);
 void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest);
 struct tipc_bearer *tipc_bearer_find(const char *name);
-struct tipc_bearer *tipc_bearer_find_interface(const char *if_name);
 struct tipc_media *tipc_media_find(const char *name);
 int tipc_bearer_setup(void);
 void tipc_bearer_cleanup(void);
index bc849f1efa167739d4831ea0f013f28541de2a79..412ff41b861166e5511ae3ad8c875fa27039ac6b 100644 (file)
@@ -50,6 +50,7 @@
  * @dest: destination address for request messages
  * @domain: network domain to which links can be established
  * @num_nodes: number of nodes currently discovered (i.e. with an active link)
+ * @lock: spinlock for controlling access to requests
  * @buf: request message to be (repeatedly) sent
  * @timer: timer governing period between requests
  * @timer_intv: current interval between requests (in ms)
@@ -59,6 +60,7 @@ struct tipc_link_req {
        struct tipc_media_addr dest;
        u32 domain;
        int num_nodes;
+       spinlock_t lock;
        struct sk_buff *buf;
        struct timer_list timer;
        unsigned int timer_intv;
@@ -274,7 +276,9 @@ static void disc_update(struct tipc_link_req *req)
  */
 void tipc_disc_add_dest(struct tipc_link_req *req)
 {
+       spin_lock_bh(&req->lock);
        req->num_nodes++;
+       spin_unlock_bh(&req->lock);
 }
 
 /**
@@ -283,8 +287,10 @@ void tipc_disc_add_dest(struct tipc_link_req *req)
  */
 void tipc_disc_remove_dest(struct tipc_link_req *req)
 {
+       spin_lock_bh(&req->lock);
        req->num_nodes--;
        disc_update(req);
+       spin_unlock_bh(&req->lock);
 }
 
 /**
@@ -297,7 +303,7 @@ static void disc_timeout(struct tipc_link_req *req)
 {
        int max_delay;
 
-       spin_lock_bh(&req->bearer->lock);
+       spin_lock_bh(&req->lock);
 
        /* Stop searching if only desired node has been found */
        if (tipc_node(req->domain) && req->num_nodes) {
@@ -325,7 +331,7 @@ static void disc_timeout(struct tipc_link_req *req)
 
        k_start_timer(&req->timer, req->timer_intv);
 exit:
-       spin_unlock_bh(&req->bearer->lock);
+       spin_unlock_bh(&req->lock);
 }
 
 /**
@@ -356,6 +362,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest,
        req->domain = dest_domain;
        req->num_nodes = 0;
        req->timer_intv = TIPC_LINK_REQ_INIT;
+       spin_lock_init(&req->lock);
        k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
        k_start_timer(&req->timer, req->timer_intv);
        b_ptr->link_req = req;
index 3d73144a1ccc4dd59449b3252fb154fe4b339da6..471973ff134f890e03437dec4ce65b436c136da6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * net/tipc/link.c: TIPC link code
  *
- * Copyright (c) 1996-2007, 2012, Ericsson AB
+ * Copyright (c) 1996-2007, 2012-2014, Ericsson AB
  * Copyright (c) 2004-2007, 2010-2013, Wind River Systems
  * All rights reserved.
  *
@@ -78,8 +78,8 @@ static const char *link_unk_evt = "Unknown link event ";
 static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
                                       struct sk_buff *buf);
 static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf);
-static int  link_recv_changeover_msg(struct tipc_link **l_ptr,
-                                    struct sk_buff **buf);
+static int  tipc_link_tunnel_rcv(struct tipc_link **l_ptr,
+                                struct sk_buff **buf);
 static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance);
 static int  link_send_sections_long(struct tipc_port *sender,
                                    struct iovec const *msg_sect,
@@ -87,7 +87,6 @@ static int  link_send_sections_long(struct tipc_port *sender,
 static void link_state_event(struct tipc_link *l_ptr, u32 event);
 static void link_reset_statistics(struct tipc_link *l_ptr);
 static void link_print(struct tipc_link *l_ptr, const char *str);
-static void link_start(struct tipc_link *l_ptr);
 static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf);
 static void tipc_link_send_sync(struct tipc_link *l);
 static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf);
@@ -278,9 +277,11 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
 
        tipc_node_attach_link(n_ptr, l_ptr);
 
-       k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr);
+       k_init_timer(&l_ptr->timer, (Handler)link_timeout,
+                    (unsigned long)l_ptr);
        list_add_tail(&l_ptr->link_list, &b_ptr->links);
-       tipc_k_signal((Handler)link_start, (unsigned long)l_ptr);
+
+       link_state_event(l_ptr, STARTING_EVT);
 
        return l_ptr;
 }
@@ -305,19 +306,13 @@ void tipc_link_delete(struct tipc_link *l_ptr)
        tipc_node_lock(l_ptr->owner);
        tipc_link_reset(l_ptr);
        tipc_node_detach_link(l_ptr->owner, l_ptr);
-       tipc_link_stop(l_ptr);
+       tipc_link_purge_queues(l_ptr);
        list_del_init(&l_ptr->link_list);
        tipc_node_unlock(l_ptr->owner);
        k_term_timer(&l_ptr->timer);
        kfree(l_ptr);
 }
 
-static void link_start(struct tipc_link *l_ptr)
-{
-       tipc_node_lock(l_ptr->owner);
-       link_state_event(l_ptr, STARTING_EVT);
-       tipc_node_unlock(l_ptr->owner);
-}
 
 /**
  * link_schedule_port - schedule port for deferred sending
@@ -403,10 +398,10 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr)
 }
 
 /**
- * tipc_link_stop - purge all inbound and outbound messages associated with link
+ * tipc_link_purge_queues - purge all pkt queues associated with link
  * @l_ptr: pointer to link
  */
-void tipc_link_stop(struct tipc_link *l_ptr)
+void tipc_link_purge_queues(struct tipc_link *l_ptr)
 {
        kfree_skb_list(l_ptr->oldest_deferred_in);
        kfree_skb_list(l_ptr->first_out);
@@ -437,8 +432,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
        tipc_node_link_down(l_ptr->owner, l_ptr);
        tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
 
-       if (was_active_link && tipc_node_active_links(l_ptr->owner) &&
-           l_ptr->owner->permit_changeover) {
+       if (was_active_link && tipc_node_active_links(l_ptr->owner)) {
                l_ptr->reset_checkpoint = checkpoint;
                l_ptr->exp_msg_count = START_CHANGEOVER;
        }
@@ -1169,7 +1163,7 @@ reject:
 /*
  * tipc_link_push_packet: Push one unsent packet to the media
  */
-u32 tipc_link_push_packet(struct tipc_link *l_ptr)
+static u32 tipc_link_push_packet(struct tipc_link *l_ptr)
 {
        struct sk_buff *buf = l_ptr->first_out;
        u32 r_q_size = l_ptr->retransm_queue_size;
@@ -1422,14 +1416,14 @@ static int link_recv_buf_validate(struct sk_buff *buf)
 }
 
 /**
- * tipc_recv_msg - process TIPC messages arriving from off-node
+ * tipc_rcv - process TIPC packets/messages arriving from off-node
  * @head: pointer to message buffer chain
  * @tb_ptr: pointer to bearer message arrived on
  *
  * Invoked with no locks held.  Bearer pointer must point to a valid bearer
  * structure (i.e. cannot be NULL), but bearer can be inactive.
  */
-void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
+void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr)
 {
        read_lock_bh(&tipc_net_lock);
        while (head) {
@@ -1603,7 +1597,7 @@ deliver:
                        continue;
                case CHANGEOVER_PROTOCOL:
                        type = msg_type(msg);
-                       if (link_recv_changeover_msg(&l_ptr, &buf)) {
+                       if (tipc_link_tunnel_rcv(&l_ptr, &buf)) {
                                msg = buf_msg(buf);
                                seq_no = msg_seqno(msg);
                                if (type == ORIGINAL_MSG)
@@ -1837,8 +1831,6 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
                if (tipc_own_addr > msg_prevnode(msg))
                        l_ptr->b_ptr->net_plane = msg_net_plane(msg);
 
-       l_ptr->owner->permit_changeover = msg_redundant_link(msg);
-
        switch (msg_type(msg)) {
 
        case RESET_MSG:
@@ -1954,13 +1946,13 @@ exit:
 }
 
 
-/*
- * tipc_link_tunnel(): Send one message via a link belonging to
- * another bearer. Owner node is locked.
+/* tipc_link_tunnel_xmit(): Tunnel one packet via a link belonging to
+ * a different bearer. Owner node is locked.
  */
-static void tipc_link_tunnel(struct tipc_link *l_ptr,
-                            struct tipc_msg *tunnel_hdr, struct tipc_msg *msg,
-                            u32 selector)
+static void tipc_link_tunnel_xmit(struct tipc_link *l_ptr,
+                                 struct tipc_msg *tunnel_hdr,
+                                 struct tipc_msg *msg,
+                                 u32 selector)
 {
        struct tipc_link *tunnel;
        struct sk_buff *buf;
@@ -1983,12 +1975,13 @@ static void tipc_link_tunnel(struct tipc_link *l_ptr,
 }
 
 
-
-/*
- * changeover(): Send whole message queue via the remaining link
- *               Owner node is locked.
+/* tipc_link_failover_send_queue(): A link has gone down, but a second
+ * link is still active. We can do failover. Tunnel the failing link's
+ * whole send queue via the remaining link. This way, we don't lose
+ * any packets, and sequence order is preserved for subsequent traffic
+ * sent over the remaining link. Owner node is locked.
  */
-void tipc_link_changeover(struct tipc_link *l_ptr)
+void tipc_link_failover_send_queue(struct tipc_link *l_ptr)
 {
        u32 msgcount = l_ptr->out_queue_size;
        struct sk_buff *crs = l_ptr->first_out;
@@ -1999,11 +1992,6 @@ void tipc_link_changeover(struct tipc_link *l_ptr)
        if (!tunnel)
                return;
 
-       if (!l_ptr->owner->permit_changeover) {
-               pr_warn("%speer did not permit changeover\n", link_co_err);
-               return;
-       }
-
        tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
                 ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr);
        msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
@@ -2037,20 +2025,30 @@ void tipc_link_changeover(struct tipc_link *l_ptr)
                        msgcount = msg_msgcnt(msg);
                        while (msgcount--) {
                                msg_set_seqno(m, msg_seqno(msg));
-                               tipc_link_tunnel(l_ptr, &tunnel_hdr, m,
-                                                msg_link_selector(m));
+                               tipc_link_tunnel_xmit(l_ptr, &tunnel_hdr, m,
+                                                     msg_link_selector(m));
                                pos += align(msg_size(m));
                                m = (struct tipc_msg *)pos;
                        }
                } else {
-                       tipc_link_tunnel(l_ptr, &tunnel_hdr, msg,
-                                        msg_link_selector(msg));
+                       tipc_link_tunnel_xmit(l_ptr, &tunnel_hdr, msg,
+                                             msg_link_selector(msg));
                }
                crs = crs->next;
        }
 }
 
-void tipc_link_send_duplicate(struct tipc_link *l_ptr, struct tipc_link *tunnel)
+/* tipc_link_dup_send_queue(): A second link has become active. Tunnel a
+ * duplicate of the first link's send queue via the new link. This way, we
+ * are guaranteed that currently queued packets from a socket are delivered
+ * before future traffic from the same socket, even if this is using the
+ * new link. The last arriving copy of each duplicate packet is dropped at
+ * the receiving end by the regular protocol check, so packet cardinality
+ * and sequence order is preserved per sender/receiver socket pair.
+ * Owner node is locked.
+ */
+void tipc_link_dup_send_queue(struct tipc_link *l_ptr,
+                             struct tipc_link *tunnel)
 {
        struct sk_buff *iter;
        struct tipc_msg tunnel_hdr;
@@ -2106,12 +2104,14 @@ static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos)
        return eb;
 }
 
-/*
- *  link_recv_changeover_msg(): Receive tunneled packet sent
- *  via other link. Node is locked. Return extracted buffer.
+/*  tipc_link_tunnel_rcv(): Receive a tunneled packet, sent
+ *  via other link as result of a failover (ORIGINAL_MSG) or
+ *  a new active link (DUPLICATE_MSG). Failover packets are
+ *  returned to the active link for delivery upwards.
+ *  Owner node is locked.
  */
-static int link_recv_changeover_msg(struct tipc_link **l_ptr,
-                                   struct sk_buff **buf)
+static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr,
+                               struct sk_buff **buf)
 {
        struct sk_buff *tunnel_buf = *buf;
        struct tipc_link *dest_link;
index 424b1dfe436b44ee5e1fddc86ae0ba431a86833b..3b6aa65b608c119311d3ef25429fbce2764f9a46 100644 (file)
@@ -216,16 +216,20 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
                              struct tipc_bearer *b_ptr,
                              const struct tipc_media_addr *media_addr);
 void tipc_link_delete(struct tipc_link *l_ptr);
-void tipc_link_changeover(struct tipc_link *l_ptr);
-void tipc_link_send_duplicate(struct tipc_link *l_ptr, struct tipc_link *dest);
+void tipc_link_failover_send_queue(struct tipc_link *l_ptr);
+void tipc_link_dup_send_queue(struct tipc_link *l_ptr,
+                             struct tipc_link *dest);
 void tipc_link_reset_fragments(struct tipc_link *l_ptr);
 int tipc_link_is_up(struct tipc_link *l_ptr);
 int tipc_link_is_active(struct tipc_link *l_ptr);
-u32 tipc_link_push_packet(struct tipc_link *l_ptr);
-void tipc_link_stop(struct tipc_link *l_ptr);
-struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd);
-struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space);
-struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space);
+void tipc_link_purge_queues(struct tipc_link *l_ptr);
+struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area,
+                                    int req_tlv_space,
+                                    u16 cmd);
+struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area,
+                                        int req_tlv_space);
+struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area,
+                                         int req_tlv_space);
 void tipc_link_reset(struct tipc_link *l_ptr);
 int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector);
 void tipc_link_send_names(struct list_head *message_list, u32 dest);
index bf1ac89b4806a71cfe8179f2e743e22cb9dbea97..efe4d41bf11bacb258e3096dc4619e97828c2904 100644 (file)
@@ -162,7 +162,7 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
                pr_info("New link <%s> becomes standby\n", l_ptr->name);
                return;
        }
-       tipc_link_send_duplicate(active[0], l_ptr);
+       tipc_link_dup_send_queue(active[0], l_ptr);
        if (l_ptr->priority == active[0]->priority) {
                active[0] = l_ptr;
                return;
@@ -225,7 +225,7 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
        if (active[0] == l_ptr)
                node_select_active_links(n_ptr);
        if (tipc_node_is_up(n_ptr))
-               tipc_link_changeover(l_ptr);
+               tipc_link_failover_send_queue(l_ptr);
        else
                node_lost_contact(n_ptr);
 }
@@ -235,11 +235,6 @@ int tipc_node_active_links(struct tipc_node *n_ptr)
        return n_ptr->active_links[0] != NULL;
 }
 
-int tipc_node_redundant_links(struct tipc_node *n_ptr)
-{
-       return n_ptr->working_links > 1;
-}
-
 int tipc_node_is_up(struct tipc_node *n_ptr)
 {
        return tipc_node_active_links(n_ptr);
index e5e96c04e1676a91af811c8c270ce42296b27636..63e2e8ead2fe5d08d50a4d26f0337b79a9961c8b 100644 (file)
@@ -64,7 +64,6 @@
  * @working_links: number of working links to node (both active and standby)
  * @block_setup: bit mask of conditions preventing link establishment to node
  * @link_cnt: number of links to node
- * @permit_changeover: non-zero if node has redundant links to this system
  * @signature: node instance identifier
  * @bclink: broadcast-related info
  *    @acked: sequence # of last outbound b'cast message acknowledged by node
@@ -89,7 +88,6 @@ struct tipc_node {
        int link_cnt;
        int working_links;
        int block_setup;
-       int permit_changeover;
        u32 signature;
        struct {
                u32 acked;
@@ -115,7 +113,6 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
 void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
 void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
 int tipc_node_active_links(struct tipc_node *n_ptr);
-int tipc_node_redundant_links(struct tipc_node *n_ptr);
 int tipc_node_is_up(struct tipc_node *n_ptr);
 struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
 struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
index 5fd4c8cec08e083ed3ee04abd30695cd5811d78d..b742b2654525e2b4c7bd7974c0b7ae6f0356156f 100644 (file)
@@ -251,18 +251,15 @@ struct tipc_port *tipc_createport(struct sock *sk,
        return p_ptr;
 }
 
-int tipc_deleteport(u32 ref)
+int tipc_deleteport(struct tipc_port *p_ptr)
 {
-       struct tipc_port *p_ptr;
        struct sk_buff *buf = NULL;
 
-       tipc_withdraw(ref, 0, NULL);
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
+       tipc_withdraw(p_ptr, 0, NULL);
 
-       tipc_ref_discard(ref);
-       tipc_port_unlock(p_ptr);
+       spin_lock_bh(p_ptr->lock);
+       tipc_ref_discard(p_ptr->ref);
+       spin_unlock_bh(p_ptr->lock);
 
        k_cancel_timer(&p_ptr->timer);
        if (p_ptr->connected) {
@@ -704,47 +701,36 @@ int tipc_set_portimportance(u32 ref, unsigned int imp)
 }
 
 
-int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
+                struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        u32 key;
-       int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
+       if (p_ptr->connected)
                return -EINVAL;
+       key = p_ptr->ref + p_ptr->pub_count + 1;
+       if (key == p_ptr->ref)
+               return -EADDRINUSE;
 
-       if (p_ptr->connected)
-               goto exit;
-       key = ref + p_ptr->pub_count + 1;
-       if (key == ref) {
-               res = -EADDRINUSE;
-               goto exit;
-       }
        publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
                                    scope, p_ptr->ref, key);
        if (publ) {
                list_add(&publ->pport_list, &p_ptr->publications);
                p_ptr->pub_count++;
                p_ptr->published = 1;
-               res = 0;
+               return 0;
        }
-exit:
-       tipc_port_unlock(p_ptr);
-       return res;
+       return -EINVAL;
 }
 
-int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
+                 struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        struct publication *tpubl;
        int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
        if (!seq) {
                list_for_each_entry_safe(publ, tpubl,
                                         &p_ptr->publications, pport_list) {
@@ -771,7 +757,6 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
        }
        if (list_empty(&p_ptr->publications))
                p_ptr->published = 0;
-       tipc_port_unlock(p_ptr);
        return res;
 }
 
index 9122535973430edff99e8ee6070a091975dea457..34f12bd4074e49ff8b4c7809bfe0bc706941ec7c 100644 (file)
@@ -116,7 +116,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err);
 
 void tipc_acknowledge(u32 port_ref, u32 ack);
 
-int tipc_deleteport(u32 portref);
+int tipc_deleteport(struct tipc_port *p_ptr);
 
 int tipc_portimportance(u32 portref, unsigned int *importance);
 int tipc_set_portimportance(u32 portref, unsigned int importance);
@@ -127,9 +127,9 @@ int tipc_set_portunreliable(u32 portref, unsigned int isunreliable);
 int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
 int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
 
-int tipc_publish(u32 portref, unsigned int scope,
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
                 struct tipc_name_seq const *name_seq);
-int tipc_withdraw(u32 portref, unsigned int scope,
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
                  struct tipc_name_seq const *name_seq);
 
 int tipc_connect(u32 portref, struct tipc_portid const *port);
index 83f466e57feaa23e3fca04cc2cde4256ada86c33..c8341d1f995e8b68ba1b88856bab88449bfe888a 100644 (file)
@@ -351,7 +351,7 @@ static int release(struct socket *sock)
         * Delete TIPC port; this ensures no more messages are queued
         * (also disconnects an active connection & sends a 'FIN-' to peer)
         */
-       res = tipc_deleteport(tport->ref);
+       res = tipc_deleteport(tport);
 
        /* Discard any remaining (connection-based) messages in receive queue */
        __skb_queue_purge(&sk->sk_receive_queue);
@@ -383,30 +383,46 @@ static int release(struct socket *sock)
  */
 static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
 {
+       struct sock *sk = sock->sk;
        struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
-       u32 portref = tipc_sk_port(sock->sk)->ref;
+       struct tipc_port *tport = tipc_sk_port(sock->sk);
+       int res = -EINVAL;
 
-       if (unlikely(!uaddr_len))
-               return tipc_withdraw(portref, 0, NULL);
+       lock_sock(sk);
+       if (unlikely(!uaddr_len)) {
+               res = tipc_withdraw(tport, 0, NULL);
+               goto exit;
+       }
 
-       if (uaddr_len < sizeof(struct sockaddr_tipc))
-               return -EINVAL;
-       if (addr->family != AF_TIPC)
-               return -EAFNOSUPPORT;
+       if (uaddr_len < sizeof(struct sockaddr_tipc)) {
+               res = -EINVAL;
+               goto exit;
+       }
+       if (addr->family != AF_TIPC) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if (addr->addrtype == TIPC_ADDR_NAME)
                addr->addr.nameseq.upper = addr->addr.nameseq.lower;
-       else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
-               return -EAFNOSUPPORT;
+       else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) &&
            (addr->addr.nameseq.type != TIPC_TOP_SRV) &&
-           (addr->addr.nameseq.type != TIPC_CFG_SRV))
-               return -EACCES;
+           (addr->addr.nameseq.type != TIPC_CFG_SRV)) {
+               res = -EACCES;
+               goto exit;
+       }
 
-       return (addr->scope > 0) ?
-               tipc_publish(portref, addr->scope, &addr->addr.nameseq) :
-               tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq);
+       res = (addr->scope > 0) ?
+               tipc_publish(tport, addr->scope, &addr->addr.nameseq) :
+               tipc_withdraw(tport, -addr->scope, &addr->addr.nameseq);
+exit:
+       release_sock(sk);
+       return res;
 }
 
 /**
@@ -751,13 +767,10 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
 
        /* Handle special cases where there is no connection */
        if (unlikely(sock->state != SS_CONNECTED)) {
-               res = -ENOTCONN;
-
                if (sock->state == SS_UNCONNECTED)
                        res = send_packet(NULL, sock, m, total_len);
-               else if (sock->state == SS_DISCONNECTING)
-                       res = -EPIPE;
-
+               else
+                       res = sock->state == SS_DISCONNECTING ? -EPIPE : -ENOTCONN;
                goto exit;
        }
 
index 324e8d851dc4ca67fd0ded84a927e782c3647c8c..11ee4ed04f73ea2ae0dd1ae6293837785d8fd5f8 100644 (file)
@@ -29,6 +29,7 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
                wdev->beacon_interval = 0;
                wdev->channel = NULL;
                wdev->ssid_len = 0;
+               rdev_set_qos_map(rdev, dev, NULL);
        }
 
        return err;
index 06db6eb5258aefc332fb4fb09ed165562ea8cd7d..d89dee2259b5994b9237100425aae0a3f21b20af 100644 (file)
@@ -203,17 +203,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
 
        rdev->opencount--;
 
-       if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
-               /*
-                * If the scan request wasn't notified as done, set it
-                * to aborted and leak it after a warning. The driver
-                * should have notified us that it ended at the latest
-                * during rdev_stop_p2p_device().
-                */
-               if (WARN_ON(!rdev->scan_req->notified))
-                       rdev->scan_req->aborted = true;
-               ___cfg80211_scan_done(rdev, !rdev->scan_req->notified);
-       }
+       WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
+               !rdev->scan_req->notified);
 }
 
 static int cfg80211_rfkill_set_block(void *data, bool blocked)
@@ -765,13 +756,16 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
 {
        struct net_device *dev = wdev->netdev;
 
+       ASSERT_RTNL();
+
        switch (wdev->iftype) {
        case NL80211_IFTYPE_ADHOC:
                cfg80211_leave_ibss(rdev, dev, true);
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
        case NL80211_IFTYPE_STATION:
-               __cfg80211_stop_sched_scan(rdev, false);
+               if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev)
+                       __cfg80211_stop_sched_scan(rdev, false);
 
                wdev_lock(wdev);
 #ifdef CONFIG_CFG80211_WEXT
@@ -865,11 +859,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                break;
        case NETDEV_DOWN:
                cfg80211_update_iface_num(rdev, wdev->iftype, -1);
-               if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
-                       if (WARN_ON(!rdev->scan_req->notified))
-                               rdev->scan_req->aborted = true;
-                       ___cfg80211_scan_done(rdev, true);
-               }
+               WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
+                       !rdev->scan_req->notified);
 
                if (WARN_ON(rdev->sched_scan_req &&
                            rdev->sched_scan_req->dev == wdev->netdev)) {
index 0a277c33bb027a879d854492ddde295be2c663a0..37ec16d7bb1ab6bf6e4948259aad19eb6e5a58cf 100644 (file)
@@ -67,9 +67,7 @@ struct cfg80211_registered_device {
        struct work_struct scan_done_wk;
        struct work_struct sched_scan_results_wk;
 
-#ifdef CONFIG_NL80211_TESTMODE
-       struct genl_info *testmode_info;
-#endif
+       struct genl_info *cur_cmd_info;
 
        struct work_struct conn_work;
        struct work_struct event_work;
@@ -363,7 +361,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
                                   struct key_params *params, int key_idx,
                                   bool pairwise, const u8 *mac_addr);
 void __cfg80211_scan_done(struct work_struct *wk);
-void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak);
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
 void __cfg80211_sched_scan_results(struct work_struct *wk);
 int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
                               bool driver_initiated);
index 730147ed8e652c625cb035309df687ca08fd5b49..f911c5f9f903d8ccdd791aaf26d950b19ad6dd9f 100644 (file)
@@ -183,6 +183,8 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
        kfree(wdev->connect_keys);
        wdev->connect_keys = NULL;
 
+       rdev_set_qos_map(rdev, dev, NULL);
+
        /*
         * Delete all the keys ... pairwise keys can't really
         * exist any more anyway, but default keys might.
index b0e1869de7de0b0775561c445389f4f2013beb58..885862447b63c3434c0784924de2b984fcfedc25 100644 (file)
@@ -99,6 +99,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
                         const struct mesh_config *conf)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
+       u8 radar_detect_width = 0;
        int err;
 
        BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN);
@@ -177,8 +178,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
        if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
                return -EINVAL;
 
-       err = cfg80211_can_use_chan(rdev, wdev, setup->chandef.chan,
-                                   CHAN_MODE_SHARED);
+       err = cfg80211_chandef_dfs_required(wdev->wiphy, &setup->chandef);
+       if (err < 0)
+               return err;
+       if (err)
+               radar_detect_width = BIT(setup->chandef.width);
+
+       err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
+                                          setup->chandef.chan,
+                                          CHAN_MODE_SHARED,
+                                          radar_detect_width);
        if (err)
                return err;
 
@@ -268,6 +277,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
        if (!err) {
                wdev->mesh_id_len = 0;
                wdev->channel = NULL;
+               rdev_set_qos_map(rdev, dev, NULL);
        }
 
        return err;
index a693f86e59704016e9c8419eb82a8c43185d9642..b4f40fe84a0121381d221fd0c18a65043428fc17 100644 (file)
@@ -53,6 +53,7 @@ enum nl80211_multicast_groups {
        NL80211_MCGRP_SCAN,
        NL80211_MCGRP_REGULATORY,
        NL80211_MCGRP_MLME,
+       NL80211_MCGRP_VENDOR,
        NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
 };
 
@@ -61,6 +62,7 @@ static const struct genl_multicast_group nl80211_mcgrps[] = {
        [NL80211_MCGRP_SCAN] = { .name = "scan", },
        [NL80211_MCGRP_REGULATORY] = { .name = "regulatory", },
        [NL80211_MCGRP_MLME] = { .name = "mlme", },
+       [NL80211_MCGRP_VENDOR] = { .name = "vendor", },
 #ifdef CONFIG_NL80211_TESTMODE
        [NL80211_MCGRP_TESTMODE] = { .name = "testmode", }
 #endif
@@ -376,6 +378,12 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
        [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
        [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
+       [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
+       [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
+       [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
+       [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
+       [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
+                                  .len = IEEE80211_QOS_MAP_LEN_MAX },
 };
 
 /* policy for the key attributes */
@@ -1450,6 +1458,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
                        if (dev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
                                CMD(channel_switch, CHANNEL_SWITCH);
                }
+               CMD(set_qos_map, SET_QOS_MAP);
 
 #ifdef CONFIG_NL80211_TESTMODE
                CMD(testmode_cmd, TESTMODE);
@@ -1579,6 +1588,41 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
                    (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
                     nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
                        goto nla_put_failure;
+               state->split_start++;
+               break;
+       case 11:
+               if (dev->wiphy.n_vendor_commands) {
+                       const struct nl80211_vendor_cmd_info *info;
+                       struct nlattr *nested;
+
+                       nested = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+                       if (!nested)
+                               goto nla_put_failure;
+
+                       for (i = 0; i < dev->wiphy.n_vendor_commands; i++) {
+                               info = &dev->wiphy.vendor_commands[i].info;
+                               if (nla_put(msg, i + 1, sizeof(*info), info))
+                                       goto nla_put_failure;
+                       }
+                       nla_nest_end(msg, nested);
+               }
+
+               if (dev->wiphy.n_vendor_events) {
+                       const struct nl80211_vendor_cmd_info *info;
+                       struct nlattr *nested;
+
+                       nested = nla_nest_start(msg,
+                                               NL80211_ATTR_VENDOR_EVENTS);
+                       if (!nested)
+                               goto nla_put_failure;
+
+                       for (i = 0; i < dev->wiphy.n_vendor_events; i++) {
+                               info = &dev->wiphy.vendor_events[i];
+                               if (nla_put(msg, i + 1, sizeof(*info), info))
+                                       goto nla_put_failure;
+                       }
+                       nla_nest_end(msg, nested);
+               }
 
                /* done */
                state->split_start = 0;
@@ -4151,6 +4195,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
                params.vht_capa =
                        nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
 
+       if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
+               params.opmode_notif_used = true;
+               params.opmode_notif =
+                       nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
+       }
+
        if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
                params.plink_action =
                        nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
@@ -5667,8 +5717,13 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
        struct net_device *dev = info->user_ptr[1];
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_chan_def chandef;
+       enum nl80211_dfs_regions dfs_region;
        int err;
 
+       dfs_region = reg_get_dfs_region(wdev->wiphy);
+       if (dfs_region == NL80211_DFS_UNSET)
+               return -EINVAL;
+
        err = nl80211_parse_chandef(rdev, info, &chandef);
        if (err)
                return err;
@@ -6693,6 +6748,52 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
        return err;
 }
 
+static struct sk_buff *
+__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
+                           int approxlen, u32 portid, u32 seq,
+                           enum nl80211_commands cmd,
+                           enum nl80211_attrs attr,
+                           const struct nl80211_vendor_cmd_info *info,
+                           gfp_t gfp)
+{
+       struct sk_buff *skb;
+       void *hdr;
+       struct nlattr *data;
+
+       skb = nlmsg_new(approxlen + 100, gfp);
+       if (!skb)
+               return NULL;
+
+       hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
+       if (!hdr) {
+               kfree_skb(skb);
+               return NULL;
+       }
+
+       if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
+               goto nla_put_failure;
+
+       if (info) {
+               if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
+                               info->vendor_id))
+                       goto nla_put_failure;
+               if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
+                               info->subcmd))
+                       goto nla_put_failure;
+       }
+
+       data = nla_nest_start(skb, attr);
+
+       ((void **)skb->cb)[0] = rdev;
+       ((void **)skb->cb)[1] = hdr;
+       ((void **)skb->cb)[2] = data;
+
+       return skb;
+
+ nla_put_failure:
+       kfree_skb(skb);
+       return NULL;
+}
 
 #ifdef CONFIG_NL80211_TESTMODE
 static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
@@ -6717,11 +6818,11 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
        if (!info->attrs[NL80211_ATTR_TESTDATA])
                return -EINVAL;
 
-       rdev->testmode_info = info;
+       rdev->cur_cmd_info = info;
        err = rdev_testmode_cmd(rdev, wdev,
                                nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
                                nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
-       rdev->testmode_info = NULL;
+       rdev->cur_cmd_info = NULL;
 
        return err;
 }
@@ -6821,92 +6922,54 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
        return err;
 }
 
-static struct sk_buff *
-__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
-                             int approxlen, u32 portid, u32 seq, gfp_t gfp)
-{
-       struct sk_buff *skb;
-       void *hdr;
-       struct nlattr *data;
-
-       skb = nlmsg_new(approxlen + 100, gfp);
-       if (!skb)
-               return NULL;
-
-       hdr = nl80211hdr_put(skb, portid, seq, 0, NL80211_CMD_TESTMODE);
-       if (!hdr) {
-               kfree_skb(skb);
-               return NULL;
-       }
-
-       if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
-               goto nla_put_failure;
-       data = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
-
-       ((void **)skb->cb)[0] = rdev;
-       ((void **)skb->cb)[1] = hdr;
-       ((void **)skb->cb)[2] = data;
-
-       return skb;
-
- nla_put_failure:
-       kfree_skb(skb);
-       return NULL;
-}
-
-struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
-                                                 int approxlen)
+struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
+                                          enum nl80211_commands cmd,
+                                          enum nl80211_attrs attr,
+                                          int vendor_event_idx,
+                                          int approxlen, gfp_t gfp)
 {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+       const struct nl80211_vendor_cmd_info *info;
 
-       if (WARN_ON(!rdev->testmode_info))
+       switch (cmd) {
+       case NL80211_CMD_TESTMODE:
+               if (WARN_ON(vendor_event_idx != -1))
+                       return NULL;
+               info = NULL;
+               break;
+       case NL80211_CMD_VENDOR:
+               if (WARN_ON(vendor_event_idx < 0 ||
+                           vendor_event_idx >= wiphy->n_vendor_events))
+                       return NULL;
+               info = &wiphy->vendor_events[vendor_event_idx];
+               break;
+       default:
+               WARN_ON(1);
                return NULL;
+       }
 
-       return __cfg80211_testmode_alloc_skb(rdev, approxlen,
-                               rdev->testmode_info->snd_portid,
-                               rdev->testmode_info->snd_seq,
-                               GFP_KERNEL);
+       return __cfg80211_alloc_vendor_skb(rdev, approxlen, 0, 0,
+                                          cmd, attr, info, gfp);
 }
-EXPORT_SYMBOL(cfg80211_testmode_alloc_reply_skb);
+EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
 
-int cfg80211_testmode_reply(struct sk_buff *skb)
+void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
 {
        struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
        void *hdr = ((void **)skb->cb)[1];
        struct nlattr *data = ((void **)skb->cb)[2];
-
-       if (WARN_ON(!rdev->testmode_info)) {
-               kfree_skb(skb);
-               return -EINVAL;
-       }
+       enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
 
        nla_nest_end(skb, data);
        genlmsg_end(skb, hdr);
-       return genlmsg_reply(skb, rdev->testmode_info);
-}
-EXPORT_SYMBOL(cfg80211_testmode_reply);
-
-struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
-                                                 int approxlen, gfp_t gfp)
-{
-       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-       return __cfg80211_testmode_alloc_skb(rdev, approxlen, 0, 0, gfp);
-}
-EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb);
 
-void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
-{
-       struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
-       void *hdr = ((void **)skb->cb)[1];
-       struct nlattr *data = ((void **)skb->cb)[2];
+       if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
+               mcgrp = NL80211_MCGRP_VENDOR;
 
-       nla_nest_end(skb, data);
-       genlmsg_end(skb, hdr);
        genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
-                               NL80211_MCGRP_TESTMODE, gfp);
+                               mcgrp, gfp);
 }
-EXPORT_SYMBOL(cfg80211_testmode_event);
+EXPORT_SYMBOL(__cfg80211_send_event_skb);
 #endif
 
 static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
@@ -7328,11 +7391,72 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
        return true;
 }
 
+static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
+{
+       u16 mcs_mask = 0;
+
+       switch (vht_mcs_map) {
+       case IEEE80211_VHT_MCS_NOT_SUPPORTED:
+               break;
+       case IEEE80211_VHT_MCS_SUPPORT_0_7:
+               mcs_mask = 0x00FF;
+               break;
+       case IEEE80211_VHT_MCS_SUPPORT_0_8:
+               mcs_mask = 0x01FF;
+               break;
+       case IEEE80211_VHT_MCS_SUPPORT_0_9:
+               mcs_mask = 0x03FF;
+               break;
+       default:
+               break;
+       }
+
+       return mcs_mask;
+}
+
+static void vht_build_mcs_mask(u16 vht_mcs_map,
+                              u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
+{
+       u8 nss;
+
+       for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
+               vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
+               vht_mcs_map >>= 2;
+       }
+}
+
+static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
+                            struct nl80211_txrate_vht *txrate,
+                            u16 mcs[NL80211_VHT_NSS_MAX])
+{
+       u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
+       u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
+       u8 i;
+
+       if (!sband->vht_cap.vht_supported)
+               return false;
+
+       memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
+
+       /* Build vht_mcs_mask from VHT capabilities */
+       vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
+
+       for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
+               if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
+                       mcs[i] = txrate->mcs[i];
+               else
+                       return false;
+       }
+
+       return true;
+}
+
 static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
        [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
                                    .len = NL80211_MAX_SUPP_RATES },
-       [NL80211_TXRATE_MCS] = { .type = NLA_BINARY,
-                                .len = NL80211_MAX_SUPP_HT_RATES },
+       [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
+                               .len = NL80211_MAX_SUPP_HT_RATES },
+       [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)},
 };
 
 static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
@@ -7345,9 +7469,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
        struct net_device *dev = info->user_ptr[1];
        struct nlattr *tx_rates;
        struct ieee80211_supported_band *sband;
-
-       if (info->attrs[NL80211_ATTR_TX_RATES] == NULL)
-               return -EINVAL;
+       u16 vht_tx_mcs_map;
 
        if (!rdev->ops->set_bitrate_mask)
                return -EOPNOTSUPP;
@@ -7356,17 +7478,26 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
        /* Default to all rates enabled */
        for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
                sband = rdev->wiphy.bands[i];
-               mask.control[i].legacy =
-                       sband ? (1 << sband->n_bitrates) - 1 : 0;
-               if (sband)
-                       memcpy(mask.control[i].mcs,
-                              sband->ht_cap.mcs.rx_mask,
-                              sizeof(mask.control[i].mcs));
-               else
-                       memset(mask.control[i].mcs, 0,
-                              sizeof(mask.control[i].mcs));
+
+               if (!sband)
+                       continue;
+
+               mask.control[i].legacy = (1 << sband->n_bitrates) - 1;
+               memcpy(mask.control[i].ht_mcs,
+                      sband->ht_cap.mcs.rx_mask,
+                      sizeof(mask.control[i].ht_mcs));
+
+               if (!sband->vht_cap.vht_supported)
+                       continue;
+
+               vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
+               vht_build_mcs_mask(vht_tx_mcs_map, mask.control[i].vht_mcs);
        }
 
+       /* if no rates are given set it back to the defaults */
+       if (!info->attrs[NL80211_ATTR_TX_RATES])
+               goto out;
+
        /*
         * The nested attribute uses enum nl80211_band as the index. This maps
         * directly to the enum ieee80211_band values used in cfg80211.
@@ -7391,31 +7522,44 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
                            nla_len(tb[NL80211_TXRATE_LEGACY]))
                                return -EINVAL;
                }
-               if (tb[NL80211_TXRATE_MCS]) {
+               if (tb[NL80211_TXRATE_HT]) {
                        if (!ht_rateset_to_mask(
                                        sband,
-                                       nla_data(tb[NL80211_TXRATE_MCS]),
-                                       nla_len(tb[NL80211_TXRATE_MCS]),
-                                       mask.control[band].mcs))
+                                       nla_data(tb[NL80211_TXRATE_HT]),
+                                       nla_len(tb[NL80211_TXRATE_HT]),
+                                       mask.control[band].ht_mcs))
+                               return -EINVAL;
+               }
+               if (tb[NL80211_TXRATE_VHT]) {
+                       if (!vht_set_mcs_mask(
+                                       sband,
+                                       nla_data(tb[NL80211_TXRATE_VHT]),
+                                       mask.control[band].vht_mcs))
                                return -EINVAL;
                }
 
                if (mask.control[band].legacy == 0) {
-                       /* don't allow empty legacy rates if HT
-                        * is not even supported. */
-                       if (!rdev->wiphy.bands[band]->ht_cap.ht_supported)
+                       /* don't allow empty legacy rates if HT or VHT
+                        * are not even supported.
+                        */
+                       if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
+                             rdev->wiphy.bands[band]->vht_cap.vht_supported))
                                return -EINVAL;
 
                        for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
-                               if (mask.control[band].mcs[i])
-                                       break;
+                               if (mask.control[band].ht_mcs[i])
+                                       goto out;
+
+                       for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
+                               if (mask.control[band].vht_mcs[i])
+                                       goto out;
 
                        /* legacy and mcs rates may not be both empty */
-                       if (i == IEEE80211_HT_MCS_MASK_LEN)
-                               return -EINVAL;
+                       return -EINVAL;
                }
        }
 
+out:
        return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
 }
 
@@ -8875,6 +9019,162 @@ static int nl80211_crit_protocol_stop(struct sk_buff *skb,
        return 0;
 }
 
+static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+       struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct wireless_dev *wdev =
+               __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
+       int i, err;
+       u32 vid, subcmd;
+
+       if (!rdev->wiphy.vendor_commands)
+               return -EOPNOTSUPP;
+
+       if (IS_ERR(wdev)) {
+               err = PTR_ERR(wdev);
+               if (err != -EINVAL)
+                       return err;
+               wdev = NULL;
+       } else if (wdev->wiphy != &rdev->wiphy) {
+               return -EINVAL;
+       }
+
+       if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
+           !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
+               return -EINVAL;
+
+       vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
+       subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
+       for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
+               const struct wiphy_vendor_command *vcmd;
+               void *data = NULL;
+               int len = 0;
+
+               vcmd = &rdev->wiphy.vendor_commands[i];
+
+               if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
+                       continue;
+
+               if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
+                                  WIPHY_VENDOR_CMD_NEED_NETDEV)) {
+                       if (!wdev)
+                               return -EINVAL;
+                       if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
+                           !wdev->netdev)
+                               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)
+                                       return -ENETDOWN;
+                       }
+               } else {
+                       wdev = NULL;
+               }
+
+               if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
+                       data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
+                       len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
+               }
+
+               rdev->cur_cmd_info = info;
+               err = rdev->wiphy.vendor_commands[i].doit(&rdev->wiphy, wdev,
+                                                         data, len);
+               rdev->cur_cmd_info = NULL;
+               return err;
+       }
+
+       return -EOPNOTSUPP;
+}
+
+struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
+                                          enum nl80211_commands cmd,
+                                          enum nl80211_attrs attr,
+                                          int approxlen)
+{
+       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+       if (WARN_ON(!rdev->cur_cmd_info))
+               return NULL;
+
+       return __cfg80211_alloc_vendor_skb(rdev, approxlen,
+                                          rdev->cur_cmd_info->snd_portid,
+                                          rdev->cur_cmd_info->snd_seq,
+                                          cmd, attr, NULL, GFP_KERNEL);
+}
+EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
+
+int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
+{
+       struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
+       void *hdr = ((void **)skb->cb)[1];
+       struct nlattr *data = ((void **)skb->cb)[2];
+
+       if (WARN_ON(!rdev->cur_cmd_info)) {
+               kfree_skb(skb);
+               return -EINVAL;
+       }
+
+       nla_nest_end(skb, data);
+       genlmsg_end(skb, hdr);
+       return genlmsg_reply(skb, rdev->cur_cmd_info);
+}
+EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
+
+
+static int nl80211_set_qos_map(struct sk_buff *skb,
+                              struct genl_info *info)
+{
+       struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct cfg80211_qos_map *qos_map = NULL;
+       struct net_device *dev = info->user_ptr[1];
+       u8 *pos, len, num_des, des_len, des;
+       int ret;
+
+       if (!rdev->ops->set_qos_map)
+               return -EOPNOTSUPP;
+
+       if (info->attrs[NL80211_ATTR_QOS_MAP]) {
+               pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
+               len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
+
+               if (len % 2 || len < IEEE80211_QOS_MAP_LEN_MIN ||
+                   len > IEEE80211_QOS_MAP_LEN_MAX)
+                       return -EINVAL;
+
+               qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
+               if (!qos_map)
+                       return -ENOMEM;
+
+               num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
+               if (num_des) {
+                       des_len = num_des *
+                               sizeof(struct cfg80211_dscp_exception);
+                       memcpy(qos_map->dscp_exception, pos, des_len);
+                       qos_map->num_des = num_des;
+                       for (des = 0; des < num_des; des++) {
+                               if (qos_map->dscp_exception[des].up > 7) {
+                                       kfree(qos_map);
+                                       return -EINVAL;
+                               }
+                       }
+                       pos += des_len;
+               }
+               memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
+       }
+
+       wdev_lock(dev->ieee80211_ptr);
+       ret = nl80211_key_allowed(dev->ieee80211_ptr);
+       if (!ret)
+               ret = rdev_set_qos_map(rdev, dev, qos_map);
+       wdev_unlock(dev->ieee80211_ptr);
+
+       kfree(qos_map);
+       return ret;
+}
+
 #define NL80211_FLAG_NEED_WIPHY                0x01
 #define NL80211_FLAG_NEED_NETDEV       0x02
 #define NL80211_FLAG_NEED_RTNL         0x04
@@ -9599,6 +9899,22 @@ static const struct genl_ops nl80211_ops[] = {
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
+       {
+               .cmd = NL80211_CMD_VENDOR,
+               .doit = nl80211_vendor_cmd,
+               .policy = nl80211_policy,
+               .flags = GENL_ADMIN_PERM,
+               .internal_flags = NL80211_FLAG_NEED_WIPHY |
+                                 NL80211_FLAG_NEED_RTNL,
+       },
+       {
+               .cmd = NL80211_CMD_SET_QOS_MAP,
+               .doit = nl80211_set_qos_map,
+               .policy = nl80211_policy,
+               .flags = GENL_ADMIN_PERM,
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+                                 NL80211_FLAG_NEED_RTNL,
+       },
 };
 
 /* notification functions */
index a271c27fac774ce987c0db6f1330ffbfca6dc7f7..722da616438cd1e933fb4d5e60a2c4846f44d186 100644 (file)
@@ -124,6 +124,10 @@ int ieee80211_radiotap_iterator_init(
        /* find payload start allowing for extended bitmap(s) */
 
        if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
+               if ((unsigned long)iterator->_arg -
+                   (unsigned long)iterator->_rtheader + sizeof(uint32_t) >
+                   (unsigned long)iterator->_max_length)
+                       return -EINVAL;
                while (get_unaligned_le32(iterator->_arg) &
                                        (1 << IEEE80211_RADIOTAP_EXT)) {
                        iterator->_arg += sizeof(uint32_t);
index a6c03ab14a0d47ea9a7f676dec76301804ab809b..c8e225947adb2601d31dbb0f4a1aa5a4392d8bc5 100644 (file)
@@ -932,4 +932,19 @@ static inline int rdev_channel_switch(struct cfg80211_registered_device *rdev,
        return ret;
 }
 
+static inline int rdev_set_qos_map(struct cfg80211_registered_device *rdev,
+                                  struct net_device *dev,
+                                  struct cfg80211_qos_map *qos_map)
+{
+       int ret = -EOPNOTSUPP;
+
+       if (rdev->ops->set_qos_map) {
+               trace_rdev_set_qos_map(&rdev->wiphy, dev, qos_map);
+               ret = rdev->ops->set_qos_map(&rdev->wiphy, dev, qos_map);
+               trace_rdev_return_int(&rdev->wiphy, ret);
+       }
+
+       return ret;
+}
+
 #endif /* __CFG80211_RDEV_OPS */
index ec54e1aac8e29c01e89ab4d0c6e9078bf112b5f9..7d20d844ca60e47e09bfea602a6bdca659d01ce6 100644 (file)
@@ -135,6 +135,33 @@ static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)
        return "Unknown";
 }
 
+enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy)
+{
+       const struct ieee80211_regdomain *regd = NULL;
+       const struct ieee80211_regdomain *wiphy_regd = NULL;
+
+       regd = get_cfg80211_regdom();
+       if (!wiphy)
+               goto out;
+
+       wiphy_regd = get_wiphy_regdom(wiphy);
+       if (!wiphy_regd)
+               goto out;
+
+       if (wiphy_regd->dfs_region == regd->dfs_region)
+               goto out;
+
+       REG_DBG_PRINT("%s: device specific dfs_region "
+                     "(%s) disagrees with cfg80211's "
+                     "central dfs_region (%s)\n",
+                     dev_name(&wiphy->dev),
+                     reg_dfs_region_str(wiphy_regd->dfs_region),
+                     reg_dfs_region_str(regd->dfs_region));
+
+out:
+       return regd->dfs_region;
+}
+
 static void rcu_free_regdom(const struct ieee80211_regdomain *r)
 {
        if (!r)
index cc4c2c0a67236cd2801f954e0a8e15dc4b5adea5..02bd8f4b0921dafca98c4e1bc23b729045b036db 100644 (file)
@@ -21,6 +21,7 @@ extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
 bool reg_is_valid_request(const char *alpha2);
 bool is_world_regdom(const char *alpha2);
 bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region);
+enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
 
 int regulatory_hint_user(const char *alpha2,
                         enum nl80211_user_reg_hint_type user_reg_hint_type);
index d4397eba5408ea4325ac3404a251b8617d878309..a32d52a04c275c6c148e71ab0a31edd9aae3020d 100644 (file)
@@ -161,7 +161,7 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
                dev->bss_generation++;
 }
 
-void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
 {
        struct cfg80211_scan_request *request;
        struct wireless_dev *wdev;
@@ -210,17 +210,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
                dev_put(wdev->netdev);
 
        rdev->scan_req = NULL;
-
-       /*
-        * OK. If this is invoked with "leak" then we can't
-        * free this ... but we've cleaned it up anyway. The
-        * driver failed to call the scan_done callback, so
-        * all bets are off, it might still be trying to use
-        * the scan request or not ... if it accesses the dev
-        * in there (it shouldn't anyway) then it may crash.
-        */
-       if (!leak)
-               kfree(request);
+       kfree(request);
 }
 
 void __cfg80211_scan_done(struct work_struct *wk)
@@ -231,7 +221,7 @@ void __cfg80211_scan_done(struct work_struct *wk)
                            scan_done_wk);
 
        rtnl_lock();
-       ___cfg80211_scan_done(rdev, false);
+       ___cfg80211_scan_done(rdev);
        rtnl_unlock();
 }
 
index 65f800890d70d857c9b42d379caad887f5a98c74..5d6e7bb2fc89a2fc1e4a1034f44beadb76b53e5a 100644 (file)
@@ -632,6 +632,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
        }
 #endif
 
+       if (!bss && (status == WLAN_STATUS_SUCCESS)) {
+               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
+               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+                                      wdev->ssid, wdev->ssid_len,
+                                      WLAN_CAPABILITY_ESS,
+                                      WLAN_CAPABILITY_ESS);
+               if (bss)
+                       cfg80211_hold_bss(bss_from_pub(bss));
+       }
+
        if (wdev->current_bss) {
                cfg80211_unhold_bss(wdev->current_bss);
                cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
@@ -649,16 +659,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                return;
        }
 
-       if (!bss) {
-               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
-               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
-                                      wdev->ssid, wdev->ssid_len,
-                                      WLAN_CAPABILITY_ESS,
-                                      WLAN_CAPABILITY_ESS);
-               if (WARN_ON(!bss))
-                       return;
-               cfg80211_hold_bss(bss_from_pub(bss));
-       }
+       if (WARN_ON(!bss))
+               return;
 
        wdev->current_bss = bss_from_pub(bss);
 
@@ -870,6 +872,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
                for (i = 0; i < 6; i++)
                        rdev_del_key(rdev, dev, i, false, NULL);
 
+       rdev_set_qos_map(rdev, dev, NULL);
+
 #ifdef CONFIG_CFG80211_WEXT
        memset(&wrqu, 0, sizeof(wrqu));
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
index f7aa7a72d9bc928aa7d24153d709e13634773b06..fbcc23edee5474459950b8566ecffd541ad4ed7d 100644 (file)
 
 #define BOOL_TO_STR(bo) (bo) ? "true" : "false"
 
+#define QOS_MAP_ENTRY __field(u8, num_des)                     \
+                     __array(u8, dscp_exception,               \
+                             2 * IEEE80211_QOS_MAP_MAX_EX)     \
+                     __array(u8, up, IEEE80211_QOS_MAP_LEN_MIN)
+#define QOS_MAP_ASSIGN(qos_map)                                        \
+       do {                                                    \
+               if ((qos_map)) {                                \
+                       __entry->num_des = (qos_map)->num_des;  \
+                       memcpy(__entry->dscp_exception,         \
+                              &(qos_map)->dscp_exception,      \
+                              2 * IEEE80211_QOS_MAP_MAX_EX);   \
+                       memcpy(__entry->up, &(qos_map)->up,     \
+                              IEEE80211_QOS_MAP_LEN_MIN);      \
+               } else {                                        \
+                       __entry->num_des = 0;                   \
+                       memset(__entry->dscp_exception, 0,      \
+                              2 * IEEE80211_QOS_MAP_MAX_EX);   \
+                       memset(__entry->up, 0,                  \
+                              IEEE80211_QOS_MAP_LEN_MIN);      \
+               }                                               \
+       } while (0)
+
 /*************************************************************
  *                     rdev->ops traces                     *
  *************************************************************/
@@ -1875,6 +1897,24 @@ TRACE_EVENT(rdev_channel_switch,
                  __entry->counter_offset_presp)
 );
 
+TRACE_EVENT(rdev_set_qos_map,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_qos_map *qos_map),
+       TP_ARGS(wiphy, netdev, qos_map),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               QOS_MAP_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               QOS_MAP_ASSIGN(qos_map);
+       ),
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", num_des: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->num_des)
+);
+
 /*************************************************************
  *          cfg80211 exported functions traces              *
  *************************************************************/
index 935dea9485da01f7a0fb82cacc6e187058ff1ce0..5618888853b24ffdac2853509a1528f70ac1661b 100644 (file)
@@ -689,7 +689,8 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
 
 /* Given a data frame determine the 802.1p/1d tag to use. */
-unsigned int cfg80211_classify8021d(struct sk_buff *skb)
+unsigned int cfg80211_classify8021d(struct sk_buff *skb,
+                                   struct cfg80211_qos_map *qos_map)
 {
        unsigned int dscp;
        unsigned char vlan_priority;
@@ -720,6 +721,21 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb)
                return 0;
        }
 
+       if (qos_map) {
+               unsigned int i, tmp_dscp = dscp >> 2;
+
+               for (i = 0; i < qos_map->num_des; i++) {
+                       if (tmp_dscp == qos_map->dscp_exception[i].dscp)
+                               return qos_map->dscp_exception[i].up;
+               }
+
+               for (i = 0; i < 8; i++) {
+                       if (tmp_dscp >= qos_map->up[i].low &&
+                           tmp_dscp <= qos_map->up[i].high)
+                               return i;
+               }
+       }
+
        return dscp >> 5;
 }
 EXPORT_SYMBOL(cfg80211_classify8021d);
@@ -863,6 +879,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
 
                dev->ieee80211_ptr->use_4addr = false;
                dev->ieee80211_ptr->mesh_id_up_len = 0;
+               rdev_set_qos_map(rdev, dev, NULL);
 
                switch (otype) {
                case NL80211_IFTYPE_AP:
index fe8942bb8bbc0f4c45da15601a14568dd1606fb6..01770826a15ad37b03a49e74e4118af5ed8c2f44 100644 (file)
@@ -1641,20 +1641,22 @@ free_dst:
        goto out;
 }
 
-static inline int
-xfrm_dst_alloc_copy(void **target, const void *src, int size)
+#ifdef CONFIG_XFRM_SUB_POLICY
+static int xfrm_dst_alloc_copy(void **target, const void *src, int size)
 {
        if (!*target) {
                *target = kmalloc(size, GFP_ATOMIC);
                if (!*target)
                        return -ENOMEM;
        }
+
        memcpy(*target, src, size);
        return 0;
 }
+#endif
 
-static inline int
-xfrm_dst_update_parent(struct dst_entry *dst, const struct xfrm_selector *sel)
+static int xfrm_dst_update_parent(struct dst_entry *dst,
+                                 const struct xfrm_selector *sel)
 {
 #ifdef CONFIG_XFRM_SUB_POLICY
        struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
@@ -1665,8 +1667,8 @@ xfrm_dst_update_parent(struct dst_entry *dst, const struct xfrm_selector *sel)
 #endif
 }
 
-static inline int
-xfrm_dst_update_origin(struct dst_entry *dst, const struct flowi *fl)
+static int xfrm_dst_update_origin(struct dst_entry *dst,
+                                 const struct flowi *fl)
 {
 #ifdef CONFIG_XFRM_SUB_POLICY
        struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
index 32b10f53d0b4cbad76b13ef86d547ad864ae19c2..2dcb37736d8469a0e18e4c1ba262281e3fd8cf37 100644 (file)
@@ -82,7 +82,9 @@ kallsyms()
                kallsymopt="${kallsymopt} --all-symbols"
        fi
 
-       kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
+       if [ -n "${CONFIG_ARM}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then
+               kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
+       fi
 
        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
index 419491d8e7d20737cc2e2098882994a1fc37ca98..6625699f497c7f3889f7b82b325a315c9e51774a 100644 (file)
@@ -4334,8 +4334,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
                err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
                                   PEER__RECV, &ad);
-               if (err)
+               if (err) {
                        selinux_netlbl_err(skb, err, 0);
+                       return err;
+               }
        }
 
        if (secmark_active) {
@@ -5586,11 +5588,11 @@ static int selinux_setprocattr(struct task_struct *p,
                /* Check for ptracing, and update the task SID if ok.
                   Otherwise, leave SID unchanged and fail. */
                ptsid = 0;
-               task_lock(p);
+               rcu_read_lock();
                tracer = ptrace_parent(p);
                if (tracer)
                        ptsid = task_sid(tracer);
-               task_unlock(p);
+               rcu_read_unlock();
 
                if (tracer) {
                        error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
index 6e03b465e44e3a05f82e93a2d25a61f030cc3cf6..a2104671f51d38df6eec99b3e0aa8ac570ea8988 100644 (file)
@@ -1937,6 +1937,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
                case SNDRV_PCM_STATE_DISCONNECTED:
                        err = -EBADFD;
                        goto _endloop;
+               case SNDRV_PCM_STATE_PAUSED:
+                       continue;
                }
                if (!tout) {
                        snd_printd("%s write error (DMA or IRQ trouble?)\n",
index 27aa14007cbd400ebcb1f21e5e4036d58e778430..956871d8b3d26a9255723eb4bdfdf963c50f031b 100644 (file)
@@ -3433,6 +3433,10 @@ static void check_probe_mask(struct azx *chip, int dev)
  * white/black-list for enable_msi
  */
 static struct snd_pci_quirk msi_black_list[] = {
+       SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x21fa, "HP", 0), /* AMD Hudson */
        SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
        SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
        SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
index 34de5dc2fe9b302e115f03961ef13c6d6b070cc2..c5646941539a87df9505eece6241dd5e9230c4ff 100644 (file)
@@ -4247,12 +4247,16 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
        SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS),
+       SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0640, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
index 8697cedccd21240f76b4b5076ba6d0968a394d75..1ead3c977a51743619b0bb2084ec174b7cf867a8 100644 (file)
@@ -648,7 +648,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
 
        dma_params = ssc_p->dma_params[dir];
 
-       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
        ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
 
        pr_debug("%s enabled SSC_SR=0x%08x\n",
@@ -657,6 +657,33 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int atmel_ssc_trigger(struct snd_pcm_substream *substream,
+                            int cmd, struct snd_soc_dai *dai)
+{
+       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+       struct atmel_pcm_dma_params *dma_params;
+       int dir;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dir = 0;
+       else
+               dir = 1;
+
+       dma_params = ssc_p->dma_params[dir];
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+               break;
+       default:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
+               break;
+       }
+
+       return 0;
+}
 
 #ifdef CONFIG_PM
 static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
@@ -731,6 +758,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
        .startup        = atmel_ssc_startup,
        .shutdown       = atmel_ssc_shutdown,
        .prepare        = atmel_ssc_prepare,
+       .trigger        = atmel_ssc_trigger,
        .hw_params      = atmel_ssc_hw_params,
        .set_fmt        = atmel_ssc_set_dai_fmt,
        .set_clkdiv     = atmel_ssc_set_dai_clkdiv,
index 1b372283bd01a947c26dc4da302f9b077adfe74a..7d6a9055874b822bb440eab72a66dc5c034127ed 100644 (file)
@@ -109,7 +109,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
        dai->stream_name = "WM8731 PCM";
        dai->codec_dai_name = "wm8731-hifi";
        dai->init = sam9x5_wm8731_init;
-       dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+       dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF
                | SND_SOC_DAIFMT_CBM_CFM;
 
        ret = snd_soc_of_parse_card_name(card, "atmel,model");
index 99b359e19d35f46a3c95946d976b294300c6ea70..0ab2dc296474373e1e407abf0762afeeffead4c6 100644 (file)
@@ -1012,7 +1012,7 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        { "AEC Loopback", "HPOUT3L", "OUT3L" },
        { "AEC Loopback", "HPOUT3R", "OUT3R" },
        { "HPOUT3L", NULL, "OUT3L" },
-       { "HPOUT3R", NULL, "OUT3L" },
+       { "HPOUT3R", NULL, "OUT3R" },
 
        { "AEC Loopback", "SPKOUTL", "OUT4L" },
        { "SPKOUTLN", NULL, "OUT4L" },
index 3938fb1c203ed86b5452ff130071d349a6821a87..53bbfac6a83ad14ed43d2aafca2514ea3a319468 100644 (file)
@@ -1444,7 +1444,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_DSP_B:
-               aif1 |= WM8904_AIF_LRCLK_INV;
+               aif1 |= 0x3 | WM8904_AIF_LRCLK_INV;
        case SND_SOC_DAIFMT_DSP_A:
                aif1 |= 0x3;
                break;
index 543c5c2631b61827bcebca8af1926ea02b5655e9..0f17ed3e29f41dc9d7ddebb505b7fad8fc545b02 100644 (file)
@@ -2439,7 +2439,20 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8962_CLOCKING_4,
                            WM8962_SYSCLK_RATE_MASK, clocking4);
 
+       /* DSPCLK_DIV can be only generated correctly after enabling SYSCLK.
+        * So we here provisionally enable it and then disable it afterward
+        * if current bias_level hasn't reached SND_SOC_BIAS_ON.
+        */
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA);
+
        dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
+
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, 0);
+
        if (dspclk < 0) {
                dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
                return;
index 46ec0e9744d4b88b50cc922cfdc65a0b4247e567..4fbcab63e61f1c5d8b4843fdec5c6d3dbfa498ed 100644 (file)
@@ -1474,13 +1474,17 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
                return ret;
 
        /* Wait for the RAM to start, should be near instantaneous */
-       count = 0;
-       do {
+       for (count = 0; count < 10; ++count) {
                ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
                                  &val);
                if (ret != 0)
                        return ret;
-       } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
+
+               if (val & ADSP2_RAM_RDY)
+                       break;
+
+               msleep(1);
+       }
 
        if (!(val & ADSP2_RAM_RDY)) {
                adsp_err(dsp, "Failed to start DSP RAM\n");
index 61e48852b9e8bd21b26eec98cca4fc9ba0eea145..3fd76bc391de19a2431dd320d0abfbdcd9616cf5 100644 (file)
@@ -130,8 +130,6 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
                break;
        }
 
-       dapm->bias_level = level;
-
        return 0;
 }
 
index 0b18f654b41340908d022003485d8a88c5e0c94e..3920a5e8125f886e15caa6607fed9e84a32950cd 100644 (file)
@@ -473,17 +473,17 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_I2S_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_I2S_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
@@ -494,17 +494,17 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
index cbc9c96ce1f412123a1704b171220a2990ad503d..41949af3baaed2580dae2df585222339ade75208 100644 (file)
@@ -305,6 +305,20 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
        }
 }
 
+static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm)
+{
+       unsigned int i;
+
+       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
+            i++) {
+               if (!pcm->chan[i])
+                       continue;
+               dma_release_channel(pcm->chan[i]);
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       break;
+       }
+}
+
 /**
  * snd_dmaengine_pcm_register - Register a dmaengine based PCM device
  * @dev: The parent device for the PCM device
@@ -315,6 +329,7 @@ int snd_dmaengine_pcm_register(struct device *dev,
        const struct snd_dmaengine_pcm_config *config, unsigned int flags)
 {
        struct dmaengine_pcm *pcm;
+       int ret;
 
        pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
        if (!pcm)
@@ -326,11 +341,20 @@ int snd_dmaengine_pcm_register(struct device *dev,
        dmaengine_pcm_request_chan_of(pcm, dev);
 
        if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
-               return snd_soc_add_platform(dev, &pcm->platform,
+               ret = snd_soc_add_platform(dev, &pcm->platform,
                                &dmaengine_no_residue_pcm_platform);
        else
-               return snd_soc_add_platform(dev, &pcm->platform,
+               ret = snd_soc_add_platform(dev, &pcm->platform,
                                &dmaengine_pcm_platform);
+       if (ret)
+               goto err_free_dma;
+
+       return 0;
+
+err_free_dma:
+       dmaengine_pcm_release_chan(pcm);
+       kfree(pcm);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register);
 
@@ -345,7 +369,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
 {
        struct snd_soc_platform *platform;
        struct dmaengine_pcm *pcm;
-       unsigned int i;
 
        platform = snd_soc_lookup_platform(dev);
        if (!platform)
@@ -353,15 +376,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
 
        pcm = soc_platform_to_pcm(platform);
 
-       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
-               if (pcm->chan[i]) {
-                       dma_release_channel(pcm->chan[i]);
-                       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
-                               break;
-               }
-       }
-
        snd_soc_remove_platform(platform);
+       dmaengine_pcm_release_chan(pcm);
        kfree(pcm);
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister);
index 11a90cd027faca2956172f3dfa92f6d2ee46a8fe..891b9a9bcbf885df92bad9007b3f23054ce68c18 100644 (file)
@@ -600,12 +600,13 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
        struct snd_soc_platform *platform = rtd->platform;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_codec *codec = rtd->codec;
+       bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
        /* apply codec digital mute */
-       if (!codec->active)
+       if ((playback && codec_dai->playback_active == 1) ||
+           (!playback && codec_dai->capture_active == 1))
                snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
 
        /* free any machine hw params */
index 364bf6a907e1c39a36df89ded1d6b2681172940f..8c819f8114708f7a94e33929a04ebecbdf3e2ffc 100644 (file)
@@ -74,7 +74,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -83,10 +83,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;
index 08bc6931c7c7fc0477703037098a8e7185d7c69d..8c7c1028e5797dbc9b23ec88b58a4cd840db1c5c 100644 (file)
@@ -67,15 +67,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
 {
        struct device *dev = dai->dev;
        struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
        int ret, spdifclock;
 
-       mask = TEGRA20_SPDIF_CTRL_PACK |
-              TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
+       mask |= TEGRA20_SPDIF_CTRL_PACK |
+               TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
-               val = TEGRA20_SPDIF_CTRL_PACK |
-                     TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
+               val |= TEGRA20_SPDIF_CTRL_PACK |
+                      TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
                break;
        default:
                return -EINVAL;
index 231a785b3921a5bd95d87914a92e7f5f2d266a63..02247fee1cf7e1450fb4bbcdf2e58cf5ee76c7e8 100644 (file)
@@ -118,7 +118,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -127,10 +127,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;