]> Pileus Git - ~andy/linux/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorDavid S. Miller <davem@davemloft.net>
Wed, 5 Jun 2013 22:56:43 +0000 (15:56 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 5 Jun 2013 23:37:30 +0000 (16:37 -0700)
Merge 'net' bug fixes into 'net-next' as we have patches
that will build on top of them.

This merge commit includes a change from Emil Goode
(emilgoode@gmail.com) that fixes a warning that would
have been introduced by this merge.  Specifically it
fixes the pingv6_ops method ipv6_chk_addr() to add a
"const" to the "struct net_device *dev" argument and
likewise update the dummy_ipv6_chk_addr() declaration.

Signed-off-by: David S. Miller <davem@davemloft.net>
436 files changed:
Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/cpsw.txt
Documentation/devicetree/bindings/net/davicom-dm9000.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/marvell-orion-net.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/micrel-ks8851.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/via-velocity.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/networking/.gitignore
Documentation/networking/00-INDEX
Documentation/networking/Makefile
Documentation/networking/bonding.txt
Documentation/networking/ifenslave.c [deleted file]
Documentation/networking/ip-sysctl.txt
Documentation/networking/netlink_mmap.txt
Documentation/networking/scaling.txt
Documentation/sysctl/net.txt
arch/arm/boot/dts/am335x-bone.dts
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am335x-evmsk.dts
arch/arm/boot/dts/sun4i-a10-cubieboard.dts
arch/arm/boot/dts/sun4i-a10-hackberry.dts
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/configs/omap2plus_defconfig
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/devices/Kconfig
arch/arm/mach-mxs/Kconfig
arch/arm/net/bpf_jit_32.c
arch/ia64/hp/sim/simeth.c
arch/mips/txx9/generic/setup_tx4939.c
arch/powerpc/Kconfig
arch/powerpc/net/bpf_jit_comp.c
arch/sparc/net/bpf_jit_comp.c
arch/x86/net/bpf_jit_comp.c
drivers/infiniband/core/cma.c
drivers/infiniband/hw/mlx4/main.c
drivers/isdn/i4l/isdn_net.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/Kconfig
drivers/net/can/at91_can.c
drivers/net/can/bfin_can.c
drivers/net/can/c_can/c_can_platform.c
drivers/net/can/cc770/cc770_isa.c
drivers/net/can/cc770/cc770_platform.c
drivers/net/can/flexcan.c
drivers/net/can/grcan.c
drivers/net/can/janz-ican3.c
drivers/net/can/led.c
drivers/net/can/mscan/mpc5xxx_can.c
drivers/net/can/sja1000/sja1000_isa.c
drivers/net/can/sja1000/sja1000_of_platform.c
drivers/net/can/sja1000/sja1000_platform.c
drivers/net/can/slcan.c
drivers/net/can/softing/softing_main.c
drivers/net/can/ti_hecc.c
drivers/net/ethernet/3com/3c509.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/Kconfig
drivers/net/ethernet/Makefile
drivers/net/ethernet/adi/bfin_mac.c
drivers/net/ethernet/aeroflex/greth.c
drivers/net/ethernet/allwinner/Kconfig [new file with mode: 0644]
drivers/net/ethernet/allwinner/Makefile [new file with mode: 0644]
drivers/net/ethernet/allwinner/sun4i-emac.c [new file with mode: 0644]
drivers/net/ethernet/allwinner/sun4i-emac.h [new file with mode: 0644]
drivers/net/ethernet/alteon/acenic.c
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/au1000_eth.c
drivers/net/ethernet/amd/sunlance.c
drivers/net/ethernet/apple/bmac.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/atheros/atlx/atl1.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bnx2.c
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_dcb.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.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_stats.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/broadcom/sb1250-mac.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/brocade/bna/bfa_defs.h
drivers/net/ethernet/brocade/bna/bfa_ioc.c
drivers/net/ethernet/brocade/bna/bfa_ioc.h
drivers/net/ethernet/brocade/bna/bna.h
drivers/net/ethernet/brocade/bna/bna_enet.c
drivers/net/ethernet/brocade/bna/bna_tx_rx.c
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/brocade/bna/bnad.h
drivers/net/ethernet/brocade/bna/cna.h
drivers/net/ethernet/cadence/at91_ether.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/calxeda/xgmac.c
drivers/net/ethernet/chelsio/cxgb/cxgb2.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
drivers/net/ethernet/chelsio/cxgb3/sge.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/cirrus/ep93xx_eth.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/dec/tulip/xircom_cb.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/ethoc.c
drivers/net/ethernet/faraday/ftgmac100.c
drivers/net/ethernet/faraday/ftmac100.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_mpc52xx.c
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
drivers/net/ethernet/freescale/fs_enet/mii-fec.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/freescale/xgmac_mdio.c
drivers/net/ethernet/ibm/Kconfig
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/emac/mal.c
drivers/net/ethernet/ibm/emac/rgmii.c
drivers/net/ethernet/ibm/emac/tah.c
drivers/net/ethernet/ibm/emac/zmii.c
drivers/net/ethernet/icplus/ipg.c
drivers/net/ethernet/intel/e1000e/80003es2lan.c
drivers/net/ethernet/intel/e1000e/82571.c
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/hw.h
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/nvm.c
drivers/net/ethernet/intel/e1000e/phy.c
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/e1000_defines.h
drivers/net/ethernet/intel/igb/e1000_hw.h
drivers/net/ethernet/intel/igb/e1000_i210.h
drivers/net/ethernet/intel/igb/e1000_mac.c
drivers/net/ethernet/intel/igb/e1000_phy.c
drivers/net/ethernet/intel/igb/e1000_phy.h
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/korina.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/micrel/ks8695net.c
drivers/net/ethernet/micrel/ks8842.c
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/netx-eth.c
drivers/net/ethernet/nuvoton/w90p910_ether.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/octeon/octeon_mgmt.c
drivers/net/ethernet/qlogic/netxen/netxen_nic.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.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_ctx.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
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_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/s6gmac.c
drivers/net/ethernet/seeq/sgiseeq.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sgi/ioc3-eth.c
drivers/net/ethernet/sgi/meth.c
drivers/net/ethernet/silan/sc92031.c
drivers/net/ethernet/sis/sis190.c
drivers/net/ethernet/smsc/Kconfig
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/sun/sunbmac.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/sun/sunqe.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_cpdma.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/ti/tlan.c
drivers/net/ethernet/ti/tlan.h
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/tundra/tsi108_eth.c
drivers/net/ethernet/via/Kconfig
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/via/via-velocity.h
drivers/net/ethernet/wiznet/w5100.c
drivers/net/ethernet/wiznet/w5300.c
drivers/net/ethernet/xilinx/Kconfig
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/fddi/skfp/skfddi.c
drivers/net/hamradio/bpqether.c
drivers/net/hippi/rrunner.c
drivers/net/irda/bfin_sir.c
drivers/net/irda/sh_irda.c
drivers/net/irda/sh_sir.c
drivers/net/macvlan.c
drivers/net/macvtap.c
drivers/net/netconsole.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/at803x.c
drivers/net/phy/bcm63xx.c
drivers/net/phy/marvell.c
drivers/net/phy/mdio-sun4i.c [new file with mode: 0644]
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/spi_ks8995.c
drivers/net/phy/vitesse.c
drivers/net/ppp/pppoe.c
drivers/net/team/team.c
drivers/net/usb/kalmia.c
drivers/net/usb/r8152.c
drivers/net/vxlan.c
drivers/net/wan/dlci.c
drivers/net/wan/hdlc.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wan/lapbether.c
drivers/net/wireless/ath/ath5k/ahb.c
drivers/net/wireless/ath/ath9k/ahb.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/dfs_debug.c
drivers/net/wireless/ath/ath9k/htc_drv_debug.c
drivers/net/wireless/iwlegacy/3945-mac.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/libertas/mesh.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netback/xenbus.c
drivers/net/xen-netfront.c
drivers/of/of_net.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/fcoe_transport.c
drivers/ssb/sprom.c
drivers/staging/csr/netdev.c
drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
drivers/staging/silicom/bpctl_mod.c
include/linux/filter.h
include/linux/marvell_phy.h
include/linux/mv643xx_eth.h
include/linux/net.h
include/linux/netdev_features.h
include/linux/netdevice.h
include/linux/netpoll.h
include/linux/phy.h
include/linux/skbuff.h
include/linux/tcp.h
include/net/if_inet6.h
include/net/inet_ecn.h
include/net/ip_fib.h
include/net/ip_tunnels.h
include/net/ipv6.h
include/net/net_namespace.h
include/net/ping.h
include/net/tcp.h
include/net/transp_v6.h
include/uapi/linux/ethtool.h
include/xen/interface/io/netif.h
net/8021q/vlan.c
net/Kconfig
net/Makefile
net/appletalk/aarp.c
net/appletalk/ddp.c
net/atm/clip.c
net/atm/mpc.c
net/ax25/af_ax25.c
net/batman-adv/Makefile
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/bridge_loop_avoidance.h
net/batman-adv/distributed-arp-table.c
net/batman-adv/hard-interface.c
net/batman-adv/icmp_socket.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/ring_buffer.c [deleted file]
net/batman-adv/ring_buffer.h [deleted file]
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/translation-table.c
net/batman-adv/translation-table.h
net/batman-adv/types.h
net/batman-adv/unicast.c
net/batman-adv/vis.c
net/bridge/br_device.c
net/bridge/br_multicast.c
net/bridge/br_notify.c
net/bridge/br_private.h
net/bridge/br_sysfs_br.c
net/caif/caif_dev.c
net/caif/caif_usb.c
net/can/af_can.c
net/can/bcm.c
net/can/gw.c
net/can/raw.c
net/core/dev.c
net/core/drop_monitor.c
net/core/dst.c
net/core/ethtool.c
net/core/fib_rules.c
net/core/net-procfs.c
net/core/netpoll.c
net/core/netprio_cgroup.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sysctl_net_core.c
net/decnet/af_decnet.c
net/ieee802154/6lowpan.c
net/ipv4/Kconfig
net/ipv4/af_inet.c
net/ipv4/ah4.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/esp4.c
net/ipv4/fib_frontend.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_gre.c
net/ipv4/ip_tunnel.c
net/ipv4/ipcomp.c
net/ipv4/ipip.c
net/ipv4/ipmr.c
net/ipv4/netfilter/ipt_MASQUERADE.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/udp.c
net/ipv4/xfrm4_tunnel.c
net/ipv6/Makefile
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/datagram.c
net/ipv6/exthdrs_core.c
net/ipv6/icmp.c
net/ipv6/ip6_offload.c
net/ipv6/ip6mr.c
net/ipv6/mcast.c
net/ipv6/mip6.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6t_MASQUERADE.c
net/ipv6/output_core.c
net/ipv6/ping.c [new file with mode: 0644]
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/udp.c
net/ipv6/udp_offload.c
net/ipx/af_ipx.c
net/iucv/af_iucv.c
net/mac80211/iface.c
net/mpls/Kconfig [new file with mode: 0644]
net/mpls/Makefile [new file with mode: 0644]
net/mpls/mpls_gso.c [new file with mode: 0644]
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_nat_helper.c
net/netfilter/nfnetlink_queue_core.c
net/netfilter/xt_TEE.c
net/netlabel/netlabel_unlabeled.c
net/netrom/af_netrom.c
net/openvswitch/dp_notify.c
net/packet/af_packet.c
net/phonet/pn_dev.c
net/rose/af_rose.c
net/sched/act_mirred.c
net/sched/sch_tbf.c
net/sctp/input.c
net/sctp/ipv6.c
net/tipc/eth_media.c
net/tipc/ib_media.c
net/wireless/core.c
net/x25/af_x25.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
security/selinux/netif.c

diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
new file mode 100644 (file)
index 0000000..b90bfcd
--- /dev/null
@@ -0,0 +1,22 @@
+* Allwinner EMAC ethernet controller
+
+Required properties:
+- compatible: should be "allwinner,sun4i-emac".
+- reg: address and length of the register set for the device.
+- interrupts: interrupt for the device
+- phy: A phandle to a phy node defining the PHY address (as the reg
+  property, a single integer).
+- clocks: A phandle to the reference clock for this device
+
+Optional properties:
+- (local-)mac-address: mac address to be used by this driver
+
+Example:
+
+emac: ethernet@01c0b000 {
+       compatible = "allwinner,sun4i-emac";
+       reg = <0x01c0b000 0x1000>;
+       interrupts = <55>;
+       clocks = <&ahb_gates 17>;
+       phy = <&phy0>;
+};
diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt
new file mode 100644 (file)
index 0000000..00b9f9a
--- /dev/null
@@ -0,0 +1,26 @@
+* Allwinner A10 MDIO Ethernet Controller interface
+
+Required properties:
+- compatible: should be "allwinner,sun4i-mdio".
+- reg: address and length of the register set for the device.
+
+Optional properties:
+- phy-supply: phandle to a regulator if the PHY needs one
+
+Example at the SoC level:
+mdio@01c0b080 {
+       compatible = "allwinner,sun4i-mdio";
+       reg = <0x01c0b080 0x14>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+};
+
+And at the board level:
+
+mdio@01c0b080 {
+       phy-supply = <&reg_emac_3v3>;
+
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+};
index 4f2ca6b4a182d3f9584c72b05414deacb085aebf..05d660e4ac6402f57be201105b94147c69776b53 100644 (file)
@@ -28,6 +28,8 @@ Optional properties:
 Slave Properties:
 Required properties:
 - phy_id               : Specifies slave phy id
+- phy-mode             : The interface between the SoC and the PHY (a string
+                         that of_get_phy_mode() can understand)
 - mac-address          : Specifies slave MAC address
 
 Optional properties:
@@ -58,11 +60,13 @@ Examples:
                cpts_clock_shift = <29>;
                cpsw_emac0: slave@0 {
                        phy_id = <&davinci_mdio>, <0>;
+                       phy-mode = "rgmii-txid";
                        /* Filled in by U-Boot */
                        mac-address = [ 00 00 00 00 00 00 ];
                };
                cpsw_emac1: slave@1 {
                        phy_id = <&davinci_mdio>, <1>;
+                       phy-mode = "rgmii-txid";
                        /* Filled in by U-Boot */
                        mac-address = [ 00 00 00 00 00 00 ];
                };
@@ -84,11 +88,13 @@ Examples:
                cpts_clock_shift = <29>;
                cpsw_emac0: slave@0 {
                        phy_id = <&davinci_mdio>, <0>;
+                       phy-mode = "rgmii-txid";
                        /* Filled in by U-Boot */
                        mac-address = [ 00 00 00 00 00 00 ];
                };
                cpsw_emac1: slave@1 {
                        phy_id = <&davinci_mdio>, <1>;
+                       phy-mode = "rgmii-txid";
                        /* Filled in by U-Boot */
                        mac-address = [ 00 00 00 00 00 00 ];
                };
diff --git a/Documentation/devicetree/bindings/net/davicom-dm9000.txt b/Documentation/devicetree/bindings/net/davicom-dm9000.txt
new file mode 100644 (file)
index 0000000..2d39c99
--- /dev/null
@@ -0,0 +1,26 @@
+Davicom DM9000 Fast Ethernet controller
+
+Required properties:
+- compatible = "davicom,dm9000";
+- reg : physical addresses and sizes of registers, must contain 2 entries:
+    first entry : address register,
+    second entry : data register.
+- interrupt-parent : interrupt controller to which the device is connected
+- interrupts : interrupt specifier specific to interrupt controller
+
+Optional properties:
+- local-mac-address : A bytestring of 6 bytes specifying Ethernet MAC address
+    to use (from firmware or bootloader)
+- davicom,no-eeprom : Configuration EEPROM is not available
+- davicom,ext-phy : Use external PHY
+
+Example:
+
+       ethernet@18000000 {
+               compatible = "davicom,dm9000";
+               reg = <0x18000000 0x2 0x18000004 0x2>;
+               interrupt-parent = <&gpn>;
+               interrupts = <7 4>;
+               local-mac-address = [00 00 de ad be ef];
+               davicom,no-eeprom;
+       };
diff --git a/Documentation/devicetree/bindings/net/marvell-orion-net.txt b/Documentation/devicetree/bindings/net/marvell-orion-net.txt
new file mode 100644 (file)
index 0000000..a73b79f
--- /dev/null
@@ -0,0 +1,85 @@
+Marvell Orion/Discovery ethernet controller
+=============================================
+
+The Marvell Discovery ethernet controller can be found on Marvell Orion SoCs
+(Kirkwood, Dove, Orion5x, and Discovery Innovation) and as part of Marvell
+Discovery system controller chips (mv64[345]60).
+
+The Discovery ethernet controller is described with two levels of nodes. The
+first level describes the ethernet controller itself and the second level
+describes up to 3 ethernet port nodes within that controller. The reason for
+the multiple levels is that the port registers are interleaved within a single
+set of controller registers. Each port node describes port-specific properties.
+
+Note: The above separation is only true for Discovery system controllers.
+For Orion SoCs we stick to the separation, although there each controller has
+only one port associated. Multiple ports are implemented as multiple single-port
+controllers. As Kirkwood has some issues with proper initialization after reset,
+an extra compatible string is added for it.
+
+* Ethernet controller node
+
+Required controller properties:
+ - #address-cells: shall be 1.
+ - #size-cells: shall be 0.
+ - compatible: shall be one of "marvell,orion-eth", "marvell,kirkwood-eth".
+ - reg: address and length of the controller registers.
+
+Optional controller properties:
+ - clocks: phandle reference to the controller clock.
+ - marvell,tx-checksum-limit: max tx packet size for hardware checksum.
+
+* Ethernet port node
+
+Required port properties:
+ - device_type: shall be "network".
+ - compatible: shall be one of "marvell,orion-eth-port",
+      "marvell,kirkwood-eth-port".
+ - reg: port number relative to ethernet controller, shall be 0, 1, or 2.
+ - interrupts: port interrupt.
+ - local-mac-address: 6 bytes MAC address.
+
+Optional port properties:
+ - marvell,tx-queue-size: size of the transmit ring buffer.
+ - marvell,tx-sram-addr: address of transmit descriptor buffer located in SRAM.
+ - marvell,tx-sram-size: size of transmit descriptor buffer located in SRAM.
+ - marvell,rx-queue-size: size of the receive ring buffer.
+ - marvell,rx-sram-addr: address of receive descriptor buffer located in SRAM.
+ - marvell,rx-sram-size: size of receive descriptor buffer located in SRAM.
+
+and
+
+ - phy-handle: phandle reference to ethernet PHY.
+
+or
+
+ - speed: port speed if no PHY connected.
+ - duplex: port mode if no PHY connected.
+
+* Node example:
+
+mdio-bus {
+       ...
+       ethphy: ethernet-phy@8 {
+               device_type = "ethernet-phy";
+               ...
+       };
+};
+
+eth: ethernet-controller@72000 {
+       compatible = "marvell,orion-eth";
+       #address-cells = <1>;
+       #size-cells = <0>;
+       reg = <0x72000 0x2000>;
+       clocks = <&gate_clk 2>;
+       marvell,tx-checksum-limit = <1600>;
+
+       ethernet@0 {
+               device_type = "network";
+               compatible = "marvell,orion-eth-port";
+               reg = <0>;
+               interrupts = <29>;
+               phy-handle = <&ethphy>;
+               local-mac-address = [00 00 00 00 00 00];
+       };
+};
diff --git a/Documentation/devicetree/bindings/net/micrel-ks8851.txt b/Documentation/devicetree/bindings/net/micrel-ks8851.txt
new file mode 100644 (file)
index 0000000..11ace3c
--- /dev/null
@@ -0,0 +1,9 @@
+Micrel KS8851 Ethernet mac
+
+Required properties:
+- compatible = "micrel,ks8851-ml" of parallel interface
+- reg : 2 physical address and size of registers for data and command
+- interrupts : interrupt connection
+
+Optional properties:
+- local-mac-address : Ethernet mac address to use
diff --git a/Documentation/devicetree/bindings/net/via-velocity.txt b/Documentation/devicetree/bindings/net/via-velocity.txt
new file mode 100644 (file)
index 0000000..b3db469
--- /dev/null
@@ -0,0 +1,20 @@
+* VIA Velocity 10/100/1000 Network Controller
+
+Required properties:
+- compatible : Should be "via,velocity-vt6110"
+- reg : Address and length of the io space
+- interrupts : Should contain the controller interrupt line
+
+Optional properties:
+- no-eeprom : PCI network cards use an external EEPROM to store data. Embedded
+       devices quite often set this data in uboot and do not provide an eeprom.
+       Specify this option if you have no external eeprom.
+
+Examples:
+
+eth0@d8004000 {
+       compatible = "via,velocity-vt6110";
+       reg = <0xd8004000 0x400>;
+       interrupts = <10>;
+       no-eeprom;
+};
index 6931c4348d240ed9f8bf6b21a0d75f9c520edf1d..2fe74e6ec209500b593280873b5f82ea1b68b150 100644 (file)
@@ -18,6 +18,7 @@ chrp  Common Hardware Reference Platform
 cirrus Cirrus Logic, Inc.
 cortina        Cortina Systems, Inc.
 dallas Maxim Integrated Products (formerly Dallas Semiconductor)
+davicom        DAVICOM Semiconductor, Inc.
 denx   Denx Software Engineering
 emmicro        EM Microelectronic
 epson  Seiko Epson Corp.
index 286a5680f49051bd9a4abb3dac827af97a1d8f3e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-ifenslave
index 258d9b92c36f78780fdb7f04e767158192361258..32dfbd924121f13747f220d692b0ad61a3a507d2 100644 (file)
@@ -88,8 +88,6 @@ gianfar.txt
        - Gianfar Ethernet Driver.
 ieee802154.txt
        - Linux IEEE 802.15.4 implementation, API and drivers
-ifenslave.c
-       - Configure network interfaces for parallel routing (bonding).
 igb.txt
        - README for the Intel Gigabit Ethernet Driver (igb).
 igbvf.txt
index 24c308dd3fd183f70e8d151fb19a59aa475de02e..0aa1ac98fc2b1b1a9325f066879216d56ae7e1db 100644 (file)
@@ -1,11 +1,6 @@
 # kbuild trick to avoid linker error. Can be omitted if a module is built.
 obj- := dummy.o
 
-# List of programs to build
-hostprogs-y := ifenslave
-
-HOSTCFLAGS_ifenslave.o += -I$(objtree)/usr/include
-
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
 
index 10a015c384b844b946ae8d7b71b81abc7fd33c79..e7454fcc91763549253c0c3daaf5edf872c73a99 100644 (file)
@@ -104,8 +104,7 @@ Table of Contents
 ==============================
 
        Most popular distro kernels ship with the bonding driver
-already available as a module and the ifenslave user level control
-program installed and ready for use. If your distro does not, or you
+already available as a module. If your distro does not, or you
 have need to compile bonding from source (e.g., configuring and
 installing a mainline kernel from kernel.org), you'll need to perform
 the following steps:
@@ -124,46 +123,13 @@ device support" section.  It is recommended that you configure the
 driver as module since it is currently the only way to pass parameters
 to the driver or configure more than one bonding device.
 
-       Build and install the new kernel and modules, then continue
-below to install ifenslave.
+       Build and install the new kernel and modules.
 
-1.2 Install ifenslave Control Utility
+1.2 Bonding Control Utility
 -------------------------------------
 
-       The ifenslave user level control program is included in the
-kernel source tree, in the file Documentation/networking/ifenslave.c.
-It is generally recommended that you use the ifenslave that
-corresponds to the kernel that you are using (either from the same
-source tree or supplied with the distro), however, ifenslave
-executables from older kernels should function (but features newer
-than the ifenslave release are not supported).  Running an ifenslave
-that is newer than the kernel is not supported, and may or may not
-work.
-
-       To install ifenslave, do the following:
-
-# gcc -Wall -O -I/usr/src/linux/include ifenslave.c -o ifenslave
-# cp ifenslave /sbin/ifenslave
-
-       If your kernel source is not in "/usr/src/linux," then replace
-"/usr/src/linux/include" in the above with the location of your kernel
-source include directory.
-
-       You may wish to back up any existing /sbin/ifenslave, or, for
-testing or informal use, tag the ifenslave to the kernel version
-(e.g., name the ifenslave executable /sbin/ifenslave-2.6.10).
-
-IMPORTANT NOTE:
-
-       If you omit the "-I" or specify an incorrect directory, you
-may end up with an ifenslave that is incompatible with the kernel
-you're trying to build it for.  Some distros (e.g., Red Hat from 7.1
-onwards) do not have /usr/include/linux symbolically linked to the
-default kernel source include directory.
-
-SECOND IMPORTANT NOTE:
-       If you plan to configure bonding using sysfs or using the
-/etc/network/interfaces file, you do not need to use ifenslave.
+        It is recommended to configure bonding via iproute2 (netlink)
+or sysfs, the old ifenslave control utility is obsolete.
 
 2. Bonding Driver Options
 =========================
@@ -851,7 +817,7 @@ resend_igmp
 ==============================
 
        You can configure bonding using either your distro's network
-initialization scripts, or manually using either ifenslave or the
+initialization scripts, or manually using either iproute2 or the
 sysfs interface.  Distros generally use one of three packages for the
 network initialization scripts: initscripts, sysconfig or interfaces.
 Recent versions of these packages have support for bonding, while older
@@ -1160,7 +1126,7 @@ not support this method for specifying multiple bonding interfaces; for
 those instances, see the "Configuring Multiple Bonds Manually" section,
 below.
 
-3.3 Configuring Bonding Manually with Ifenslave
+3.3 Configuring Bonding Manually with iproute2
 -----------------------------------------------
 
        This section applies to distros whose network initialization
@@ -1171,7 +1137,7 @@ version 8.
        The general method for these systems is to place the bonding
 module parameters into a config file in /etc/modprobe.d/ (as
 appropriate for the installed distro), then add modprobe and/or
-ifenslave commands to the system's global init script.  The name of
+`ip link` commands to the system's global init script.  The name of
 the global init script differs; for sysconfig, it is
 /etc/init.d/boot.local and for initscripts it is /etc/rc.d/rc.local.
 
@@ -1183,8 +1149,8 @@ reboots, edit the appropriate file (/etc/init.d/boot.local or
 modprobe bonding mode=balance-alb miimon=100
 modprobe e100
 ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up
-ifenslave bond0 eth0
-ifenslave bond0 eth1
+ip link set eth0 master bond0
+ip link set eth1 master bond0
 
        Replace the example bonding module parameters and bond0
 network configuration (IP address, netmask, etc) with the appropriate
diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c
deleted file mode 100644 (file)
index ac5debb..0000000
+++ /dev/null
@@ -1,1105 +0,0 @@
-/* Mode: C;
- * ifenslave.c: Configure network interfaces for parallel routing.
- *
- *     This program controls the Linux implementation of running multiple
- *     network interfaces in parallel.
- *
- * Author:     Donald Becker <becker@cesdis.gsfc.nasa.gov>
- *             Copyright 1994-1996 Donald Becker
- *
- *             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.
- *
- *     The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
- *     Center of Excellence in Space Data and Information Sciences
- *        Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
- *
- *  Changes :
- *    - 2000/10/02 Willy Tarreau <willy at meta-x.org> :
- *       - few fixes. Master's MAC address is now correctly taken from
- *         the first device when not previously set ;
- *       - detach support : call BOND_RELEASE to detach an enslaved interface.
- *       - give a mini-howto from command-line help : # ifenslave -h
- *
- *    - 2001/02/16 Chad N. Tindel <ctindel at ieee dot org> :
- *       - Master is now brought down before setting the MAC address.  In
- *         the 2.4 kernel you can't change the MAC address while the device is
- *         up because you get EBUSY.
- *
- *    - 2001/09/13 Takao Indoh <indou dot takao at jp dot fujitsu dot com>
- *       - Added the ability to change the active interface on a mode 1 bond
- *         at runtime.
- *
- *    - 2001/10/23 Chad N. Tindel <ctindel at ieee dot org> :
- *       - No longer set the MAC address of the master.  The bond device will
- *         take care of this itself
- *       - Try the SIOC*** versions of the bonding ioctls before using the
- *         old versions
- *    - 2002/02/18 Erik Habbinga <erik_habbinga @ hp dot com> :
- *       - ifr2.ifr_flags was not initialized in the hwaddr_notset case,
- *         SIOCGIFFLAGS now called before hwaddr_notset test
- *
- *    - 2002/10/31 Tony Cureington <tony.cureington * hp_com> :
- *       - If the master does not have a hardware address when the first slave
- *         is enslaved, the master is assigned the hardware address of that
- *         slave - there is a comment in bonding.c stating "ifenslave takes
- *         care of this now." This corrects the problem of slaves having
- *         different hardware addresses in active-backup mode when
- *         multiple interfaces are specified on a single ifenslave command
- *         (ifenslave bond0 eth0 eth1).
- *
- *    - 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *                   Shmulik Hen <shmulik.hen at intel dot com>
- *       - Moved setting the slave's mac address and openning it, from
- *         the application to the driver. This enables support of modes
- *         that need to use the unique mac address of each slave.
- *         The driver also takes care of closing the slave and restoring its
- *         original mac address upon release.
- *         In addition, block possibility of enslaving before the master is up.
- *         This prevents putting the system in an undefined state.
- *
- *    - 2003/05/01 - Amir Noam <amir.noam at intel dot com>
- *       - Added ABI version control to restore compatibility between
- *         new/old ifenslave and new/old bonding.
- *       - Prevent adding an adapter that is already a slave.
- *         Fixes the problem of stalling the transmission and leaving
- *         the slave in a down state.
- *
- *    - 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *       - Prevent enslaving if the bond device is down.
- *         Fixes the problem of leaving the system in unstable state and
- *         halting when trying to remove the module.
- *       - Close socket on all abnormal exists.
- *       - Add versioning scheme that follows that of the bonding driver.
- *         current version is 1.0.0 as a base line.
- *
- *    - 2003/05/22 - Jay Vosburgh <fubar at us dot ibm dot com>
- *      - ifenslave -c was broken; it's now fixed
- *      - Fixed problem with routes vanishing from master during enslave
- *        processing.
- *
- *    - 2003/05/27 - Amir Noam <amir.noam at intel dot com>
- *      - Fix backward compatibility issues:
- *        For drivers not using ABI versions, slave was set down while
- *        it should be left up before enslaving.
- *        Also, master was not set down and the default set_mac_address()
- *        would fail and generate an error message in the system log.
- *      - For opt_c: slave should not be set to the master's setting
- *        while it is running. It was already set during enslave. To
- *        simplify things, it is now handled separately.
- *
- *    - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *      - Code cleanup and style changes
- *        set version to 1.1.0
- */
-
-#define APP_VERSION    "1.1.0"
-#define APP_RELDATE    "December 1, 2003"
-#define APP_NAME       "ifenslave"
-
-static char *version =
-APP_NAME ".c:v" APP_VERSION " (" APP_RELDATE ")\n"
-"o Donald Becker (becker@cesdis.gsfc.nasa.gov).\n"
-"o Detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n"
-"o 2.4 kernel support added on 2001/02/16 by Chad N. Tindel\n"
-"  (ctindel at ieee dot org).\n";
-
-static const char *usage_msg =
-"Usage: ifenslave [-f] <master-if> <slave-if> [<slave-if>...]\n"
-"       ifenslave -d   <master-if> <slave-if> [<slave-if>...]\n"
-"       ifenslave -c   <master-if> <slave-if>\n"
-"       ifenslave --help\n";
-
-static const char *help_msg =
-"\n"
-"       To create a bond device, simply follow these three steps :\n"
-"       - ensure that the required drivers are properly loaded :\n"
-"         # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n"
-"       - assign an IP address to the bond device :\n"
-"         # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n"
-"       - attach all the interfaces you need to the bond device :\n"
-"         # ifenslave [{-f|--force}] bond0 eth0 [eth1 [eth2]...]\n"
-"         If bond0 didn't have a MAC address, it will take eth0's. Then, all\n"
-"         interfaces attached AFTER this assignment will get the same MAC addr.\n"
-"         (except for ALB/TLB modes)\n"
-"\n"
-"       To set the bond device down and automatically release all the slaves :\n"
-"         # ifconfig bond0 down\n"
-"\n"
-"       To detach a dead interface without setting the bond device down :\n"
-"         # ifenslave {-d|--detach} bond0 eth0 [eth1 [eth2]...]\n"
-"\n"
-"       To change active slave :\n"
-"         # ifenslave {-c|--change-active} bond0 eth0\n"
-"\n"
-"       To show master interface info\n"
-"         # ifenslave bond0\n"
-"\n"
-"       To show all interfaces info\n"
-"       # ifenslave {-a|--all-interfaces}\n"
-"\n"
-"       To be more verbose\n"
-"       # ifenslave {-v|--verbose} ...\n"
-"\n"
-"       # ifenslave {-u|--usage}   Show usage\n"
-"       # ifenslave {-V|--version} Show version\n"
-"       # ifenslave {-h|--help}    This message\n"
-"\n";
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <linux/if.h>
-#include <net/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/if_bonding.h>
-#include <linux/sockios.h>
-
-typedef unsigned long long u64;        /* hack, so we may include kernel's ethtool.h */
-typedef __uint32_t u32;                /* ditto */
-typedef __uint16_t u16;                /* ditto */
-typedef __uint8_t u8;          /* ditto */
-#include <linux/ethtool.h>
-
-struct option longopts[] = {
-       /* { name  has_arg  *flag  val } */
-       {"all-interfaces",      0, 0, 'a'},     /* Show all interfaces. */
-       {"change-active",       0, 0, 'c'},     /* Change the active slave.  */
-       {"detach",              0, 0, 'd'},     /* Detach a slave interface. */
-       {"force",               0, 0, 'f'},     /* Force the operation. */
-       {"help",                0, 0, 'h'},     /* Give help */
-       {"usage",               0, 0, 'u'},     /* Give usage */
-       {"verbose",             0, 0, 'v'},     /* Report each action taken. */
-       {"version",             0, 0, 'V'},     /* Emit version information. */
-       { 0, 0, 0, 0}
-};
-
-/* Command-line flags. */
-unsigned int
-opt_a = 0,     /* Show-all-interfaces flag. */
-opt_c = 0,     /* Change-active-slave flag. */
-opt_d = 0,     /* Detach a slave interface. */
-opt_f = 0,     /* Force the operation. */
-opt_h = 0,     /* Help */
-opt_u = 0,     /* Usage */
-opt_v = 0,     /* Verbose flag. */
-opt_V = 0;     /* Version */
-
-int skfd = -1;         /* AF_INET socket for ioctl() calls.*/
-int abi_ver = 0;       /* userland - kernel ABI version */
-int hwaddr_set = 0;    /* Master's hwaddr is set */
-int saved_errno;
-
-struct ifreq master_mtu, master_flags, master_hwaddr;
-struct ifreq slave_mtu, slave_flags, slave_hwaddr;
-
-struct dev_ifr {
-       struct ifreq *req_ifr;
-       char *req_name;
-       int req_type;
-};
-
-struct dev_ifr master_ifra[] = {
-       {&master_mtu,     "SIOCGIFMTU",     SIOCGIFMTU},
-       {&master_flags,   "SIOCGIFFLAGS",   SIOCGIFFLAGS},
-       {&master_hwaddr,  "SIOCGIFHWADDR",  SIOCGIFHWADDR},
-       {NULL, "", 0}
-};
-
-struct dev_ifr slave_ifra[] = {
-       {&slave_mtu,     "SIOCGIFMTU",     SIOCGIFMTU},
-       {&slave_flags,   "SIOCGIFFLAGS",   SIOCGIFFLAGS},
-       {&slave_hwaddr,  "SIOCGIFHWADDR",  SIOCGIFHWADDR},
-       {NULL, "", 0}
-};
-
-static void if_print(char *ifname);
-static int get_drv_info(char *master_ifname);
-static int get_if_settings(char *ifname, struct dev_ifr ifra[]);
-static int get_slave_flags(char *slave_ifname);
-static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr);
-static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr);
-static int set_slave_mtu(char *slave_ifname, int mtu);
-static int set_if_flags(char *ifname, short flags);
-static int set_if_up(char *ifname, short flags);
-static int set_if_down(char *ifname, short flags);
-static int clear_if_addr(char *ifname);
-static int set_if_addr(char *master_ifname, char *slave_ifname);
-static int change_active(char *master_ifname, char *slave_ifname);
-static int enslave(char *master_ifname, char *slave_ifname);
-static int release(char *master_ifname, char *slave_ifname);
-#define v_print(fmt, args...)  \
-       if (opt_v)              \
-               fprintf(stderr, fmt, ## args )
-
-int main(int argc, char *argv[])
-{
-       char **spp, *master_ifname, *slave_ifname;
-       int c, i, rv;
-       int res = 0;
-       int exclusive = 0;
-
-       while ((c = getopt_long(argc, argv, "acdfhuvV", longopts, 0)) != EOF) {
-               switch (c) {
-               case 'a': opt_a++; exclusive++; break;
-               case 'c': opt_c++; exclusive++; break;
-               case 'd': opt_d++; exclusive++; break;
-               case 'f': opt_f++; exclusive++; break;
-               case 'h': opt_h++; exclusive++; break;
-               case 'u': opt_u++; exclusive++; break;
-               case 'v': opt_v++; break;
-               case 'V': opt_V++; exclusive++; break;
-
-               case '?':
-                       fprintf(stderr, "%s", usage_msg);
-                       res = 2;
-                       goto out;
-               }
-       }
-
-       /* options check */
-       if (exclusive > 1) {
-               fprintf(stderr, "%s", usage_msg);
-               res = 2;
-               goto out;
-       }
-
-       if (opt_v || opt_V) {
-               printf("%s", version);
-               if (opt_V) {
-                       res = 0;
-                       goto out;
-               }
-       }
-
-       if (opt_u) {
-               printf("%s", usage_msg);
-               res = 0;
-               goto out;
-       }
-
-       if (opt_h) {
-               printf("%s", usage_msg);
-               printf("%s", help_msg);
-               res = 0;
-               goto out;
-       }
-
-       /* Open a basic socket */
-       if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               perror("socket");
-               res = 1;
-               goto out;
-       }
-
-       if (opt_a) {
-               if (optind == argc) {
-                       /* No remaining args */
-                       /* show all interfaces */
-                       if_print((char *)NULL);
-                       goto out;
-               } else {
-                       /* Just show usage */
-                       fprintf(stderr, "%s", usage_msg);
-                       res = 2;
-                       goto out;
-               }
-       }
-
-       /* Copy the interface name */
-       spp = argv + optind;
-       master_ifname = *spp++;
-
-       if (master_ifname == NULL) {
-               fprintf(stderr, "%s", usage_msg);
-               res = 2;
-               goto out;
-       }
-
-       /* exchange abi version with bonding module */
-       res = get_drv_info(master_ifname);
-       if (res) {
-               fprintf(stderr,
-                       "Master '%s': Error: handshake with driver failed. "
-                       "Aborting\n",
-                       master_ifname);
-               goto out;
-       }
-
-       slave_ifname = *spp++;
-
-       if (slave_ifname == NULL) {
-               if (opt_d || opt_c) {
-                       fprintf(stderr, "%s", usage_msg);
-                       res = 2;
-                       goto out;
-               }
-
-               /* A single arg means show the
-                * configuration for this interface
-                */
-               if_print(master_ifname);
-               goto out;
-       }
-
-       res = get_if_settings(master_ifname, master_ifra);
-       if (res) {
-               /* Probably a good reason not to go on */
-               fprintf(stderr,
-                       "Master '%s': Error: get settings failed: %s. "
-                       "Aborting\n",
-                       master_ifname, strerror(res));
-               goto out;
-       }
-
-       /* check if master is indeed a master;
-        * if not then fail any operation
-        */
-       if (!(master_flags.ifr_flags & IFF_MASTER)) {
-               fprintf(stderr,
-                       "Illegal operation; the specified interface '%s' "
-                       "is not a master. Aborting\n",
-                       master_ifname);
-               res = 1;
-               goto out;
-       }
-
-       /* check if master is up; if not then fail any operation */
-       if (!(master_flags.ifr_flags & IFF_UP)) {
-               fprintf(stderr,
-                       "Illegal operation; the specified master interface "
-                       "'%s' is not up.\n",
-                       master_ifname);
-               res = 1;
-               goto out;
-       }
-
-       /* Only for enslaving */
-       if (!opt_c && !opt_d) {
-               sa_family_t master_family = master_hwaddr.ifr_hwaddr.sa_family;
-               unsigned char *hwaddr =
-                       (unsigned char *)master_hwaddr.ifr_hwaddr.sa_data;
-
-               /* The family '1' is ARPHRD_ETHER for ethernet. */
-               if (master_family != 1 && !opt_f) {
-                       fprintf(stderr,
-                               "Illegal operation: The specified master "
-                               "interface '%s' is not ethernet-like.\n "
-                               "This program is designed to work with "
-                               "ethernet-like network interfaces.\n "
-                               "Use the '-f' option to force the "
-                               "operation.\n",
-                               master_ifname);
-                       res = 1;
-                       goto out;
-               }
-
-               /* Check master's hw addr */
-               for (i = 0; i < 6; i++) {
-                       if (hwaddr[i] != 0) {
-                               hwaddr_set = 1;
-                               break;
-                       }
-               }
-
-               if (hwaddr_set) {
-                       v_print("current hardware address of master '%s' "
-                               "is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
-                               "type %d\n",
-                               master_ifname,
-                               hwaddr[0], hwaddr[1],
-                               hwaddr[2], hwaddr[3],
-                               hwaddr[4], hwaddr[5],
-                               master_family);
-               }
-       }
-
-       /* Accepts only one slave */
-       if (opt_c) {
-               /* change active slave */
-               res = get_slave_flags(slave_ifname);
-               if (res) {
-                       fprintf(stderr,
-                               "Slave '%s': Error: get flags failed. "
-                               "Aborting\n",
-                               slave_ifname);
-                       goto out;
-               }
-               res = change_active(master_ifname, slave_ifname);
-               if (res) {
-                       fprintf(stderr,
-                               "Master '%s', Slave '%s': Error: "
-                               "Change active failed\n",
-                               master_ifname, slave_ifname);
-               }
-       } else {
-               /* Accept multiple slaves */
-               do {
-                       if (opt_d) {
-                               /* detach a slave interface from the master */
-                               rv = get_slave_flags(slave_ifname);
-                               if (rv) {
-                                       /* Can't work with this slave. */
-                                       /* remember the error and skip it*/
-                                       fprintf(stderr,
-                                               "Slave '%s': Error: get flags "
-                                               "failed. Skipping\n",
-                                               slave_ifname);
-                                       res = rv;
-                                       continue;
-                               }
-                               rv = release(master_ifname, slave_ifname);
-                               if (rv) {
-                                       fprintf(stderr,
-                                               "Master '%s', Slave '%s': Error: "
-                                               "Release failed\n",
-                                               master_ifname, slave_ifname);
-                                       res = rv;
-                               }
-                       } else {
-                               /* attach a slave interface to the master */
-                               rv = get_if_settings(slave_ifname, slave_ifra);
-                               if (rv) {
-                                       /* Can't work with this slave. */
-                                       /* remember the error and skip it*/
-                                       fprintf(stderr,
-                                               "Slave '%s': Error: get "
-                                               "settings failed: %s. "
-                                               "Skipping\n",
-                                               slave_ifname, strerror(rv));
-                                       res = rv;
-                                       continue;
-                               }
-                               rv = enslave(master_ifname, slave_ifname);
-                               if (rv) {
-                                       fprintf(stderr,
-                                               "Master '%s', Slave '%s': Error: "
-                                               "Enslave failed\n",
-                                               master_ifname, slave_ifname);
-                                       res = rv;
-                               }
-                       }
-               } while ((slave_ifname = *spp++) != NULL);
-       }
-
-out:
-       if (skfd >= 0) {
-               close(skfd);
-       }
-
-       return res;
-}
-
-static short mif_flags;
-
-/* Get the inteface configuration from the kernel. */
-static int if_getconfig(char *ifname)
-{
-       struct ifreq ifr;
-       int metric, mtu;        /* Parameters of the master interface. */
-       struct sockaddr dstaddr, broadaddr, netmask;
-       unsigned char *hwaddr;
-
-       strcpy(ifr.ifr_name, ifname);
-       if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
-               return -1;
-       mif_flags = ifr.ifr_flags;
-       printf("The result of SIOCGIFFLAGS on %s is %x.\n",
-              ifname, ifr.ifr_flags);
-
-       strcpy(ifr.ifr_name, ifname);
-       if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0)
-               return -1;
-       printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n",
-              ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1],
-              ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]);
-
-       strcpy(ifr.ifr_name, ifname);
-       if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
-               return -1;
-
-       /* Gotta convert from 'char' to unsigned for printf(). */
-       hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data;
-       printf("The result of SIOCGIFHWADDR is type %d  "
-              "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
-              ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
-              hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
-
-       strcpy(ifr.ifr_name, ifname);
-       if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) {
-               metric = 0;
-       } else
-               metric = ifr.ifr_metric;
-       printf("The result of SIOCGIFMETRIC is %d\n", metric);
-
-       strcpy(ifr.ifr_name, ifname);
-       if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
-               mtu = 0;
-       else
-               mtu = ifr.ifr_mtu;
-       printf("The result of SIOCGIFMTU is %d\n", mtu);
-
-       strcpy(ifr.ifr_name, ifname);
-       if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) < 0) {
-               memset(&dstaddr, 0, sizeof(struct sockaddr));
-       } else
-               dstaddr = ifr.ifr_dstaddr;
-
-       strcpy(ifr.ifr_name, ifname);
-       if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) {
-               memset(&broadaddr, 0, sizeof(struct sockaddr));
-       } else
-               broadaddr = ifr.ifr_broadaddr;
-
-       strcpy(ifr.ifr_name, ifname);
-       if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) {
-               memset(&netmask, 0, sizeof(struct sockaddr));
-       } else
-               netmask = ifr.ifr_netmask;
-
-       return 0;
-}
-
-static void if_print(char *ifname)
-{
-       char buff[1024];
-       struct ifconf ifc;
-       struct ifreq *ifr;
-       int i;
-
-       if (ifname == (char *)NULL) {
-               ifc.ifc_len = sizeof(buff);
-               ifc.ifc_buf = buff;
-               if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
-                       perror("SIOCGIFCONF failed");
-                       return;
-               }
-
-               ifr = ifc.ifc_req;
-               for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
-                       if (if_getconfig(ifr->ifr_name) < 0) {
-                               fprintf(stderr,
-                                       "%s: unknown interface.\n",
-                                       ifr->ifr_name);
-                               continue;
-                       }
-
-                       if (((mif_flags & IFF_UP) == 0) && !opt_a) continue;
-                       /*ife_print(&ife);*/
-               }
-       } else {
-               if (if_getconfig(ifname) < 0) {
-                       fprintf(stderr,
-                               "%s: unknown interface.\n", ifname);
-               }
-       }
-}
-
-static int get_drv_info(char *master_ifname)
-{
-       struct ifreq ifr;
-       struct ethtool_drvinfo info;
-       char *endptr;
-
-       memset(&ifr, 0, sizeof(ifr));
-       strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
-       ifr.ifr_data = (caddr_t)&info;
-
-       info.cmd = ETHTOOL_GDRVINFO;
-       strncpy(info.driver, "ifenslave", 32);
-       snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION);
-
-       if (ioctl(skfd, SIOCETHTOOL, &ifr) < 0) {
-               if (errno == EOPNOTSUPP) {
-                       goto out;
-               }
-
-               saved_errno = errno;
-               v_print("Master '%s': Error: get bonding info failed %s\n",
-                       master_ifname, strerror(saved_errno));
-               return 1;
-       }
-
-       abi_ver = strtoul(info.fw_version, &endptr, 0);
-       if (*endptr) {
-                v_print("Master '%s': Error: got invalid string as an ABI "
-                       "version from the bonding module\n",
-                       master_ifname);
-               return 1;
-       }
-
-out:
-       v_print("ABI ver is %d\n", abi_ver);
-
-       return 0;
-}
-
-static int change_active(char *master_ifname, char *slave_ifname)
-{
-       struct ifreq ifr;
-       int res = 0;
-
-       if (!(slave_flags.ifr_flags & IFF_SLAVE)) {
-               fprintf(stderr,
-                       "Illegal operation: The specified slave interface "
-                       "'%s' is not a slave\n",
-                       slave_ifname);
-               return 1;
-       }
-
-       strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
-       strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
-       if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &ifr) < 0) &&
-           (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &ifr) < 0)) {
-               saved_errno = errno;
-               v_print("Master '%s': Error: SIOCBONDCHANGEACTIVE failed: "
-                       "%s\n",
-                       master_ifname, strerror(saved_errno));
-               res = 1;
-       }
-
-       return res;
-}
-
-static int enslave(char *master_ifname, char *slave_ifname)
-{
-       struct ifreq ifr;
-       int res = 0;
-
-       if (slave_flags.ifr_flags & IFF_SLAVE) {
-               fprintf(stderr,
-                       "Illegal operation: The specified slave interface "
-                       "'%s' is already a slave\n",
-                       slave_ifname);
-               return 1;
-       }
-
-       res = set_if_down(slave_ifname, slave_flags.ifr_flags);
-       if (res) {
-               fprintf(stderr,
-                       "Slave '%s': Error: bring interface down failed\n",
-                       slave_ifname);
-               return res;
-       }
-
-       if (abi_ver < 2) {
-               /* Older bonding versions would panic if the slave has no IP
-                * address, so get the IP setting from the master.
-                */
-               set_if_addr(master_ifname, slave_ifname);
-       } else {
-               res = clear_if_addr(slave_ifname);
-               if (res) {
-                       fprintf(stderr,
-                               "Slave '%s': Error: clear address failed\n",
-                               slave_ifname);
-                       return res;
-               }
-       }
-
-       if (master_mtu.ifr_mtu != slave_mtu.ifr_mtu) {
-               res = set_slave_mtu(slave_ifname, master_mtu.ifr_mtu);
-               if (res) {
-                       fprintf(stderr,
-                               "Slave '%s': Error: set MTU failed\n",
-                               slave_ifname);
-                       return res;
-               }
-       }
-
-       if (hwaddr_set) {
-               /* Master already has an hwaddr
-                * so set it's hwaddr to the slave
-                */
-               if (abi_ver < 1) {
-                       /* The driver is using an old ABI, so
-                        * the application sets the slave's
-                        * hwaddr
-                        */
-                       res = set_slave_hwaddr(slave_ifname,
-                                              &(master_hwaddr.ifr_hwaddr));
-                       if (res) {
-                               fprintf(stderr,
-                                       "Slave '%s': Error: set hw address "
-                                       "failed\n",
-                                       slave_ifname);
-                               goto undo_mtu;
-                       }
-
-                       /* For old ABI the application needs to bring the
-                        * slave back up
-                        */
-                       res = set_if_up(slave_ifname, slave_flags.ifr_flags);
-                       if (res) {
-                               fprintf(stderr,
-                                       "Slave '%s': Error: bring interface "
-                                       "down failed\n",
-                                       slave_ifname);
-                               goto undo_slave_mac;
-                       }
-               }
-               /* The driver is using a new ABI,
-                * so the driver takes care of setting
-                * the slave's hwaddr and bringing
-                * it up again
-                */
-       } else {
-               /* No hwaddr for master yet, so
-                * set the slave's hwaddr to it
-                */
-               if (abi_ver < 1) {
-                       /* For old ABI, the master needs to be
-                        * down before setting its hwaddr
-                        */
-                       res = set_if_down(master_ifname, master_flags.ifr_flags);
-                       if (res) {
-                               fprintf(stderr,
-                                       "Master '%s': Error: bring interface "
-                                       "down failed\n",
-                                       master_ifname);
-                               goto undo_mtu;
-                       }
-               }
-
-               res = set_master_hwaddr(master_ifname,
-                                       &(slave_hwaddr.ifr_hwaddr));
-               if (res) {
-                       fprintf(stderr,
-                               "Master '%s': Error: set hw address "
-                               "failed\n",
-                               master_ifname);
-                       goto undo_mtu;
-               }
-
-               if (abi_ver < 1) {
-                       /* For old ABI, bring the master
-                        * back up
-                        */
-                       res = set_if_up(master_ifname, master_flags.ifr_flags);
-                       if (res) {
-                               fprintf(stderr,
-                                       "Master '%s': Error: bring interface "
-                                       "up failed\n",
-                                       master_ifname);
-                               goto undo_master_mac;
-                       }
-               }
-
-               hwaddr_set = 1;
-       }
-
-       /* Do the real thing */
-       strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
-       strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
-       if ((ioctl(skfd, SIOCBONDENSLAVE, &ifr) < 0) &&
-           (ioctl(skfd, BOND_ENSLAVE_OLD, &ifr) < 0)) {
-               saved_errno = errno;
-               v_print("Master '%s': Error: SIOCBONDENSLAVE failed: %s\n",
-                       master_ifname, strerror(saved_errno));
-               res = 1;
-       }
-
-       if (res) {
-               goto undo_master_mac;
-       }
-
-       return 0;
-
-/* rollback (best effort) */
-undo_master_mac:
-       set_master_hwaddr(master_ifname, &(master_hwaddr.ifr_hwaddr));
-       hwaddr_set = 0;
-       goto undo_mtu;
-undo_slave_mac:
-       set_slave_hwaddr(slave_ifname, &(slave_hwaddr.ifr_hwaddr));
-undo_mtu:
-       set_slave_mtu(slave_ifname, slave_mtu.ifr_mtu);
-       return res;
-}
-
-static int release(char *master_ifname, char *slave_ifname)
-{
-       struct ifreq ifr;
-       int res = 0;
-
-       if (!(slave_flags.ifr_flags & IFF_SLAVE)) {
-               fprintf(stderr,
-                       "Illegal operation: The specified slave interface "
-                       "'%s' is not a slave\n",
-                       slave_ifname);
-               return 1;
-       }
-
-       strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
-       strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
-       if ((ioctl(skfd, SIOCBONDRELEASE, &ifr) < 0) &&
-           (ioctl(skfd, BOND_RELEASE_OLD, &ifr) < 0)) {
-               saved_errno = errno;
-               v_print("Master '%s': Error: SIOCBONDRELEASE failed: %s\n",
-                       master_ifname, strerror(saved_errno));
-               return 1;
-       } else if (abi_ver < 1) {
-               /* The driver is using an old ABI, so we'll set the interface
-                * down to avoid any conflicts due to same MAC/IP
-                */
-               res = set_if_down(slave_ifname, slave_flags.ifr_flags);
-               if (res) {
-                       fprintf(stderr,
-                               "Slave '%s': Error: bring interface "
-                               "down failed\n",
-                               slave_ifname);
-               }
-       }
-
-       /* set to default mtu */
-       set_slave_mtu(slave_ifname, 1500);
-
-       return res;
-}
-
-static int get_if_settings(char *ifname, struct dev_ifr ifra[])
-{
-       int i;
-       int res = 0;
-
-       for (i = 0; ifra[i].req_ifr; i++) {
-               strncpy(ifra[i].req_ifr->ifr_name, ifname, IFNAMSIZ);
-               res = ioctl(skfd, ifra[i].req_type, ifra[i].req_ifr);
-               if (res < 0) {
-                       saved_errno = errno;
-                       v_print("Interface '%s': Error: %s failed: %s\n",
-                               ifname, ifra[i].req_name,
-                               strerror(saved_errno));
-
-                       return saved_errno;
-               }
-       }
-
-       return 0;
-}
-
-static int get_slave_flags(char *slave_ifname)
-{
-       int res = 0;
-
-       strncpy(slave_flags.ifr_name, slave_ifname, IFNAMSIZ);
-       res = ioctl(skfd, SIOCGIFFLAGS, &slave_flags);
-       if (res < 0) {
-               saved_errno = errno;
-               v_print("Slave '%s': Error: SIOCGIFFLAGS failed: %s\n",
-                       slave_ifname, strerror(saved_errno));
-       } else {
-               v_print("Slave %s: flags %04X.\n",
-                       slave_ifname, slave_flags.ifr_flags);
-       }
-
-       return res;
-}
-
-static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr)
-{
-       unsigned char *addr = (unsigned char *)hwaddr->sa_data;
-       struct ifreq ifr;
-       int res = 0;
-
-       strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
-       memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr));
-       res = ioctl(skfd, SIOCSIFHWADDR, &ifr);
-       if (res < 0) {
-               saved_errno = errno;
-               v_print("Master '%s': Error: SIOCSIFHWADDR failed: %s\n",
-                       master_ifname, strerror(saved_errno));
-               return res;
-       } else {
-               v_print("Master '%s': hardware address set to "
-                       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
-                       master_ifname, addr[0], addr[1], addr[2],
-                       addr[3], addr[4], addr[5]);
-       }
-
-       return res;
-}
-
-static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr)
-{
-       unsigned char *addr = (unsigned char *)hwaddr->sa_data;
-       struct ifreq ifr;
-       int res = 0;
-
-       strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ);
-       memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr));
-       res = ioctl(skfd, SIOCSIFHWADDR, &ifr);
-       if (res < 0) {
-               saved_errno = errno;
-
-               v_print("Slave '%s': Error: SIOCSIFHWADDR failed: %s\n",
-                       slave_ifname, strerror(saved_errno));
-
-               if (saved_errno == EBUSY) {
-                       v_print("  The device is busy: it must be idle "
-                               "before running this command.\n");
-               } else if (saved_errno == EOPNOTSUPP) {
-                       v_print("  The device does not support setting "
-                               "the MAC address.\n"
-                               "  Your kernel likely does not support slave "
-                               "devices.\n");
-               } else if (saved_errno == EINVAL) {
-                       v_print("  The device's address type does not match "
-                               "the master's address type.\n");
-               }
-               return res;
-       } else {
-               v_print("Slave '%s': hardware address set to "
-                       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
-                       slave_ifname, addr[0], addr[1], addr[2],
-                       addr[3], addr[4], addr[5]);
-       }
-
-       return res;
-}
-
-static int set_slave_mtu(char *slave_ifname, int mtu)
-{
-       struct ifreq ifr;
-       int res = 0;
-
-       ifr.ifr_mtu = mtu;
-       strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ);
-
-       res = ioctl(skfd, SIOCSIFMTU, &ifr);
-       if (res < 0) {
-               saved_errno = errno;
-               v_print("Slave '%s': Error: SIOCSIFMTU failed: %s\n",
-                       slave_ifname, strerror(saved_errno));
-       } else {
-               v_print("Slave '%s': MTU set to %d.\n", slave_ifname, mtu);
-       }
-
-       return res;
-}
-
-static int set_if_flags(char *ifname, short flags)
-{
-       struct ifreq ifr;
-       int res = 0;
-
-       ifr.ifr_flags = flags;
-       strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
-
-       res = ioctl(skfd, SIOCSIFFLAGS, &ifr);
-       if (res < 0) {
-               saved_errno = errno;
-               v_print("Interface '%s': Error: SIOCSIFFLAGS failed: %s\n",
-                       ifname, strerror(saved_errno));
-       } else {
-               v_print("Interface '%s': flags set to %04X.\n", ifname, flags);
-       }
-
-       return res;
-}
-
-static int set_if_up(char *ifname, short flags)
-{
-       return set_if_flags(ifname, flags | IFF_UP);
-}
-
-static int set_if_down(char *ifname, short flags)
-{
-       return set_if_flags(ifname, flags & ~IFF_UP);
-}
-
-static int clear_if_addr(char *ifname)
-{
-       struct ifreq ifr;
-       int res = 0;
-
-       strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
-       ifr.ifr_addr.sa_family = AF_INET;
-       memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data));
-
-       res = ioctl(skfd, SIOCSIFADDR, &ifr);
-       if (res < 0) {
-               saved_errno = errno;
-               v_print("Interface '%s': Error: SIOCSIFADDR failed: %s\n",
-                       ifname, strerror(saved_errno));
-       } else {
-               v_print("Interface '%s': address cleared\n", ifname);
-       }
-
-       return res;
-}
-
-static int set_if_addr(char *master_ifname, char *slave_ifname)
-{
-       struct ifreq ifr;
-       int res;
-       unsigned char *ipaddr;
-       int i;
-       struct {
-               char *req_name;
-               char *desc;
-               int g_ioctl;
-               int s_ioctl;
-       } ifra[] = {
-               {"IFADDR", "addr", SIOCGIFADDR, SIOCSIFADDR},
-               {"DSTADDR", "destination addr", SIOCGIFDSTADDR, SIOCSIFDSTADDR},
-               {"BRDADDR", "broadcast addr", SIOCGIFBRDADDR, SIOCSIFBRDADDR},
-               {"NETMASK", "netmask", SIOCGIFNETMASK, SIOCSIFNETMASK},
-               {NULL, NULL, 0, 0},
-       };
-
-       for (i = 0; ifra[i].req_name; i++) {
-               strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
-               res = ioctl(skfd, ifra[i].g_ioctl, &ifr);
-               if (res < 0) {
-                       int saved_errno = errno;
-
-                       v_print("Interface '%s': Error: SIOCG%s failed: %s\n",
-                               master_ifname, ifra[i].req_name,
-                               strerror(saved_errno));
-
-                       ifr.ifr_addr.sa_family = AF_INET;
-                       memset(ifr.ifr_addr.sa_data, 0,
-                              sizeof(ifr.ifr_addr.sa_data));
-               }
-
-               strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ);
-               res = ioctl(skfd, ifra[i].s_ioctl, &ifr);
-               if (res < 0) {
-                       int saved_errno = errno;
-
-                       v_print("Interface '%s': Error: SIOCS%s failed: %s\n",
-                               slave_ifname, ifra[i].req_name,
-                               strerror(saved_errno));
-
-               }
-
-               ipaddr = (unsigned char *)ifr.ifr_addr.sa_data;
-               v_print("Interface '%s': set IP %s to %d.%d.%d.%d\n",
-                       slave_ifname, ifra[i].desc,
-                       ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
-       }
-
-       return 0;
-}
-
-/*
- * Local variables:
- *  version-control: t
- *  kept-new-versions: 5
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- *  compile-command: "gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave"
- * End:
- */
-
index f98ca633b5282eb838ae1b04f9497e4a4495f198..398d0fb1dd0e033bbe76ea87d7f67054da0d696a 100644 (file)
@@ -183,7 +183,7 @@ tcp_early_retrans - INTEGER
        for triggering fast retransmit when the amount of outstanding data is
        small and when no previously unsent data can be transmitted (such
        that limited transmit could be used). Also controls the use of
-       Tail loss probe (TLP) that converts RTOs occuring due to tail
+       Tail loss probe (TLP) that converts RTOs occurring due to tail
        losses into fast recovery (draft-dukkipati-tcpm-tcp-loss-probe-01).
        Possible values:
                0 disables ER
index 1c2dab4096252bd54fc839f5ec435f161f94a537..e6088baf109de98567731eb4de901a52ce029bfa 100644 (file)
@@ -54,7 +54,7 @@ it will use an allocated socket buffer as usual and the contents will be
  copied to the ring on transmission, nullifying most of the performance gains.
 Dumps of kernel databases automatically support memory mapped I/O.
 
-Conversion of the transmit path involves changing message contruction to
+Conversion of the transmit path involves changing message construction to
 use memory from the TX ring instead of (usually) a buffer declared on the
 stack and setting up the frame header approriately. Optionally poll() can
 be used to wait for free frames in the TX ring.
@@ -65,8 +65,8 @@ Structured and definitions for using memory mapped I/O are contained in
 RX and TX rings
 ----------------
 
-Each ring contains a number of continous memory blocks, containing frames of
-fixed size dependant on the parameters used for ring setup.
+Each ring contains a number of continuous memory blocks, containing frames of
+fixed size dependent on the parameters used for ring setup.
 
 Ring:  [ block 0 ]
                [ frame 0 ]
@@ -80,7 +80,7 @@ Ring: [ block 0 ]
                [ frame 2 * n + 1 ]
 
 The blocks are only visible to the kernel, from the point of view of user-space
-the ring just contains the frames in a continous memory zone.
+the ring just contains the frames in a continuous memory zone.
 
 The ring parameters used for setting up the ring are defined as follows:
 
@@ -91,7 +91,7 @@ struct nl_mmap_req {
        unsigned int    nm_frame_nr;
 };
 
-Frames are grouped into blocks, where each block is a continous region of memory
+Frames are grouped into blocks, where each block is a continuous region of memory
 and holds nm_block_size / nm_frame_size frames. The total number of frames in
 the ring is nm_frame_nr. The following invariants hold:
 
@@ -113,8 +113,8 @@ Some parameters are constrained, specifically:
 
 - nm_frame_nr must equal the actual number of frames as specified above.
 
-When the kernel can't allocate phsyically continous memory for a ring block,
-it will fall back to use physically discontinous memory. This might affect
+When the kernel can't allocate phsyically continuous memory for a ring block,
+it will fall back to use physically discontinuous memory. This might affect
 performance negatively, in order to avoid this the nm_frame_size parameter
 should be chosen to be as small as possible for the required frame size and
 the number of blocks should be increased instead.
index 579994afbe067bf9bf6d79bf50c62986dda2765d..ca6977f5b2ed066f49823c0d7c0129a9a16b0820 100644 (file)
@@ -163,6 +163,64 @@ and unnecessary. If there are fewer hardware queues than CPUs, then
 RPS might be beneficial if the rps_cpus for each queue are the ones that
 share the same memory domain as the interrupting CPU for that queue.
 
+==== RPS Flow Limit
+
+RPS scales kernel receive processing across CPUs without introducing
+reordering. The trade-off to sending all packets from the same flow
+to the same CPU is CPU load imbalance if flows vary in packet rate.
+In the extreme case a single flow dominates traffic. Especially on
+common server workloads with many concurrent connections, such
+behavior indicates a problem such as a misconfiguration or spoofed
+source Denial of Service attack.
+
+Flow Limit is an optional RPS feature that prioritizes small flows
+during CPU contention by dropping packets from large flows slightly
+ahead of those from small flows. It is active only when an RPS or RFS
+destination CPU approaches saturation.  Once a CPU's input packet
+queue exceeds half the maximum queue length (as set by sysctl
+net.core.netdev_max_backlog), the kernel starts a per-flow packet
+count over the last 256 packets. If a flow exceeds a set ratio (by
+default, half) of these packets when a new packet arrives, then the
+new packet is dropped. Packets from other flows are still only
+dropped once the input packet queue reaches netdev_max_backlog.
+No packets are dropped when the input packet queue length is below
+the threshold, so flow limit does not sever connections outright:
+even large flows maintain connectivity.
+
+== Interface
+
+Flow limit is compiled in by default (CONFIG_NET_FLOW_LIMIT), but not
+turned on. It is implemented for each CPU independently (to avoid lock
+and cache contention) and toggled per CPU by setting the relevant bit
+in sysctl net.core.flow_limit_cpu_bitmap. It exposes the same CPU
+bitmap interface as rps_cpus (see above) when called from procfs:
+
+ /proc/sys/net/core/flow_limit_cpu_bitmap
+
+Per-flow rate is calculated by hashing each packet into a hashtable
+bucket and incrementing a per-bucket counter. The hash function is
+the same that selects a CPU in RPS, but as the number of buckets can
+be much larger than the number of CPUs, flow limit has finer-grained
+identification of large flows and fewer false positives. The default
+table has 4096 buckets. This value can be modified through sysctl
+
+ net.core.flow_limit_table_len
+
+The value is only consulted when a new table is allocated. Modifying
+it does not update active tables.
+
+== Suggested Configuration
+
+Flow limit is useful on systems with many concurrent connections,
+where a single connection taking up 50% of a CPU indicates a problem.
+In such environments, enable the feature on all CPUs that handle
+network rx interrupts (as set in /proc/irq/N/smp_affinity).
+
+The feature depends on the input packet queue length to exceed
+the flow limit threshold (50%) + the flow history length (256).
+Setting net.core.netdev_max_backlog to either 1000 or 10000
+performed well in experiments.
+
 
 RFS: Receive Flow Steering
 ==========================
index 98335b7a533795607ccedcfb5d3975a45acba0fe..c1f8640c2fc8818519e5840e72be92edcc8c98eb 100644 (file)
@@ -93,8 +93,7 @@ netdev_budget
 
 Maximum number of packets taken from all interfaces in one polling cycle (NAPI
 poll). In one polling cycle interfaces which are registered to polling are
-probed in a round-robin manner. The limit of packets in one such probe can be
-set per-device via sysfs class/net/<device>/weight .
+probed in a round-robin manner.
 
 netdev_max_backlog
 ------------------
index 5302f79c05b719e3317bb0e3431c144073691724..4b5a8e065dcb60c577bcb138de40ab8141558f1c 100644 (file)
 
 &cpsw_emac0 {
        phy_id = <&davinci_mdio>, <0>;
+       phy-mode = "mii";
 };
 
 &cpsw_emac1 {
        phy_id = <&davinci_mdio>, <1>;
+       phy-mode = "mii";
 };
index 0423298a26fe634e174b4138cac7ee2ee28f6a2c..814ee037fd51fbb9a81774b2c4ba5e23fda6ae3a 100644 (file)
 
 &cpsw_emac0 {
        phy_id = <&davinci_mdio>, <0>;
+       phy-mode = "rgmii-txid";
 };
 
 &cpsw_emac1 {
        phy_id = <&davinci_mdio>, <1>;
+       phy-mode = "rgmii-txid";
 };
index f67c360844f482f20338c9b18b5ff0b76f2de542..4297899a24708a30e13e7cf5e24b99a591fb0eeb 100644 (file)
                };
        };
 };
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <0>;
+       phy-mode = "rgmii-txid";
+};
+
+&cpsw_emac1 {
+       phy_id = <&davinci_mdio>, <1>;
+       phy-mode = "rgmii-txid";
+};
index b70fe0db6bb7583cd541d25b7573a057caec130d..e752b570b4ecdf9c36f12b183137d9ce70271a05 100644 (file)
        };
 
        soc@01c20000 {
+               emac: ethernet@01c0b000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&emac_pins_a>;
+                       phy = <&phy1>;
+                       status = "okay";
+               };
+
+               mdio@01c0b080 {
+                       status = "okay";
+
+                       phy1: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+               };
+
                pinctrl@01c20800 {
                        led_pins_cubieboard: led_pins@0 {
                                allwinner,pins = "PH20", "PH21";
index b9efac100c85b2aac70c41a5bb4c9b8d83a11a11..3514b37d66bcd180df6e963a5d816e3446ef9379 100644 (file)
        };
 
        soc@01c20000 {
+               emac: ethernet@01c0b000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&emac_pins_a>;
+                       phy = <&phy0>;
+                       status = "okay";
+               };
+
+               mdio@01c0b080 {
+                       phy-supply = <&reg_emac_3v3>;
+                       status = "okay";
+
+                       phy0: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+               };
+
+               pio: pinctrl@01c20800 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&hackberry_hogs>;
+
+                       hackberry_hogs: hogs@0 {
+                               allwinner,pins = "PH19";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+               };
+
                uart0: serial@01c28000 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&uart0_pins_a>;
                        status = "okay";
                };
        };
+
+       regulators {
+               compatible = "simple-bus";
+
+               reg_emac_3v3: emac-3v3 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "emac-3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       enable-active-high;
+                       gpio = <&pio 7 19 0>;
+               };
+       };
 };
index e7ef619a70a2531440400086cdac4ee6ae3b71eb..983da33bebaaa0d2914629a01ef03922263de439 100644 (file)
                reg = <0x01c20000 0x300000>;
                ranges;
 
+               emac: ethernet@01c0b000 {
+                       compatible = "allwinner,sun4i-emac";
+                       reg = <0x01c0b000 0x1000>;
+                       interrupts = <55>;
+                       clocks = <&ahb_gates 17>;
+                       status = "disabled";
+               };
+
+               mdio@01c0b080 {
+                       compatible = "allwinner,sun4i-mdio";
+                       reg = <0x01c0b080 0x14>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
                intc: interrupt-controller@01c20400 {
                        compatible = "allwinner,sun4i-ic";
                        reg = <0x01c20400 0x400>;
                                allwinner,drive = <0>;
                                allwinner,pull = <0>;
                        };
+
+                       emac_pins_a: emac0@0 {
+                               allwinner,pins = "PA0", "PA1", "PA2",
+                                               "PA3", "PA4", "PA5", "PA6",
+                                               "PA7", "PA8", "PA9", "PA10",
+                                               "PA11", "PA12", "PA13", "PA14",
+                                               "PA15", "PA16";
+                               allwinner,function = "emac";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
                };
 
                timer@01c20c00 {
index abbe31937c65228e53dc2c97b4b2d4c14451ec38..769c0f039882c2d99661c41832b2738e82a1ccfd 100644 (file)
@@ -284,3 +284,4 @@ CONFIG_SOC_OMAP5=y
 CONFIG_TI_DAVINCI_MDIO=y
 CONFIG_TI_DAVINCI_CPDMA=y
 CONFIG_TI_CPSW=y
+CONFIG_AT803X_PHY=y
index ba44328464f37c0cdce9eb9039fcfce8ad8dc743..af8e109953d1214fc6413f7614eaa2aa13ecfdde 100644 (file)
@@ -111,7 +111,6 @@ config SOC_IMX25
        select ARCH_MXC_IOMUX_V3
        select COMMON_CLK
        select CPU_ARM926T
-       select HAVE_CAN_FLEXCAN if CAN
        select MXC_AVIC
 
 config SOC_IMX27
@@ -137,7 +136,6 @@ config SOC_IMX35
        select ARCH_MXC_IOMUX_V3
        select COMMON_CLK
        select CPU_V6K
-       select HAVE_CAN_FLEXCAN if CAN
        select HAVE_EPIT
        select MXC_AVIC
        select SMP_ON_UP if SMP
@@ -776,7 +774,6 @@ comment "Device tree only"
 
 config SOC_IMX53
        bool "i.MX53 support"
-       select HAVE_CAN_FLEXCAN if CAN
        select HAVE_IMX_SRC
        select IMX_HAVE_PLATFORM_IMX2_WDT
        select PINCTRL
@@ -799,7 +796,6 @@ config SOC_IMX6Q
        select CPU_V7
        select HAVE_ARM_SCU if SMP
        select HAVE_ARM_TWD if LOCAL_TIMERS
-       select HAVE_CAN_FLEXCAN if CAN
        select HAVE_IMX_ANATOP
        select HAVE_IMX_GPC
        select HAVE_IMX_MMDC
index 3dd2b1b041d15dc8d4eaf7e8880644c435660888..68c74fb0373c63a1f47b97630cf90f70b2e59ee1 100644 (file)
@@ -4,7 +4,6 @@ config IMX_HAVE_PLATFORM_FEC
 
 config IMX_HAVE_PLATFORM_FLEXCAN
        bool
-       select HAVE_CAN_FLEXCAN if CAN
 
 config IMX_HAVE_PLATFORM_FSL_USB2_UDC
        bool
index 4dc2fbba0ecd1bc511e3369a9916a263420b02f9..ce6e7d606a7ce9cc1867e0e83263e93610e8445d 100644 (file)
@@ -11,7 +11,6 @@ config SOC_IMX28
        select ARM_AMBA
        select ARM_CPU_SUSPEND if PM
        select CPU_ARM926T
-       select HAVE_CAN_FLEXCAN if CAN
        select HAVE_PWM
        select PINCTRL_IMX28
 
index 1a643ee8e082464108cf9280266fe73016b982be..f50d223a0bd31271ed73beabd60679c137ccb440 100644 (file)
@@ -900,8 +900,7 @@ void bpf_jit_compile(struct sk_filter *fp)
 #endif
 
        alloc_size = 4 * ctx.idx;
-       ctx.target = module_alloc(max(sizeof(struct work_struct),
-                                     alloc_size));
+       ctx.target = module_alloc(alloc_size);
        if (unlikely(ctx.target == NULL))
                goto out;
 
@@ -927,19 +926,8 @@ out:
        return;
 }
 
-static void bpf_jit_free_worker(struct work_struct *work)
-{
-       module_free(NULL, work);
-}
-
 void bpf_jit_free(struct sk_filter *fp)
 {
-       struct work_struct *work;
-
-       if (fp->bpf_func != sk_run_filter) {
-               work = (struct work_struct *)fp->bpf_func;
-
-               INIT_WORK(work, bpf_jit_free_worker);
-               schedule_work(work);
-       }
+       if (fp->bpf_func != sk_run_filter)
+               module_free(NULL, fp->bpf_func);
 }
index c13064e422df6a28a1e544848376436bf4b8b54a..d1b04c4c95e308061c1292d09f0e6642489abdd7 100644 (file)
@@ -268,7 +268,7 @@ static __inline__ int dev_is_ethdev(struct net_device *dev)
 static int
 simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct simeth_local *local;
        struct in_device *in_dev;
        struct in_ifaddr **ifap = NULL;
index 729a50991780f7e6aceb022012e4278993c5a6a7..b7eccbd17bf7e72d3ec78250ecc0bc80f606b504 100644 (file)
@@ -331,7 +331,8 @@ static int tx4939_netdev_event(struct notifier_block *this,
                               unsigned long event,
                               void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+
        if (event == NETDEV_CHANGE && netif_carrier_ok(dev)) {
                __u64 bit = 0;
                if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(0))
index c33e3ad2c8fd52c9e0c31dfc272faf3d34902f37..7754c6b8c453602d890c47d41f005798a6e8b62d 100644 (file)
@@ -674,7 +674,6 @@ config SBUS
 
 config FSL_SOC
        bool
-       select HAVE_CAN_FLEXCAN if NET && CAN
 
 config FSL_PCI
        bool
index c427ae36374ab4fa6eb1503c15b07de2926006e6..bf56e33f8257f68717b241c98abefb2f925f2858 100644 (file)
@@ -650,8 +650,7 @@ void bpf_jit_compile(struct sk_filter *fp)
 
        proglen = cgctx.idx * 4;
        alloclen = proglen + FUNCTION_DESCR_SIZE;
-       image = module_alloc(max_t(unsigned int, alloclen,
-                                  sizeof(struct work_struct)));
+       image = module_alloc(alloclen);
        if (!image)
                goto out;
 
@@ -688,20 +687,8 @@ out:
        return;
 }
 
-static void jit_free_defer(struct work_struct *arg)
-{
-       module_free(NULL, arg);
-}
-
-/* run from softirq, we must use a work_struct to call
- * module_free() from process context
- */
 void bpf_jit_free(struct sk_filter *fp)
 {
-       if (fp->bpf_func != sk_run_filter) {
-               struct work_struct *work = (struct work_struct *)fp->bpf_func;
-
-               INIT_WORK(work, jit_free_defer);
-               schedule_work(work);
-       }
+       if (fp->bpf_func != sk_run_filter)
+               module_free(NULL, fp->bpf_func);
 }
index d36a85ebb5e027c38929c2a5a8f9e7be772984b9..9c7be59e6f5ad3ad360facd10c6a2c35fd3bde75 100644 (file)
@@ -785,9 +785,7 @@ cond_branch:                        f_offset = addrs[i + filter[i].jf];
                        break;
                }
                if (proglen == oldproglen) {
-                       image = module_alloc(max_t(unsigned int,
-                                                  proglen,
-                                                  sizeof(struct work_struct)));
+                       image = module_alloc(proglen);
                        if (!image)
                                goto out;
                }
@@ -806,20 +804,8 @@ out:
        return;
 }
 
-static void jit_free_defer(struct work_struct *arg)
-{
-       module_free(NULL, arg);
-}
-
-/* run from softirq, we must use a work_struct to call
- * module_free() from process context
- */
 void bpf_jit_free(struct sk_filter *fp)
 {
-       if (fp->bpf_func != sk_run_filter) {
-               struct work_struct *work = (struct work_struct *)fp->bpf_func;
-
-               INIT_WORK(work, jit_free_defer);
-               schedule_work(work);
-       }
+       if (fp->bpf_func != sk_run_filter)
+               module_free(NULL, fp->bpf_func);
 }
index f66b54086ce597562d72f03d5bbaacfb09622005..79c216aa0e2baaac3a65a43972161922489c4978 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/netdevice.h>
 #include <linux/filter.h>
 #include <linux/if_vlan.h>
+#include <linux/random.h>
 
 /*
  * Conventions :
@@ -144,6 +145,39 @@ static int pkt_type_offset(void)
        return -1;
 }
 
+struct bpf_binary_header {
+       unsigned int    pages;
+       /* Note : for security reasons, bpf code will follow a randomly
+        * sized amount of int3 instructions
+        */
+       u8              image[];
+};
+
+static struct bpf_binary_header *bpf_alloc_binary(unsigned int proglen,
+                                                 u8 **image_ptr)
+{
+       unsigned int sz, hole;
+       struct bpf_binary_header *header;
+
+       /* Most of BPF filters are really small,
+        * but if some of them fill a page, allow at least
+        * 128 extra bytes to insert a random section of int3
+        */
+       sz = round_up(proglen + sizeof(*header) + 128, PAGE_SIZE);
+       header = module_alloc(sz);
+       if (!header)
+               return NULL;
+
+       memset(header, 0xcc, sz); /* fill whole space with int3 instructions */
+
+       header->pages = sz / PAGE_SIZE;
+       hole = sz - (proglen + sizeof(*header));
+
+       /* insert a random number of int3 instructions before BPF code */
+       *image_ptr = &header->image[prandom_u32() % hole];
+       return header;
+}
+
 void bpf_jit_compile(struct sk_filter *fp)
 {
        u8 temp[64];
@@ -153,6 +187,7 @@ void bpf_jit_compile(struct sk_filter *fp)
        int t_offset, f_offset;
        u8 t_op, f_op, seen = 0, pass;
        u8 *image = NULL;
+       struct bpf_binary_header *header = NULL;
        u8 *func;
        int pc_ret0 = -1; /* bpf index of first RET #0 instruction (if any) */
        unsigned int cleanup_addr; /* epilogue code offset */
@@ -693,7 +728,7 @@ cond_branch:                        f_offset = addrs[i + filter[i].jf] - addrs[i];
                                if (unlikely(proglen + ilen > oldproglen)) {
                                        pr_err("bpb_jit_compile fatal error\n");
                                        kfree(addrs);
-                                       module_free(NULL, image);
+                                       module_free(NULL, header);
                                        return;
                                }
                                memcpy(image + proglen, temp, ilen);
@@ -717,10 +752,8 @@ cond_branch:                       f_offset = addrs[i + filter[i].jf] - addrs[i];
                        break;
                }
                if (proglen == oldproglen) {
-                       image = module_alloc(max_t(unsigned int,
-                                                  proglen,
-                                                  sizeof(struct work_struct)));
-                       if (!image)
+                       header = bpf_alloc_binary(proglen, &image);
+                       if (!header)
                                goto out;
                }
                oldproglen = proglen;
@@ -730,7 +763,8 @@ cond_branch:                        f_offset = addrs[i + filter[i].jf] - addrs[i];
                bpf_jit_dump(flen, proglen, pass, image);
 
        if (image) {
-               bpf_flush_icache(image, image + proglen);
+               bpf_flush_icache(header, image + proglen);
+               set_memory_ro((unsigned long)header, header->pages);
                fp->bpf_func = (void *)image;
        }
 out:
@@ -738,20 +772,13 @@ out:
        return;
 }
 
-static void jit_free_defer(struct work_struct *arg)
-{
-       module_free(NULL, arg);
-}
-
-/* run from softirq, we must use a work_struct to call
- * module_free() from process context
- */
 void bpf_jit_free(struct sk_filter *fp)
 {
        if (fp->bpf_func != sk_run_filter) {
-               struct work_struct *work = (struct work_struct *)fp->bpf_func;
+               unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
+               struct bpf_binary_header *header = (void *)addr;
 
-               INIT_WORK(work, jit_free_defer);
-               schedule_work(work);
+               set_memory_rw(addr, header->pages);
+               module_free(NULL, header);
        }
 }
index 71c2c71168028dbe6c8cfe6b3de314cc344d84cd..34fbc2f60a09debc72652b4e8ab8dcef0d09dbe7 100644 (file)
@@ -3269,9 +3269,9 @@ static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id
 }
 
 static int cma_netdev_callback(struct notifier_block *self, unsigned long event,
-                              void *ctx)
+                              void *ptr)
 {
-       struct net_device *ndev = (struct net_device *)ctx;
+       struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
        struct cma_device *cma_dev;
        struct rdma_id_private *id_priv;
        int ret = NOTIFY_DONE;
index 23d734349d8e45e31bb81776f59757687e1e135c..a188d31785590e9cf59c7f3bf77926a11817e4b7 100644 (file)
@@ -1161,7 +1161,7 @@ static void netdev_removed(struct mlx4_ib_dev *dev, int port)
 static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event,
                                void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct mlx4_ib_dev *ibdev;
        struct net_device *oldnd;
        struct mlx4_ib_iboe *iboe;
index 88d657dff47454a3c374469db0ac51d03c53e502..8b98d53d99764be297362969fc1c88d1865639ec 100644 (file)
@@ -885,7 +885,7 @@ isdn_net_log_skb(struct sk_buff *skb, isdn_net_local *lp)
 
        addinfo[0] = '\0';
        /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
-       if (p < skb->data || skb->network_header >= skb->tail) {
+       if (p < skb->data || skb_network_header(skb) >= skb_tail_pointer(skb)) {
                /* fall back to old isdn_net_log_packet method() */
                char *buf = skb->data;
 
index e02cc265723abbaf397abbf84b0751d817dc5efd..a236234d2c2702894e41974d90d7d2351e023ff4 100644 (file)
@@ -1056,7 +1056,7 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[])
  *
  */
 
-static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct slave *slave2)
+static void alb_swap_mac_addr(struct slave *slave1, struct slave *slave2)
 {
        u8 tmp_mac_addr[ETH_ALEN];
 
@@ -1149,7 +1149,7 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
 
                if (found) {
                        /* locking: needs RTNL and nothing else */
-                       alb_swap_mac_addr(bond, slave, tmp_slave);
+                       alb_swap_mac_addr(slave, tmp_slave);
                        alb_fasten_mac_swap(bond, slave, tmp_slave);
                }
        }
@@ -1750,7 +1750,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
        /* curr_active_slave must be set before calling alb_swap_mac_addr */
        if (swap_slave) {
                /* swap mac address */
-               alb_swap_mac_addr(bond, swap_slave, new_slave);
+               alb_swap_mac_addr(swap_slave, new_slave);
        } else {
                /* set the new_slave to the bond mac address */
                alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
@@ -1810,7 +1810,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
        }
 
        if (swap_slave) {
-               alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
+               alb_swap_mac_addr(swap_slave, bond->curr_active_slave);
                alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
        } else {
                alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
index 29b846cbfb48d3380fa8dae7e87782e641e2519b..f4489d65bf338b3915be7da7e05eef5d6c81ba88 100644 (file)
@@ -3277,7 +3277,7 @@ static int bond_slave_netdev_event(unsigned long event,
 static int bond_netdev_event(struct notifier_block *this,
                             unsigned long event, void *ptr)
 {
-       struct net_device *event_dev = (struct net_device *)ptr;
+       struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
 
        pr_debug("event_dev: %s, event: %lx\n",
                 event_dev ? event_dev->name : "None",
index d7434e0a610e925e6a8b6de206856b37b4fd0375..f8bee4c0cbf10f9fa9d87a8115f907669b9322d4 100644 (file)
@@ -231,8 +231,7 @@ static ssize_t bonding_show_slaves(struct device *d,
 }
 
 /*
- * Set the slaves in the current bond.  The bond interface must be
- * up for this to succeed.
+ * Set the slaves in the current bond.
  * This is supposed to be only thin wrapper for bond_enslave and bond_release.
  * All hard work should be done there.
  */
@@ -363,7 +362,6 @@ static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
 
 /*
  * Show and set the bonding transmit hash method.
- * The bond interface must be down to change the xmit hash policy.
  */
 static ssize_t bonding_show_xmit_hash(struct device *d,
                                      struct device_attribute *attr,
@@ -383,20 +381,12 @@ static ssize_t bonding_store_xmit_hash(struct device *d,
        int new_value, ret = count;
        struct bonding *bond = to_bond(d);
 
-       if (bond->dev->flags & IFF_UP) {
-               pr_err("%s: Interface is up. Unable to update xmit policy.\n",
-                      bond->dev->name);
-               ret = -EPERM;
-               goto out;
-       }
-
        new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
        if (new_value < 0)  {
                pr_err("%s: Ignoring invalid xmit hash policy value %.*s.\n",
                       bond->dev->name,
                       (int)strlen(buf) - 1, buf);
                ret = -EINVAL;
-               goto out;
        } else {
                bond->params.xmit_policy = new_value;
                bond_set_mode_ops(bond, bond->params.mode);
@@ -404,7 +394,7 @@ static ssize_t bonding_store_xmit_hash(struct device *d,
                        bond->dev->name,
                        xmit_hashtype_tbl[new_value].modename, new_value);
        }
-out:
+
        return ret;
 }
 static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR,
index e456b70933c230abd7703ca3f6abed853679e5ef..3c069472eb8b6ddfc4f134209ccf92b51ac0ee84 100644 (file)
@@ -102,12 +102,9 @@ config CAN_JANZ_ICAN3
          This driver can also be built as a module. If so, the module will be
          called janz-ican3.ko.
 
-config HAVE_CAN_FLEXCAN
-       bool
-
 config CAN_FLEXCAN
        tristate "Support for Freescale FLEXCAN based chips"
-       depends on HAVE_CAN_FLEXCAN
+       depends on ARM || PPC
        ---help---
          Say Y here if you want to support for Freescale FlexCAN.
 
index db52f4414def171a4b76fffad88231589ddcc5c5..ce8421ac453a4d5a0252b1b0e6b4d87e6acb6f91 100644 (file)
@@ -1220,7 +1220,7 @@ static ssize_t at91_sysfs_set_mb0_id(struct device *dev,
                goto out;
        }
 
-       err = strict_strtoul(buf, 0, &can_id);
+       err = kstrtoul(buf, 0, &can_id);
        if (err) {
                ret = err;
                goto out;
@@ -1393,8 +1393,6 @@ static int at91_can_remove(struct platform_device *pdev)
 
        unregister_netdev(dev);
 
-       platform_set_drvdata(pdev, NULL);
-
        iounmap(priv->reg_base);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index d4a15e82bfc0954860999e5831a043ff53b07d9a..a2700d25ff0ed87fb800d4c157aeef911234d26e 100644 (file)
@@ -580,7 +580,7 @@ static int bfin_can_probe(struct platform_device *pdev)
        priv->pin_list = pdata;
        priv->can.clock.freq = get_sclk();
 
-       dev_set_drvdata(&pdev->dev, dev);
+       platform_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        dev->flags |= IFF_ECHO; /* we support local echo */
@@ -613,7 +613,7 @@ exit:
 
 static int bfin_can_remove(struct platform_device *pdev)
 {
-       struct net_device *dev = dev_get_drvdata(&pdev->dev);
+       struct net_device *dev = platform_get_drvdata(pdev);
        struct bfin_can_priv *priv = netdev_priv(dev);
        struct resource *res;
 
@@ -621,8 +621,6 @@ static int bfin_can_remove(struct platform_device *pdev)
 
        unregister_candev(dev);
 
-       dev_set_drvdata(&pdev->dev, NULL);
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, resource_size(res));
 
@@ -635,7 +633,7 @@ static int bfin_can_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
-       struct net_device *dev = dev_get_drvdata(&pdev->dev);
+       struct net_device *dev = platform_get_drvdata(pdev);
        struct bfin_can_priv *priv = netdev_priv(dev);
        struct bfin_can_regs __iomem *reg = priv->membase;
        int timeout = BFIN_CAN_TIMEOUT;
@@ -658,7 +656,7 @@ static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
 
 static int bfin_can_resume(struct platform_device *pdev)
 {
-       struct net_device *dev = dev_get_drvdata(&pdev->dev);
+       struct net_device *dev = platform_get_drvdata(pdev);
        struct bfin_can_priv *priv = netdev_priv(dev);
        struct bfin_can_regs __iomem *reg = priv->membase;
 
index d63b91904f829e9954596b06c0e34f48e3d1ba3b..6b6130b8bdc4c3d58489e1b920fc6d81c6ad0454 100644 (file)
@@ -234,7 +234,6 @@ static int c_can_plat_probe(struct platform_device *pdev)
        return 0;
 
 exit_free_device:
-       platform_set_drvdata(pdev, NULL);
        free_c_can_dev(dev);
 exit_iounmap:
        iounmap(addr);
@@ -255,7 +254,6 @@ static int c_can_plat_remove(struct platform_device *pdev)
        struct resource *mem;
 
        unregister_c_can_dev(dev);
-       platform_set_drvdata(pdev, NULL);
 
        free_c_can_dev(dev);
        iounmap(priv->base);
index 8eaaac81f320a70040c6af68f6acabec51316134..87a47c0cfd49185b1c5f9198a5945a3e9a51161a 100644 (file)
@@ -265,7 +265,7 @@ static int cc770_isa_probe(struct platform_device *pdev)
        else
                priv->clkout = COR_DEFAULT;
 
-       dev_set_drvdata(&pdev->dev, dev);
+       platform_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        err = register_cc770dev(dev);
@@ -293,12 +293,11 @@ static int cc770_isa_probe(struct platform_device *pdev)
 
 static int cc770_isa_remove(struct platform_device *pdev)
 {
-       struct net_device *dev = dev_get_drvdata(&pdev->dev);
+       struct net_device *dev = platform_get_drvdata(pdev);
        struct cc770_priv *priv = netdev_priv(dev);
        int idx = pdev->id;
 
        unregister_cc770dev(dev);
-       dev_set_drvdata(&pdev->dev, NULL);
 
        if (mem[idx]) {
                iounmap(priv->reg_base);
index d0f6bfc45aea1fae0a824f65cb431f847e2ae578..034bdd816a60c74104b00b5b203c69f120f0555d 100644 (file)
@@ -216,7 +216,7 @@ static int cc770_platform_probe(struct platform_device *pdev)
                 priv->reg_base, dev->irq, priv->can.clock.freq,
                 priv->cpu_interface, priv->bus_config, priv->clkout);
 
-       dev_set_drvdata(&pdev->dev, dev);
+       platform_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        err = register_cc770dev(dev);
@@ -240,7 +240,7 @@ exit_release_mem:
 
 static int cc770_platform_remove(struct platform_device *pdev)
 {
-       struct net_device *dev = dev_get_drvdata(&pdev->dev);
+       struct net_device *dev = platform_get_drvdata(pdev);
        struct cc770_priv *priv = netdev_priv(dev);
        struct resource *mem;
 
index 769d29ed106dbb1336745510b7fa2ff60f387bf7..f873b9f8d4d4b915411e7963394a52e37f67b47a 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
-#include <linux/pinctrl/consumer.h>
 
 #define DRV_NAME                       "flexcan"
 
@@ -1004,16 +1003,11 @@ static int flexcan_probe(struct platform_device *pdev)
        struct flexcan_priv *priv;
        struct resource *mem;
        struct clk *clk_ipg = NULL, *clk_per = NULL;
-       struct pinctrl *pinctrl;
        void __iomem *base;
        resource_size_t mem_size;
        int err, irq;
        u32 clock_freq = 0;
 
-       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-       if (IS_ERR(pinctrl))
-               return PTR_ERR(pinctrl);
-
        if (pdev->dev.of_node)
                of_property_read_u32(pdev->dev.of_node,
                                                "clock-frequency", &clock_freq);
@@ -1127,7 +1121,6 @@ static int flexcan_remove(struct platform_device *pdev)
        struct resource *mem;
 
        unregister_flexcandev(dev);
-       platform_set_drvdata(pdev, NULL);
        iounmap(priv->base);
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1138,10 +1131,10 @@ static int flexcan_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int flexcan_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int flexcan_suspend(struct device *device)
 {
-       struct net_device *dev = platform_get_drvdata(pdev);
+       struct net_device *dev = dev_get_drvdata(device);
        struct flexcan_priv *priv = netdev_priv(dev);
 
        flexcan_chip_disable(priv);
@@ -1155,9 +1148,9 @@ static int flexcan_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-static int flexcan_resume(struct platform_device *pdev)
+static int flexcan_resume(struct device *device)
 {
-       struct net_device *dev = platform_get_drvdata(pdev);
+       struct net_device *dev = dev_get_drvdata(device);
        struct flexcan_priv *priv = netdev_priv(dev);
 
        priv->can.state = CAN_STATE_ERROR_ACTIVE;
@@ -1169,21 +1162,19 @@ static int flexcan_resume(struct platform_device *pdev)
 
        return 0;
 }
-#else
-#define flexcan_suspend NULL
-#define flexcan_resume NULL
-#endif
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(flexcan_pm_ops, flexcan_suspend, flexcan_resume);
 
 static struct platform_driver flexcan_driver = {
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
+               .pm = &flexcan_pm_ops,
                .of_match_table = flexcan_of_match,
        },
        .probe = flexcan_probe,
        .remove = flexcan_remove,
-       .suspend = flexcan_suspend,
-       .resume = flexcan_resume,
        .id_table = flexcan_id_table,
 };
 
index 17fbc7a092247b556caf31c0c4adfa0a05b7f6b2..6aa737a243931f2db7f18842e6d5386ab4f812ae 100644 (file)
@@ -1646,7 +1646,7 @@ static int grcan_setup_netdev(struct platform_device *ofdev,
        if (err)
                goto exit_free_candev;
 
-       dev_set_drvdata(&ofdev->dev, dev);
+       platform_set_drvdata(ofdev, dev);
 
        /* Reset device to allow bit-timing to be set. No need to call
         * grcan_reset at this stage. That is done in grcan_open.
@@ -1683,10 +1683,9 @@ static int grcan_probe(struct platform_device *ofdev)
        }
 
        res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
-       base = devm_request_and_ioremap(&ofdev->dev, res);
-       if (!base) {
-               dev_err(&ofdev->dev, "couldn't map IO resource\n");
-               err = -EADDRNOTAVAIL;
+       base = devm_ioremap_resource(&ofdev->dev, res);
+       if (IS_ERR(base)) {
+               err = PTR_ERR(base);
                goto exit_error;
        }
 
@@ -1716,13 +1715,12 @@ exit_error:
 
 static int grcan_remove(struct platform_device *ofdev)
 {
-       struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+       struct net_device *dev = platform_get_drvdata(ofdev);
        struct grcan_priv *priv = netdev_priv(dev);
 
        unregister_candev(dev); /* Will in turn call grcan_close */
 
        irq_dispose_mapping(dev->irq);
-       dev_set_drvdata(&ofdev->dev, NULL);
        netif_napi_del(&priv->napi);
        free_candev(dev);
 
index c4bc1d2e2033214db1a20ff584d184f35d8635ec..36bd6fa1c7f3e4760b5f69f65b420f8d55b66a5f 100644 (file)
@@ -1734,7 +1734,7 @@ static ssize_t ican3_sysfs_set_term(struct device *dev,
        unsigned long enable;
        int ret;
 
-       if (strict_strtoul(buf, 0, &enable))
+       if (kstrtoul(buf, 0, &enable))
                return -EINVAL;
 
        ret = ican3_set_termination(mod, enable);
index f27fca65dc4a3590f99e3e55428326c19e937425..a3d99a8fd2d19ee46f846448d2707f8dadf3e4af 100644 (file)
@@ -88,9 +88,9 @@ EXPORT_SYMBOL_GPL(devm_can_led_init);
 
 /* NETDEV rename notifier to rename the associated led triggers too */
 static int can_led_notifier(struct notifier_block *nb, unsigned long msg,
-                       void *data)
+                           void *ptr)
 {
-       struct net_device *netdev = data;
+       struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
        struct can_priv *priv = safe_candev_priv(netdev);
        char name[CAN_LED_NAME_SZ];
 
index 668850e441dcd7e3c13e901efc2cc1e0f3473f53..5b0ee8ef5885e54a610030b9318445bae8aaf321 100644 (file)
@@ -302,7 +302,7 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
                goto exit_free_mscan;
        }
 
-       dev_set_drvdata(&ofdev->dev, dev);
+       platform_set_drvdata(ofdev, dev);
 
        dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
                 priv->reg_base, dev->irq, priv->can.clock.freq);
@@ -321,11 +321,9 @@ exit_unmap_mem:
 
 static int mpc5xxx_can_remove(struct platform_device *ofdev)
 {
-       struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+       struct net_device *dev = platform_get_drvdata(ofdev);
        struct mscan_priv *priv = netdev_priv(dev);
 
-       dev_set_drvdata(&ofdev->dev, NULL);
-
        unregister_mscandev(dev);
        iounmap(priv->reg_base);
        irq_dispose_mapping(dev->irq);
@@ -338,7 +336,7 @@ static int mpc5xxx_can_remove(struct platform_device *ofdev)
 static struct mscan_regs saved_regs;
 static int mpc5xxx_can_suspend(struct platform_device *ofdev, pm_message_t state)
 {
-       struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+       struct net_device *dev = platform_get_drvdata(ofdev);
        struct mscan_priv *priv = netdev_priv(dev);
        struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
 
@@ -349,7 +347,7 @@ static int mpc5xxx_can_suspend(struct platform_device *ofdev, pm_message_t state
 
 static int mpc5xxx_can_resume(struct platform_device *ofdev)
 {
-       struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+       struct net_device *dev = platform_get_drvdata(ofdev);
        struct mscan_priv *priv = netdev_priv(dev);
        struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
 
index 5c8da46614892504c1a30972f3199ffd7309b68a..06a282397fff076816818ba7c591ad78f528e7bf 100644 (file)
@@ -197,7 +197,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
        else
                priv->cdr = CDR_DEFAULT;
 
-       dev_set_drvdata(&pdev->dev, dev);
+       platform_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        err = register_sja1000dev(dev);
@@ -225,12 +225,11 @@ static int sja1000_isa_probe(struct platform_device *pdev)
 
 static int sja1000_isa_remove(struct platform_device *pdev)
 {
-       struct net_device *dev = dev_get_drvdata(&pdev->dev);
+       struct net_device *dev = platform_get_drvdata(pdev);
        struct sja1000_priv *priv = netdev_priv(dev);
        int idx = pdev->id;
 
        unregister_sja1000dev(dev);
-       dev_set_drvdata(&pdev->dev, NULL);
 
        if (mem[idx]) {
                iounmap(priv->reg_base);
index 8e0c4a0019397f61af74d44da1b60ca0c61032d2..31ad33911167058f06d1690ee62ca7b38e3eef1e 100644 (file)
@@ -72,13 +72,11 @@ static void sja1000_ofp_write_reg(const struct sja1000_priv *priv,
 
 static int sja1000_ofp_remove(struct platform_device *ofdev)
 {
-       struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+       struct net_device *dev = platform_get_drvdata(ofdev);
        struct sja1000_priv *priv = netdev_priv(dev);
        struct device_node *np = ofdev->dev.of_node;
        struct resource res;
 
-       dev_set_drvdata(&ofdev->dev, NULL);
-
        unregister_sja1000dev(dev);
        free_sja1000dev(dev);
        iounmap(priv->reg_base);
@@ -181,7 +179,7 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
                 priv->reg_base, dev->irq, priv->can.clock.freq,
                 priv->ocr, priv->cdr);
 
-       dev_set_drvdata(&ofdev->dev, dev);
+       platform_set_drvdata(ofdev, dev);
        SET_NETDEV_DEV(dev, &ofdev->dev);
 
        err = register_sja1000dev(dev);
index 21619bb5b869282a2d0a2f20090d93ea35908282..8e259c541036c575fc181796ebfe21f0c8798a1d 100644 (file)
@@ -135,7 +135,7 @@ static int sp_probe(struct platform_device *pdev)
                break;
        }
 
-       dev_set_drvdata(&pdev->dev, dev);
+       platform_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        err = register_sja1000dev(dev);
@@ -161,12 +161,11 @@ static int sp_probe(struct platform_device *pdev)
 
 static int sp_remove(struct platform_device *pdev)
 {
-       struct net_device *dev = dev_get_drvdata(&pdev->dev);
+       struct net_device *dev = platform_get_drvdata(pdev);
        struct sja1000_priv *priv = netdev_priv(dev);
        struct resource *res;
 
        unregister_sja1000dev(dev);
-       dev_set_drvdata(&pdev->dev, NULL);
 
        if (priv->reg_base)
                iounmap(priv->reg_base);
index 06b7e097d36e5ed3117e9d1dc8258ee74d51c6be..874188ba06f7172fed36b93db05be06ae0e2bd59 100644 (file)
@@ -161,7 +161,7 @@ static void slc_bump(struct slcan *sl)
 
        sl->rbuff[dlc_pos] = 0; /* terminate can_id string */
 
-       if (strict_strtoul(sl->rbuff+1, 16, &ultmp))
+       if (kstrtoul(sl->rbuff+1, 16, &ultmp))
                return;
 
        cf.can_id = ultmp;
index 3a2b45601ec29d69f07ec4dab98425ebb09add15..65eef1eea2e2434ca47cfeb086095a415d2b385e 100644 (file)
@@ -594,7 +594,7 @@ static ssize_t store_output(struct device *dev, struct device_attribute *attr,
        unsigned long val;
        int ret;
 
-       ret = strict_strtoul(buf, 0, &val);
+       ret = kstrtoul(buf, 0, &val);
        if (ret < 0)
                return ret;
        val &= 0xFF;
index f21fc37ec578d3926a09cda2706e2be610e593d8..3a349a22d5bc46eed31bdc32e12d27c25df3bd13 100644 (file)
@@ -1001,7 +1001,6 @@ static int ti_hecc_remove(struct platform_device *pdev)
        iounmap(priv->base);
        release_mem_region(res->start, resource_size(res));
        free_candev(ndev);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index adb4bf5eb4b4166dcdaa6c7883ef01fd3deb2afe..ede8daa68275dfdefc4976e6261e29a01e93e93a 100644 (file)
@@ -723,25 +723,6 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
                           dev->name, skb->len, inw(ioaddr + EL3_STATUS));
        }
-#if 0
-#ifndef final_version
-       {       /* Error-checking code, delete someday. */
-               ushort status = inw(ioaddr + EL3_STATUS);
-               if (status & 0x0001 &&          /* IRQ line active, missed one. */
-                   inw(ioaddr + EL3_STATUS) & 1) {                     /* Make sure. */
-                       pr_debug("%s: Missed interrupt, status then %04x now %04x"
-                                  "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
-                                  inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
-                                  inw(ioaddr + RX_STATUS));
-                       /* Fake interrupt trigger by masking, acknowledge interrupts. */
-                       outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
-                       outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
-                                ioaddr + EL3_CMD);
-                       outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
-               }
-       }
-#endif
-#endif
        /*
         *      We lock the driver against other processors. Note
         *      we don't need to lock versus the IRQ as we suspended
index 072c6f14e8fcea3c88f04d74d68afa73aef60554..30e74211a75537d7430d11dc3d12b00555fe68c3 100644 (file)
@@ -1473,7 +1473,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
 
        if (pdev) {
                vp->pm_state_valid = 1;
-               pci_save_state(VORTEX_PCI(vp));
+               pci_save_state(pdev);
                acpi_set_WOL(dev);
        }
        retval = register_netdev(dev);
@@ -3233,21 +3233,20 @@ static void vortex_remove_one(struct pci_dev *pdev)
        vp = netdev_priv(dev);
 
        if (vp->cb_fn_base)
-               pci_iounmap(VORTEX_PCI(vp), vp->cb_fn_base);
+               pci_iounmap(pdev, vp->cb_fn_base);
 
        unregister_netdev(dev);
 
-       if (VORTEX_PCI(vp)) {
-               pci_set_power_state(VORTEX_PCI(vp), PCI_D0);    /* Go active */
-               if (vp->pm_state_valid)
-                       pci_restore_state(VORTEX_PCI(vp));
-               pci_disable_device(VORTEX_PCI(vp));
-       }
+       pci_set_power_state(pdev, PCI_D0);      /* Go active */
+       if (vp->pm_state_valid)
+               pci_restore_state(pdev);
+       pci_disable_device(pdev);
+
        /* Should really use issue_and_wait() here */
        iowrite16(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14),
             vp->ioaddr + EL3_CMD);
 
-       pci_iounmap(VORTEX_PCI(vp), vp->ioaddr);
+       pci_iounmap(pdev, vp->ioaddr);
 
        pci_free_consistent(pdev,
                                                sizeof(struct boom_rx_desc) * RX_RING_SIZE
index 47618e505355ae91fc0ade4e50231ec780bcc56f..b2e8405137357f2cef6303c1a9a16d96b1abb23d 100644 (file)
@@ -849,7 +849,6 @@ static int ne_drv_remove(struct platform_device *pdev)
                free_irq(dev->irq, dev);
                release_region(dev->base_addr, NE_IO_EXTENT);
                free_netdev(dev);
-               platform_set_drvdata(pdev, NULL);
        }
        return 0;
 }
index ed956e08d38b1d835f233b4f1ba7698f75447c1b..18fd6fbeb109e42f644622c8838718ff201b476c 100644 (file)
@@ -20,6 +20,7 @@ config SUNGEM_PHY
 source "drivers/net/ethernet/3com/Kconfig"
 source "drivers/net/ethernet/adaptec/Kconfig"
 source "drivers/net/ethernet/aeroflex/Kconfig"
+source "drivers/net/ethernet/allwinner/Kconfig"
 source "drivers/net/ethernet/alteon/Kconfig"
 source "drivers/net/ethernet/amd/Kconfig"
 source "drivers/net/ethernet/apple/Kconfig"
index 8268d85f944849b904ca44b749d3b5eb72b6e363..009da27b6e268372ee210d8f2f33028d8d79bb54 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_NET_VENDOR_3COM) += 3com/
 obj-$(CONFIG_NET_VENDOR_8390) += 8390/
 obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
 obj-$(CONFIG_GRETH) += aeroflex/
+obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
 obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
 obj-$(CONFIG_NET_VENDOR_AMD) += amd/
 obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
index dada66bfe0d6e018778ba24939f15b82e9468b0d..e904b3838dccef44ace7fb126c32e9cd706597a9 100644 (file)
@@ -1719,7 +1719,6 @@ out_err_mii_probe:
        mdiobus_unregister(lp->mii_bus);
        mdiobus_free(lp->mii_bus);
 out_err_probe_mac:
-       platform_set_drvdata(pdev, NULL);
        free_netdev(ndev);
 
        return rc;
@@ -1732,8 +1731,6 @@ static int bfin_mac_remove(struct platform_device *pdev)
 
        bfin_phc_release(lp);
 
-       platform_set_drvdata(pdev, NULL);
-
        lp->mii_bus->priv = NULL;
 
        unregister_netdev(ndev);
@@ -1868,7 +1865,6 @@ static int bfin_mii_bus_remove(struct platform_device *pdev)
        struct bfin_mii_bus_platform_data *mii_bus_pd =
                dev_get_platdata(&pdev->dev);
 
-       platform_set_drvdata(pdev, NULL);
        mdiobus_unregister(miibus);
        kfree(miibus->irq);
        mdiobus_free(miibus);
index 269295403fc48959a35be1c65430e416fc385d0b..7ff4b30d55ea8bcbd5f9a1f2c18f99ffc88bcd2b 100644 (file)
@@ -1565,7 +1565,7 @@ error1:
 
 static int greth_of_remove(struct platform_device *of_dev)
 {
-       struct net_device *ndev = dev_get_drvdata(&of_dev->dev);
+       struct net_device *ndev = platform_get_drvdata(of_dev);
        struct greth_private *greth = netdev_priv(ndev);
 
        /* Free descriptor areas */
@@ -1573,8 +1573,6 @@ static int greth_of_remove(struct platform_device *of_dev)
 
        dma_free_coherent(&of_dev->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys);
 
-       dev_set_drvdata(&of_dev->dev, NULL);
-
        if (greth->phy)
                phy_stop(greth->phy);
        mdiobus_unregister(greth->mdio);
diff --git a/drivers/net/ethernet/allwinner/Kconfig b/drivers/net/ethernet/allwinner/Kconfig
new file mode 100644 (file)
index 0000000..66d3532
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# Allwinner device configuration
+#
+
+config NET_VENDOR_ALLWINNER
+       bool "Allwinner devices"
+       default y
+       depends on ARCH_SUNXI
+       ---help---
+         If you have a network (Ethernet) card belonging to this
+        class, say Y and read the Ethernet-HOWTO, available from
+        <http://www.tldp.org/docs.html#howto>.
+
+        Note that the answer to this question doesn't directly
+        affect the kernel: saying N will just cause the configurator
+        to skip all the questions about Allwinner cards. If you say Y,
+        you will be asked for your specific card in the following
+        questions.
+
+if NET_VENDOR_ALLWINNER
+
+config SUN4I_EMAC
+        tristate "Allwinner A10 EMAC support"
+       depends on ARCH_SUNXI
+       depends on OF
+       select CRC32
+       select NET_CORE
+       select MII
+       select PHYLIB
+        ---help---
+          Support for Allwinner A10 EMAC ethernet driver.
+
+          To compile this driver as a module, choose M here.  The module
+          will be called sun4i-emac.
+
+endif # NET_VENDOR_ALLWINNER
diff --git a/drivers/net/ethernet/allwinner/Makefile b/drivers/net/ethernet/allwinner/Makefile
new file mode 100644 (file)
index 0000000..03129f7
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Allwinner device drivers.
+#
+
+obj-$(CONFIG_SUN4I_EMAC) += sun4i-emac.o
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
new file mode 100644 (file)
index 0000000..50b853a
--- /dev/null
@@ -0,0 +1,954 @@
+/*
+ * Allwinner EMAC Fast Ethernet driver for Linux.
+ *
+ * Copyright 2012-2013 Stefan Roese <sr@denx.de>
+ * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * Based on the Linux driver provided by Allwinner:
+ * Copyright (C) 1997  Sten Wang
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+
+#include "sun4i-emac.h"
+
+#define DRV_NAME               "sun4i-emac"
+#define DRV_VERSION            "1.02"
+
+#define EMAC_MAX_FRAME_LEN     0x0600
+
+/* Transmit timeout, default 5 seconds. */
+static int watchdog = 5000;
+module_param(watchdog, int, 0400);
+MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+
+/* EMAC register address locking.
+ *
+ * The EMAC uses an address register to control where data written
+ * to the data register goes. This means that the address register
+ * must be preserved over interrupts or similar calls.
+ *
+ * During interrupt and other critical calls, a spinlock is used to
+ * protect the system, but the calls themselves save the address
+ * in the address register in case they are interrupting another
+ * access to the device.
+ *
+ * For general accesses a lock is provided so that calls which are
+ * allowed to sleep are serialised so that the address register does
+ * not need to be saved. This lock also serves to serialise access
+ * to the EEPROM and PHY access registers which are shared between
+ * these two devices.
+ */
+
+/* The driver supports the original EMACE, and now the two newer
+ * devices, EMACA and EMACB.
+ */
+
+struct emac_board_info {
+       struct clk              *clk;
+       struct device           *dev;
+       struct platform_device  *pdev;
+       spinlock_t              lock;
+       void __iomem            *membase;
+       u32                     msg_enable;
+       struct net_device       *ndev;
+       struct sk_buff          *skb_last;
+       u16                     tx_fifo_stat;
+
+       int                     emacrx_completed_flag;
+
+       struct phy_device       *phy_dev;
+       struct device_node      *phy_node;
+       unsigned int            link;
+       unsigned int            speed;
+       unsigned int            duplex;
+
+       phy_interface_t         phy_interface;
+};
+
+static void emac_update_speed(struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+       unsigned int reg_val;
+
+       /* set EMAC SPEED, depend on PHY  */
+       reg_val = readl(db->membase + EMAC_MAC_SUPP_REG);
+       reg_val &= ~(0x1 << 8);
+       if (db->speed == SPEED_100)
+               reg_val |= 1 << 8;
+       writel(reg_val, db->membase + EMAC_MAC_SUPP_REG);
+}
+
+static void emac_update_duplex(struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+       unsigned int reg_val;
+
+       /* set duplex depend on phy */
+       reg_val = readl(db->membase + EMAC_MAC_CTL1_REG);
+       reg_val &= ~EMAC_MAC_CTL1_DUPLEX_EN;
+       if (db->duplex)
+               reg_val |= EMAC_MAC_CTL1_DUPLEX_EN;
+       writel(reg_val, db->membase + EMAC_MAC_CTL1_REG);
+}
+
+static void emac_handle_link_change(struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+       struct phy_device *phydev = db->phy_dev;
+       unsigned long flags;
+       int status_change = 0;
+
+       if (phydev->link) {
+               if (db->speed != phydev->speed) {
+                       spin_lock_irqsave(&db->lock, flags);
+                       db->speed = phydev->speed;
+                       emac_update_speed(dev);
+                       spin_unlock_irqrestore(&db->lock, flags);
+                       status_change = 1;
+               }
+
+               if (db->duplex != phydev->duplex) {
+                       spin_lock_irqsave(&db->lock, flags);
+                       db->duplex = phydev->duplex;
+                       emac_update_duplex(dev);
+                       spin_unlock_irqrestore(&db->lock, flags);
+                       status_change = 1;
+               }
+       }
+
+       if (phydev->link != db->link) {
+               if (!phydev->link) {
+                       db->speed = 0;
+                       db->duplex = -1;
+               }
+               db->link = phydev->link;
+
+               status_change = 1;
+       }
+
+       if (status_change)
+               phy_print_status(phydev);
+}
+
+static int emac_mdio_probe(struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+
+       /* to-do: PHY interrupts are currently not supported */
+
+       /* attach the mac to the phy */
+       db->phy_dev = of_phy_connect(db->ndev, db->phy_node,
+                                    &emac_handle_link_change, 0,
+                                    db->phy_interface);
+       if (!db->phy_dev) {
+               netdev_err(db->ndev, "could not find the PHY\n");
+               return -ENODEV;
+       }
+
+       /* mask with MAC supported features */
+       db->phy_dev->supported &= PHY_BASIC_FEATURES;
+       db->phy_dev->advertising = db->phy_dev->supported;
+
+       db->link = 0;
+       db->speed = 0;
+       db->duplex = -1;
+
+       return 0;
+}
+
+static void emac_mdio_remove(struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+
+       phy_disconnect(db->phy_dev);
+       db->phy_dev = NULL;
+}
+
+static void emac_reset(struct emac_board_info *db)
+{
+       dev_dbg(db->dev, "resetting device\n");
+
+       /* RESET device */
+       writel(0, db->membase + EMAC_CTL_REG);
+       udelay(200);
+       writel(EMAC_CTL_RESET, db->membase + EMAC_CTL_REG);
+       udelay(200);
+}
+
+static void emac_outblk_32bit(void __iomem *reg, void *data, int count)
+{
+       writesl(reg, data, round_up(count, 4) / 4);
+}
+
+static void emac_inblk_32bit(void __iomem *reg, void *data, int count)
+{
+       readsl(reg, data, round_up(count, 4) / 4);
+}
+
+static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       struct emac_board_info *dm = netdev_priv(dev);
+       struct phy_device *phydev = dm->phy_dev;
+
+       if (!netif_running(dev))
+               return -EINVAL;
+
+       if (!phydev)
+               return -ENODEV;
+
+       return phy_mii_ioctl(phydev, rq, cmd);
+}
+
+/* ethtool ops */
+static void emac_get_drvinfo(struct net_device *dev,
+                             struct ethtool_drvinfo *info)
+{
+       strlcpy(info->driver, DRV_NAME, sizeof(DRV_NAME));
+       strlcpy(info->version, DRV_VERSION, sizeof(DRV_VERSION));
+       strlcpy(info->bus_info, dev_name(&dev->dev), sizeof(info->bus_info));
+}
+
+static int emac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct emac_board_info *dm = netdev_priv(dev);
+       struct phy_device *phydev = dm->phy_dev;
+
+       if (!phydev)
+               return -ENODEV;
+
+       return phy_ethtool_gset(phydev, cmd);
+}
+
+static int emac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct emac_board_info *dm = netdev_priv(dev);
+       struct phy_device *phydev = dm->phy_dev;
+
+       if (!phydev)
+               return -ENODEV;
+
+       return phy_ethtool_sset(phydev, cmd);
+}
+
+static const struct ethtool_ops emac_ethtool_ops = {
+       .get_drvinfo    = emac_get_drvinfo,
+       .get_settings   = emac_get_settings,
+       .set_settings   = emac_set_settings,
+       .get_link       = ethtool_op_get_link,
+};
+
+static unsigned int emac_setup(struct net_device *ndev)
+{
+       struct emac_board_info *db = netdev_priv(ndev);
+       unsigned int reg_val;
+
+       /* set up TX */
+       reg_val = readl(db->membase + EMAC_TX_MODE_REG);
+
+       writel(reg_val | EMAC_TX_MODE_ABORTED_FRAME_EN,
+               db->membase + EMAC_TX_MODE_REG);
+
+       /* set up RX */
+       reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+
+       writel(reg_val | EMAC_RX_CTL_PASS_LEN_OOR_EN |
+               EMAC_RX_CTL_ACCEPT_UNICAST_EN | EMAC_RX_CTL_DA_FILTER_EN |
+               EMAC_RX_CTL_ACCEPT_MULTICAST_EN |
+               EMAC_RX_CTL_ACCEPT_BROADCAST_EN,
+               db->membase + EMAC_RX_CTL_REG);
+
+       /* set MAC */
+       /* set MAC CTL0 */
+       reg_val = readl(db->membase + EMAC_MAC_CTL0_REG);
+       writel(reg_val | EMAC_MAC_CTL0_RX_FLOW_CTL_EN |
+               EMAC_MAC_CTL0_TX_FLOW_CTL_EN,
+               db->membase + EMAC_MAC_CTL0_REG);
+
+       /* set MAC CTL1 */
+       reg_val = readl(db->membase + EMAC_MAC_CTL1_REG);
+       reg_val |= EMAC_MAC_CTL1_LEN_CHECK_EN;
+       reg_val |= EMAC_MAC_CTL1_CRC_EN;
+       reg_val |= EMAC_MAC_CTL1_PAD_EN;
+       writel(reg_val, db->membase + EMAC_MAC_CTL1_REG);
+
+       /* set up IPGT */
+       writel(EMAC_MAC_IPGT_FULL_DUPLEX, db->membase + EMAC_MAC_IPGT_REG);
+
+       /* set up IPGR */
+       writel((EMAC_MAC_IPGR_IPG1 << 8) | EMAC_MAC_IPGR_IPG2,
+               db->membase + EMAC_MAC_IPGR_REG);
+
+       /* set up Collison window */
+       writel((EMAC_MAC_CLRT_COLLISION_WINDOW << 8) | EMAC_MAC_CLRT_RM,
+               db->membase + EMAC_MAC_CLRT_REG);
+
+       /* set up Max Frame Length */
+       writel(EMAC_MAX_FRAME_LEN,
+               db->membase + EMAC_MAC_MAXF_REG);
+
+       return 0;
+}
+
+static unsigned int emac_powerup(struct net_device *ndev)
+{
+       struct emac_board_info *db = netdev_priv(ndev);
+       unsigned int reg_val;
+
+       /* initial EMAC */
+       /* flush RX FIFO */
+       reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+       reg_val |= 0x8;
+       writel(reg_val, db->membase + EMAC_RX_CTL_REG);
+       udelay(1);
+
+       /* initial MAC */
+       /* soft reset MAC */
+       reg_val = readl(db->membase + EMAC_MAC_CTL0_REG);
+       reg_val &= ~EMAC_MAC_CTL0_SOFT_RESET;
+       writel(reg_val, db->membase + EMAC_MAC_CTL0_REG);
+
+       /* set MII clock */
+       reg_val = readl(db->membase + EMAC_MAC_MCFG_REG);
+       reg_val &= (~(0xf << 2));
+       reg_val |= (0xD << 2);
+       writel(reg_val, db->membase + EMAC_MAC_MCFG_REG);
+
+       /* clear RX counter */
+       writel(0x0, db->membase + EMAC_RX_FBC_REG);
+
+       /* disable all interrupt and clear interrupt status */
+       writel(0, db->membase + EMAC_INT_CTL_REG);
+       reg_val = readl(db->membase + EMAC_INT_STA_REG);
+       writel(reg_val, db->membase + EMAC_INT_STA_REG);
+
+       udelay(1);
+
+       /* set up EMAC */
+       emac_setup(ndev);
+
+       /* set mac_address to chip */
+       writel(ndev->dev_addr[0] << 16 | ndev->dev_addr[1] << 8 | ndev->
+              dev_addr[2], db->membase + EMAC_MAC_A1_REG);
+       writel(ndev->dev_addr[3] << 16 | ndev->dev_addr[4] << 8 | ndev->
+              dev_addr[5], db->membase + EMAC_MAC_A0_REG);
+
+       mdelay(1);
+
+       return 0;
+}
+
+static int emac_set_mac_address(struct net_device *dev, void *p)
+{
+       struct sockaddr *addr = p;
+       struct emac_board_info *db = netdev_priv(dev);
+
+       if (netif_running(dev))
+               return -EBUSY;
+
+       memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+
+       writel(dev->dev_addr[0] << 16 | dev->dev_addr[1] << 8 | dev->
+              dev_addr[2], db->membase + EMAC_MAC_A1_REG);
+       writel(dev->dev_addr[3] << 16 | dev->dev_addr[4] << 8 | dev->
+              dev_addr[5], db->membase + EMAC_MAC_A0_REG);
+
+       return 0;
+}
+
+/* Initialize emac board */
+static void emac_init_device(struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+       unsigned long flags;
+       unsigned int reg_val;
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       emac_update_speed(dev);
+       emac_update_duplex(dev);
+
+       /* enable RX/TX */
+       reg_val = readl(db->membase + EMAC_CTL_REG);
+       writel(reg_val | EMAC_CTL_RESET | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN,
+               db->membase + EMAC_CTL_REG);
+
+       /* enable RX/TX0/RX Hlevel interrup */
+       reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+       reg_val |= (0xf << 0) | (0x01 << 8);
+       writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+
+       spin_unlock_irqrestore(&db->lock, flags);
+}
+
+/* Our watchdog timed out. Called by the networking layer */
+static void emac_timeout(struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+       unsigned long flags;
+
+       if (netif_msg_timer(db))
+               dev_err(db->dev, "tx time out.\n");
+
+       /* Save previous register address */
+       spin_lock_irqsave(&db->lock, flags);
+
+       netif_stop_queue(dev);
+       emac_reset(db);
+       emac_init_device(dev);
+       /* We can accept TX packets again */
+       dev->trans_start = jiffies;
+       netif_wake_queue(dev);
+
+       /* Restore previous register address */
+       spin_unlock_irqrestore(&db->lock, flags);
+}
+
+/* Hardware start transmission.
+ * Send a packet to media from the upper layer.
+ */
+static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+       unsigned long channel;
+       unsigned long flags;
+
+       channel = db->tx_fifo_stat & 3;
+       if (channel == 3)
+               return 1;
+
+       channel = (channel == 1 ? 1 : 0);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       writel(channel, db->membase + EMAC_TX_INS_REG);
+
+       emac_outblk_32bit(db->membase + EMAC_TX_IO_DATA_REG,
+                       skb->data, skb->len);
+       dev->stats.tx_bytes += skb->len;
+
+       db->tx_fifo_stat |= 1 << channel;
+       /* TX control: First packet immediately send, second packet queue */
+       if (channel == 0) {
+               /* set TX len */
+               writel(skb->len, db->membase + EMAC_TX_PL0_REG);
+               /* start translate from fifo to phy */
+               writel(readl(db->membase + EMAC_TX_CTL0_REG) | 1,
+                      db->membase + EMAC_TX_CTL0_REG);
+
+               /* save the time stamp */
+               dev->trans_start = jiffies;
+       } else if (channel == 1) {
+               /* set TX len */
+               writel(skb->len, db->membase + EMAC_TX_PL1_REG);
+               /* start translate from fifo to phy */
+               writel(readl(db->membase + EMAC_TX_CTL1_REG) | 1,
+                      db->membase + EMAC_TX_CTL1_REG);
+
+               /* save the time stamp */
+               dev->trans_start = jiffies;
+       }
+
+       if ((db->tx_fifo_stat & 3) == 3) {
+               /* Second packet */
+               netif_stop_queue(dev);
+       }
+
+       spin_unlock_irqrestore(&db->lock, flags);
+
+       /* free this SKB */
+       dev_kfree_skb(skb);
+
+       return NETDEV_TX_OK;
+}
+
+/* EMAC interrupt handler
+ * receive the packet to upper layer, free the transmitted packet
+ */
+static void emac_tx_done(struct net_device *dev, struct emac_board_info *db,
+                         unsigned int tx_status)
+{
+       /* One packet sent complete */
+       db->tx_fifo_stat &= ~(tx_status & 3);
+       if (3 == (tx_status & 3))
+               dev->stats.tx_packets += 2;
+       else
+               dev->stats.tx_packets++;
+
+       if (netif_msg_tx_done(db))
+               dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
+
+       netif_wake_queue(dev);
+}
+
+/* Received a packet and pass to upper layer
+ */
+static void emac_rx(struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+       struct sk_buff *skb;
+       u8 *rdptr;
+       bool good_packet;
+       static int rxlen_last;
+       unsigned int reg_val;
+       u32 rxhdr, rxstatus, rxcount, rxlen;
+
+       /* Check packet ready or not */
+       while (1) {
+               /* race warning: the first packet might arrive with
+                * the interrupts disabled, but the second will fix
+                * it
+                */
+               rxcount = readl(db->membase + EMAC_RX_FBC_REG);
+
+               if (netif_msg_rx_status(db))
+                       dev_dbg(db->dev, "RXCount: %x\n", rxcount);
+
+               if ((db->skb_last != NULL) && (rxlen_last > 0)) {
+                       dev->stats.rx_bytes += rxlen_last;
+
+                       /* Pass to upper layer */
+                       db->skb_last->protocol = eth_type_trans(db->skb_last,
+                                                               dev);
+                       netif_rx(db->skb_last);
+                       dev->stats.rx_packets++;
+                       db->skb_last = NULL;
+                       rxlen_last = 0;
+
+                       reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+                       reg_val &= ~EMAC_RX_CTL_DMA_EN;
+                       writel(reg_val, db->membase + EMAC_RX_CTL_REG);
+               }
+
+               if (!rxcount) {
+                       db->emacrx_completed_flag = 1;
+                       reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+                       reg_val |= (0xf << 0) | (0x01 << 8);
+                       writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+
+                       /* had one stuck? */
+                       rxcount = readl(db->membase + EMAC_RX_FBC_REG);
+                       if (!rxcount)
+                               return;
+               }
+
+               reg_val = readl(db->membase + EMAC_RX_IO_DATA_REG);
+               if (netif_msg_rx_status(db))
+                       dev_dbg(db->dev, "receive header: %x\n", reg_val);
+               if (reg_val != EMAC_UNDOCUMENTED_MAGIC) {
+                       /* disable RX */
+                       reg_val = readl(db->membase + EMAC_CTL_REG);
+                       writel(reg_val & ~EMAC_CTL_RX_EN,
+                              db->membase + EMAC_CTL_REG);
+
+                       /* Flush RX FIFO */
+                       reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+                       writel(reg_val | (1 << 3),
+                              db->membase + EMAC_RX_CTL_REG);
+
+                       do {
+                               reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+                       } while (reg_val & (1 << 3));
+
+                       /* enable RX */
+                       reg_val = readl(db->membase + EMAC_CTL_REG);
+                       writel(reg_val | EMAC_CTL_RX_EN,
+                              db->membase + EMAC_CTL_REG);
+                       reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+                       reg_val |= (0xf << 0) | (0x01 << 8);
+                       writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+
+                       db->emacrx_completed_flag = 1;
+
+                       return;
+               }
+
+               /* A packet ready now  & Get status/length */
+               good_packet = true;
+
+               emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
+                               &rxhdr, sizeof(rxhdr));
+
+               if (netif_msg_rx_status(db))
+                       dev_dbg(db->dev, "rxhdr: %x\n", *((int *)(&rxhdr)));
+
+               rxlen = EMAC_RX_IO_DATA_LEN(rxhdr);
+               rxstatus = EMAC_RX_IO_DATA_STATUS(rxhdr);
+
+               if (netif_msg_rx_status(db))
+                       dev_dbg(db->dev, "RX: status %02x, length %04x\n",
+                               rxstatus, rxlen);
+
+               /* Packet Status check */
+               if (rxlen < 0x40) {
+                       good_packet = false;
+                       if (netif_msg_rx_err(db))
+                               dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
+               }
+
+               if (unlikely(!(rxstatus & EMAC_RX_IO_DATA_STATUS_OK))) {
+                       good_packet = false;
+
+                       if (rxstatus & EMAC_RX_IO_DATA_STATUS_CRC_ERR) {
+                               if (netif_msg_rx_err(db))
+                                       dev_dbg(db->dev, "crc error\n");
+                               dev->stats.rx_crc_errors++;
+                       }
+
+                       if (rxstatus & EMAC_RX_IO_DATA_STATUS_LEN_ERR) {
+                               if (netif_msg_rx_err(db))
+                                       dev_dbg(db->dev, "length error\n");
+                               dev->stats.rx_length_errors++;
+                       }
+               }
+
+               /* Move data from EMAC */
+               skb = dev_alloc_skb(rxlen + 4);
+               if (good_packet && skb) {
+                       skb_reserve(skb, 2);
+                       rdptr = (u8 *) skb_put(skb, rxlen - 4);
+
+                       /* Read received packet from RX SRAM */
+                       if (netif_msg_rx_status(db))
+                               dev_dbg(db->dev, "RxLen %x\n", rxlen);
+
+                       emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
+                                       rdptr, rxlen);
+                       dev->stats.rx_bytes += rxlen;
+
+                       /* Pass to upper layer */
+                       skb->protocol = eth_type_trans(skb, dev);
+                       netif_rx(skb);
+                       dev->stats.rx_packets++;
+               }
+       }
+}
+
+static irqreturn_t emac_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       struct emac_board_info *db = netdev_priv(dev);
+       int int_status;
+       unsigned long flags;
+       unsigned int reg_val;
+
+       /* A real interrupt coming */
+
+       /* holders of db->lock must always block IRQs */
+       spin_lock_irqsave(&db->lock, flags);
+
+       /* Disable all interrupts */
+       writel(0, db->membase + EMAC_INT_CTL_REG);
+
+       /* Got EMAC interrupt status */
+       /* Got ISR */
+       int_status = readl(db->membase + EMAC_INT_STA_REG);
+       /* Clear ISR status */
+       writel(int_status, db->membase + EMAC_INT_STA_REG);
+
+       if (netif_msg_intr(db))
+               dev_dbg(db->dev, "emac interrupt %02x\n", int_status);
+
+       /* Received the coming packet */
+       if ((int_status & 0x100) && (db->emacrx_completed_flag == 1)) {
+               /* carrier lost */
+               db->emacrx_completed_flag = 0;
+               emac_rx(dev);
+       }
+
+       /* Transmit Interrupt check */
+       if (int_status & (0x01 | 0x02))
+               emac_tx_done(dev, db, int_status);
+
+       if (int_status & (0x04 | 0x08))
+               netdev_info(dev, " ab : %x\n", int_status);
+
+       /* Re-enable interrupt mask */
+       if (db->emacrx_completed_flag == 1) {
+               reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+               reg_val |= (0xf << 0) | (0x01 << 8);
+               writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+       }
+       spin_unlock_irqrestore(&db->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Used by netconsole
+ */
+static void emac_poll_controller(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       emac_interrupt(dev->irq, dev);
+       enable_irq(dev->irq);
+}
+#endif
+
+/*  Open the interface.
+ *  The interface is opened whenever "ifconfig" actives it.
+ */
+static int emac_open(struct net_device *dev)
+{
+       struct emac_board_info *db = netdev_priv(dev);
+       int ret;
+
+       if (netif_msg_ifup(db))
+               dev_dbg(db->dev, "enabling %s\n", dev->name);
+
+       if (devm_request_irq(db->dev, dev->irq, &emac_interrupt,
+                            0, dev->name, dev))
+               return -EAGAIN;
+
+       /* Initialize EMAC board */
+       emac_reset(db);
+       emac_init_device(dev);
+
+       ret = emac_mdio_probe(dev);
+       if (ret < 0) {
+               netdev_err(dev, "cannot probe MDIO bus\n");
+               return ret;
+       }
+
+       phy_start(db->phy_dev);
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+static void emac_shutdown(struct net_device *dev)
+{
+       unsigned int reg_val;
+       struct emac_board_info *db = netdev_priv(dev);
+
+       /* Disable all interrupt */
+       writel(0, db->membase + EMAC_INT_CTL_REG);
+
+       /* clear interupt status */
+       reg_val = readl(db->membase + EMAC_INT_STA_REG);
+       writel(reg_val, db->membase + EMAC_INT_STA_REG);
+
+       /* Disable RX/TX */
+       reg_val = readl(db->membase + EMAC_CTL_REG);
+       reg_val &= ~(EMAC_CTL_TX_EN | EMAC_CTL_RX_EN | EMAC_CTL_RESET);
+       writel(reg_val, db->membase + EMAC_CTL_REG);
+}
+
+/* Stop the interface.
+ * The interface is stopped when it is brought.
+ */
+static int emac_stop(struct net_device *ndev)
+{
+       struct emac_board_info *db = netdev_priv(ndev);
+
+       if (netif_msg_ifdown(db))
+               dev_dbg(db->dev, "shutting down %s\n", ndev->name);
+
+       netif_stop_queue(ndev);
+       netif_carrier_off(ndev);
+
+       phy_stop(db->phy_dev);
+
+       emac_mdio_remove(ndev);
+
+       emac_shutdown(ndev);
+
+       return 0;
+}
+
+static const struct net_device_ops emac_netdev_ops = {
+       .ndo_open               = emac_open,
+       .ndo_stop               = emac_stop,
+       .ndo_start_xmit         = emac_start_xmit,
+       .ndo_tx_timeout         = emac_timeout,
+       .ndo_do_ioctl           = emac_ioctl,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = emac_set_mac_address,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = emac_poll_controller,
+#endif
+};
+
+/* Search EMAC board, allocate space and register it
+ */
+static int emac_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct emac_board_info *db;
+       struct net_device *ndev;
+       int ret = 0;
+       const char *mac_addr;
+
+       ndev = alloc_etherdev(sizeof(struct emac_board_info));
+       if (!ndev) {
+               dev_err(&pdev->dev, "could not allocate device.\n");
+               return -ENOMEM;
+       }
+
+       SET_NETDEV_DEV(ndev, &pdev->dev);
+
+       db = netdev_priv(ndev);
+       memset(db, 0, sizeof(*db));
+
+       db->dev = &pdev->dev;
+       db->ndev = ndev;
+       db->pdev = pdev;
+
+       spin_lock_init(&db->lock);
+
+       db->membase = of_iomap(np, 0);
+       if (!db->membase) {
+               dev_err(&pdev->dev, "failed to remap registers\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* fill in parameters for net-dev structure */
+       ndev->base_addr = (unsigned long)db->membase;
+       ndev->irq = irq_of_parse_and_map(np, 0);
+       if (ndev->irq == -ENXIO) {
+               netdev_err(ndev, "No irq resource\n");
+               ret = ndev->irq;
+               goto out;
+       }
+
+       db->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(db->clk))
+               goto out;
+
+       clk_prepare_enable(db->clk);
+
+       db->phy_node = of_parse_phandle(np, "phy", 0);
+       if (!db->phy_node) {
+               dev_err(&pdev->dev, "no associated PHY\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /* Read MAC-address from DT */
+       mac_addr = of_get_mac_address(np);
+       if (mac_addr)
+               memcpy(ndev->dev_addr, mac_addr, ETH_ALEN);
+
+       /* Check if the MAC address is valid, if not get a random one */
+       if (!is_valid_ether_addr(ndev->dev_addr)) {
+               eth_hw_addr_random(ndev);
+               dev_warn(&pdev->dev, "using random MAC address %pM\n",
+                        ndev->dev_addr);
+       }
+
+       db->emacrx_completed_flag = 1;
+       emac_powerup(ndev);
+       emac_reset(db);
+
+       ether_setup(ndev);
+
+       ndev->netdev_ops = &emac_netdev_ops;
+       ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
+       ndev->ethtool_ops = &emac_ethtool_ops;
+
+       platform_set_drvdata(pdev, ndev);
+
+       /* Carrier starts down, phylib will bring it up */
+       netif_carrier_off(ndev);
+
+       ret = register_netdev(ndev);
+       if (ret) {
+               dev_err(&pdev->dev, "Registering netdev failed!\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       dev_info(&pdev->dev, "%s: at %p, IRQ %d MAC: %pM\n",
+                ndev->name, db->membase, ndev->irq, ndev->dev_addr);
+
+       return 0;
+
+out:
+       dev_err(db->dev, "not found (%d).\n", ret);
+
+       free_netdev(ndev);
+
+       return ret;
+}
+
+static int emac_remove(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+
+       unregister_netdev(ndev);
+       free_netdev(ndev);
+
+       dev_dbg(&pdev->dev, "released and freed device\n");
+       return 0;
+}
+
+static int emac_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct net_device *ndev = platform_get_drvdata(dev);
+
+       netif_carrier_off(ndev);
+       netif_device_detach(ndev);
+       emac_shutdown(ndev);
+
+       return 0;
+}
+
+static int emac_resume(struct platform_device *dev)
+{
+       struct net_device *ndev = platform_get_drvdata(dev);
+       struct emac_board_info *db = netdev_priv(ndev);
+
+       emac_reset(db);
+       emac_init_device(ndev);
+       netif_device_attach(ndev);
+
+       return 0;
+}
+
+static const struct of_device_id emac_of_match[] = {
+       {.compatible = "allwinner,sun4i-emac",},
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, emac_of_match);
+
+static struct platform_driver emac_driver = {
+       .driver = {
+               .name = "sun4i-emac",
+               .of_match_table = emac_of_match,
+       },
+       .probe = emac_probe,
+       .remove = emac_remove,
+       .suspend = emac_suspend,
+       .resume = emac_resume,
+};
+
+module_platform_driver(emac_driver);
+
+MODULE_AUTHOR("Stefan Roese <sr@denx.de>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A10 emac network driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.h b/drivers/net/ethernet/allwinner/sun4i-emac.h
new file mode 100644 (file)
index 0000000..38c72d9
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Allwinner EMAC Fast Ethernet driver for Linux.
+ *
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * Based on the Linux driver provided by Allwinner:
+ * Copyright (C) 1997  Sten Wang
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _SUN4I_EMAC_H_
+#define _SUN4I_EMAC_H_
+
+#define EMAC_CTL_REG           (0x00)
+#define EMAC_CTL_RESET                 (1 << 0)
+#define EMAC_CTL_TX_EN                 (1 << 1)
+#define EMAC_CTL_RX_EN                 (1 << 2)
+#define EMAC_TX_MODE_REG       (0x04)
+#define EMAC_TX_MODE_ABORTED_FRAME_EN  (1 << 0)
+#define EMAC_TX_MODE_DMA_EN            (1 << 1)
+#define EMAC_TX_FLOW_REG       (0x08)
+#define EMAC_TX_CTL0_REG       (0x0c)
+#define EMAC_TX_CTL1_REG       (0x10)
+#define EMAC_TX_INS_REG                (0x14)
+#define EMAC_TX_PL0_REG                (0x18)
+#define EMAC_TX_PL1_REG                (0x1c)
+#define EMAC_TX_STA_REG                (0x20)
+#define EMAC_TX_IO_DATA_REG    (0x24)
+#define EMAC_TX_IO_DATA1_REG   (0x28)
+#define EMAC_TX_TSVL0_REG      (0x2c)
+#define EMAC_TX_TSVH0_REG      (0x30)
+#define EMAC_TX_TSVL1_REG      (0x34)
+#define EMAC_TX_TSVH1_REG      (0x38)
+#define EMAC_RX_CTL_REG                (0x3c)
+#define EMAC_RX_CTL_AUTO_DRQ_EN                (1 << 1)
+#define EMAC_RX_CTL_DMA_EN             (1 << 2)
+#define EMAC_RX_CTL_PASS_ALL_EN                (1 << 4)
+#define EMAC_RX_CTL_PASS_CTL_EN                (1 << 5)
+#define EMAC_RX_CTL_PASS_CRC_ERR_EN    (1 << 6)
+#define EMAC_RX_CTL_PASS_LEN_ERR_EN    (1 << 7)
+#define EMAC_RX_CTL_PASS_LEN_OOR_EN    (1 << 8)
+#define EMAC_RX_CTL_ACCEPT_UNICAST_EN  (1 << 16)
+#define EMAC_RX_CTL_DA_FILTER_EN       (1 << 17)
+#define EMAC_RX_CTL_ACCEPT_MULTICAST_EN        (1 << 20)
+#define EMAC_RX_CTL_HASH_FILTER_EN     (1 << 21)
+#define EMAC_RX_CTL_ACCEPT_BROADCAST_EN        (1 << 22)
+#define EMAC_RX_CTL_SA_FILTER_EN       (1 << 24)
+#define EMAC_RX_CTL_SA_FILTER_INVERT_EN        (1 << 25)
+#define EMAC_RX_HASH0_REG      (0x40)
+#define EMAC_RX_HASH1_REG      (0x44)
+#define EMAC_RX_STA_REG                (0x48)
+#define EMAC_RX_IO_DATA_REG    (0x4c)
+#define EMAC_RX_IO_DATA_LEN(x)         (x & 0xffff)
+#define EMAC_RX_IO_DATA_STATUS(x)      ((x >> 16) & 0xffff)
+#define EMAC_RX_IO_DATA_STATUS_CRC_ERR (1 << 4)
+#define EMAC_RX_IO_DATA_STATUS_LEN_ERR (3 << 5)
+#define EMAC_RX_IO_DATA_STATUS_OK      (1 << 7)
+#define EMAC_RX_FBC_REG                (0x50)
+#define EMAC_INT_CTL_REG       (0x54)
+#define EMAC_INT_STA_REG       (0x58)
+#define EMAC_MAC_CTL0_REG      (0x5c)
+#define EMAC_MAC_CTL0_RX_FLOW_CTL_EN   (1 << 2)
+#define EMAC_MAC_CTL0_TX_FLOW_CTL_EN   (1 << 3)
+#define EMAC_MAC_CTL0_SOFT_RESET       (1 << 15)
+#define EMAC_MAC_CTL1_REG      (0x60)
+#define EMAC_MAC_CTL1_DUPLEX_EN                (1 << 0)
+#define EMAC_MAC_CTL1_LEN_CHECK_EN     (1 << 1)
+#define EMAC_MAC_CTL1_HUGE_FRAME_EN    (1 << 2)
+#define EMAC_MAC_CTL1_DELAYED_CRC_EN   (1 << 3)
+#define EMAC_MAC_CTL1_CRC_EN           (1 << 4)
+#define EMAC_MAC_CTL1_PAD_EN           (1 << 5)
+#define EMAC_MAC_CTL1_PAD_CRC_EN       (1 << 6)
+#define EMAC_MAC_CTL1_AD_SHORT_FRAME_EN        (1 << 7)
+#define EMAC_MAC_CTL1_BACKOFF_DIS      (1 << 12)
+#define EMAC_MAC_IPGT_REG      (0x64)
+#define EMAC_MAC_IPGT_HALF_DUPLEX      (0x12)
+#define EMAC_MAC_IPGT_FULL_DUPLEX      (0x15)
+#define EMAC_MAC_IPGR_REG      (0x68)
+#define EMAC_MAC_IPGR_IPG1             (0x0c)
+#define EMAC_MAC_IPGR_IPG2             (0x12)
+#define EMAC_MAC_CLRT_REG      (0x6c)
+#define EMAC_MAC_CLRT_COLLISION_WINDOW (0x37)
+#define EMAC_MAC_CLRT_RM               (0x0f)
+#define EMAC_MAC_MAXF_REG      (0x70)
+#define EMAC_MAC_SUPP_REG      (0x74)
+#define EMAC_MAC_TEST_REG      (0x78)
+#define EMAC_MAC_MCFG_REG      (0x7c)
+#define EMAC_MAC_A0_REG                (0x98)
+#define EMAC_MAC_A1_REG                (0x9c)
+#define EMAC_MAC_A2_REG                (0xa0)
+#define EMAC_SAFX_L_REG0       (0xa4)
+#define EMAC_SAFX_H_REG0       (0xa8)
+#define EMAC_SAFX_L_REG1       (0xac)
+#define EMAC_SAFX_H_REG1       (0xb0)
+#define EMAC_SAFX_L_REG2       (0xb4)
+#define EMAC_SAFX_H_REG2       (0xb8)
+#define EMAC_SAFX_L_REG3       (0xbc)
+#define EMAC_SAFX_H_REG3       (0xc0)
+
+#define EMAC_PHY_DUPLEX                (1 << 8)
+
+#define EMAC_EEPROM_MAGIC      (0x444d394b)
+#define EMAC_UNDOCUMENTED_MAGIC        (0x0143414d)
+#endif /* _SUN4I_EMAC_H_ */
index b7894f8af9d1969e31410b0ffb3784c774a88275..219be1bf3cfccd60db67ac0515f5e49c65def9e0 100644 (file)
@@ -702,19 +702,6 @@ static struct pci_driver acenic_pci_driver = {
        .remove         = acenic_remove_one,
 };
 
-static int __init acenic_init(void)
-{
-       return pci_register_driver(&acenic_pci_driver);
-}
-
-static void __exit acenic_exit(void)
-{
-       pci_unregister_driver(&acenic_pci_driver);
-}
-
-module_init(acenic_init);
-module_exit(acenic_exit);
-
 static void ace_free_descriptors(struct net_device *dev)
 {
        struct ace_private *ap = netdev_priv(dev);
@@ -3199,3 +3186,5 @@ static int read_eeprom_byte(struct net_device *dev, unsigned long offset)
               ap->name, offset);
        goto out;
 }
+
+module_pci_driver(acenic_pci_driver);
index 8e6b665a672686350f872565e4e071fad7c6caa9..bc71aec1159d4cd8bc0fb8ec620697fd04cc0e5a 100644 (file)
@@ -1981,15 +1981,4 @@ static struct pci_driver amd8111e_driver = {
        .resume         = amd8111e_resume
 };
 
-static int __init amd8111e_init(void)
-{
-       return pci_register_driver(&amd8111e_driver);
-}
-
-static void __exit amd8111e_cleanup(void)
-{
-       pci_unregister_driver(&amd8111e_driver);
-}
-
-module_init(amd8111e_init);
-module_exit(amd8111e_cleanup);
+module_pci_driver(amd8111e_driver);
index 688aede742c7d0068d061f377582253f52280d12..ceb45bc963a93d8ba9cb2c554ff2c002ec6c916c 100644 (file)
@@ -1301,8 +1301,6 @@ static int au1000_remove(struct platform_device *pdev)
        int i;
        struct resource *base, *macen;
 
-       platform_set_drvdata(pdev, NULL);
-
        unregister_netdev(dev);
        mdiobus_unregister(aup->mii_bus);
        mdiobus_free(aup->mii_bus);
index f47b780892e97f4a4e5ca186e08ee1679f4eee6c..ece56831a647a9e1d93cbdcab7fed2842b6cd549 100644 (file)
@@ -1470,7 +1470,7 @@ no_link_test:
                goto fail;
        }
 
-       dev_set_drvdata(&op->dev, lp);
+       platform_set_drvdata(op, lp);
 
        printk(KERN_INFO "%s: LANCE %pM\n",
               dev->name, dev->dev_addr);
@@ -1501,7 +1501,7 @@ static int sunlance_sbus_probe(struct platform_device *op)
 
 static int sunlance_sbus_remove(struct platform_device *op)
 {
-       struct lance_private *lp = dev_get_drvdata(&op->dev);
+       struct lance_private *lp = platform_get_drvdata(op);
        struct net_device *net_dev = lp->dev;
 
        unregister_netdev(net_dev);
@@ -1510,8 +1510,6 @@ static int sunlance_sbus_remove(struct platform_device *op)
 
        free_netdev(net_dev);
 
-       dev_set_drvdata(&op->dev, NULL);
-
        return 0;
 }
 
index f36bbd6d5085da5f5d2ba830b88c7e517e3f5f9e..714dcfe3a46929e7757011aaf01a15c517c129c3 100644 (file)
@@ -1030,14 +1030,12 @@ static void bmac_set_multicast(struct net_device *dev)
                rx_cfg |= RxPromiscEnable;
                bmwrite(dev, RXCFG, rx_cfg);
        } else {
-               u16 hash_table[4];
+               u16 hash_table[4] = { 0 };
 
                rx_cfg = bmread(dev, RXCFG);
                rx_cfg &= ~RxPromiscEnable;
                bmwrite(dev, RXCFG, rx_cfg);
 
-               for(i = 0; i < 4; i++) hash_table[i] = 0;
-
                netdev_for_each_mc_addr(ha, dev) {
                        crc = ether_crc_le(6, ha->addr);
                        crc >>= 26;
index 0ba900762b138d87a3547a0a6d810bcfb151429d..786a87483298ea400733b987da389144e297824b 100644 (file)
@@ -2755,27 +2755,4 @@ static struct pci_driver atl1c_driver = {
        .driver.pm = &atl1c_pm_ops,
 };
 
-/**
- * atl1c_init_module - Driver Registration Routine
- *
- * atl1c_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- */
-static int __init atl1c_init_module(void)
-{
-       return pci_register_driver(&atl1c_driver);
-}
-
-/**
- * atl1c_exit_module - Driver Exit Cleanup Routine
- *
- * atl1c_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit atl1c_exit_module(void)
-{
-       pci_unregister_driver(&atl1c_driver);
-}
-
-module_init(atl1c_init_module);
-module_exit(atl1c_exit_module);
+module_pci_driver(atl1c_driver);
index 0688bb82b442e9cd55d5ce6da9d1a9f064295403..895f5377ad1ba2ad7819d162b8f1395d974111d7 100644 (file)
@@ -2489,27 +2489,4 @@ static struct pci_driver atl1e_driver = {
        .err_handler = &atl1e_err_handler
 };
 
-/**
- * atl1e_init_module - Driver Registration Routine
- *
- * atl1e_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- */
-static int __init atl1e_init_module(void)
-{
-       return pci_register_driver(&atl1e_driver);
-}
-
-/**
- * atl1e_exit_module - Driver Exit Cleanup Routine
- *
- * atl1e_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit atl1e_exit_module(void)
-{
-       pci_unregister_driver(&atl1e_driver);
-}
-
-module_init(atl1e_init_module);
-module_exit(atl1e_exit_module);
+module_pci_driver(atl1e_driver);
index fa0915f3999b24c8d3d53d0efddad6ad7efb98d6..538211d6f7d9ad5fc806008a58d984750c91edcd 100644 (file)
@@ -3145,31 +3145,6 @@ static struct pci_driver atl1_driver = {
        .driver.pm = &atl1_pm_ops,
 };
 
-/**
- * atl1_exit_module - Driver Exit Cleanup Routine
- *
- * atl1_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit atl1_exit_module(void)
-{
-       pci_unregister_driver(&atl1_driver);
-}
-
-/**
- * atl1_init_module - Driver Registration Routine
- *
- * atl1_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- */
-static int __init atl1_init_module(void)
-{
-       return pci_register_driver(&atl1_driver);
-}
-
-module_init(atl1_init_module);
-module_exit(atl1_exit_module);
-
 struct atl1_stats {
        char stat_string[ETH_GSTRING_LEN];
        int sizeof_stat;
@@ -3705,3 +3680,5 @@ static const struct ethtool_ops atl1_ethtool_ops = {
        .get_ethtool_stats      = atl1_get_ethtool_stats,
        .get_sset_count         = atl1_get_sset_count,
 };
+
+module_pci_driver(atl1_driver);
index 0b3e23ec37f769dde56f47f475b262c5c101f35d..e46466cb3627ee1297b4b5b9cfa0e8fbe8fa2e60 100644 (file)
@@ -1847,7 +1847,6 @@ static int bcm_enet_remove(struct platform_device *pdev)
        clk_disable_unprepare(priv->mac_clk);
        clk_put(priv->mac_clk);
 
-       platform_set_drvdata(pdev, NULL);
        free_netdev(dev);
        return 0;
 }
index 5d204492c603a84fd94f03faf5fc1179abf61208..1a1b23eb13dccfb7e6ea65c5bed2a74d68233e93 100644 (file)
@@ -8764,18 +8764,4 @@ static struct pci_driver bnx2_pci_driver = {
        .err_handler    = &bnx2_err_handler,
 };
 
-static int __init bnx2_init(void)
-{
-       return pci_register_driver(&bnx2_pci_driver);
-}
-
-static void __exit bnx2_cleanup(void)
-{
-       pci_unregister_driver(&bnx2_pci_driver);
-}
-
-module_init(bnx2_init);
-module_exit(bnx2_cleanup);
-
-
-
+module_pci_driver(bnx2_pci_driver);
index 3dba2a70a00e41f6ab86de036b4a3a7d859fd105..f76597e5fa5537309b99f65793b33b938532ea10 100644 (file)
 #define BCM_DCBNL
 #endif
 
-
 #include "bnx2x_hsi.h"
 
 #include "../cnic_if.h"
 
-
 #define BNX2X_MIN_MSIX_VEC_CNT(bp)             ((bp)->min_msix_vec_cnt)
 
 #include <linux/mdio.h>
@@ -114,7 +112,6 @@ do {                                                                \
 #define BNX2X_ERROR(fmt, ...)                                  \
        pr_err("[%s:%d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
 
-
 /* before we have a dev->name use dev_info() */
 #define BNX2X_DEV_INFO(fmt, ...)                                \
 do {                                                            \
@@ -147,7 +144,6 @@ do {                                                \
 #define U64_HI(x)                      ((u32)(((u64)(x)) >> 32))
 #define HILO_U64(hi, lo)               ((((u64)(hi)) << 32) + (lo))
 
-
 #define REG_ADDR(bp, offset)           ((bp->regview) + (offset))
 
 #define REG_RD(bp, offset)             readl(REG_ADDR(bp, offset))
@@ -366,7 +362,7 @@ union db_prod {
 /*
  * Number of required  SGEs is the sum of two:
  * 1. Number of possible opened aggregations (next packet for
- *    these aggregations will probably consume SGE immidiatelly)
+ *    these aggregations will probably consume SGE immediately)
  * 2. Rest of BRB blocks divided by 2 (block will consume new SGE only
  *    after placement on BD for new TPA aggregation)
  *
@@ -387,7 +383,6 @@ union db_prod {
 #define BIT_VEC64_ELEM_SHIFT           6
 #define BIT_VEC64_ELEM_MASK            ((u64)BIT_VEC64_ELEM_SZ - 1)
 
-
 #define __BIT_VEC64_SET_BIT(el, bit) \
        do { \
                el = ((el) | ((u64)0x1 << (bit))); \
@@ -398,7 +393,6 @@ union db_prod {
                el = ((el) & (~((u64)0x1 << (bit)))); \
        } while (0)
 
-
 #define BIT_VEC64_SET_BIT(vec64, idx) \
        __BIT_VEC64_SET_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
                           (idx) & BIT_VEC64_ELEM_MASK)
@@ -419,8 +413,6 @@ union db_prod {
 
 /*******************************************************/
 
-
-
 /* Number of u64 elements in SGE mask array */
 #define RX_SGE_MASK_LEN                        (NUM_RX_SGE / BIT_VEC64_ELEM_SZ)
 #define RX_SGE_MASK_LEN_MASK           (RX_SGE_MASK_LEN - 1)
@@ -494,10 +486,10 @@ struct bnx2x_fastpath {
 
        struct napi_struct      napi;
        union host_hc_status_block      status_blk;
-       /* chip independed shortcuts into sb structure */
+       /* chip independent shortcuts into sb structure */
        __le16                  *sb_index_values;
        __le16                  *sb_running_index;
-       /* chip independed shortcut into rx_prods_offset memory */
+       /* chip independent shortcut into rx_prods_offset memory */
        u32                     ustorm_rx_prods_offset;
 
        u32                     rx_buf_size;
@@ -580,12 +572,10 @@ struct bnx2x_fastpath {
                                                txdata_ptr[FIRST_TX_COS_INDEX] \
                                                ->var)
 
-
 #define IS_ETH_FP(fp)          ((fp)->index < BNX2X_NUM_ETH_QUEUES((fp)->bp))
 #define IS_FCOE_FP(fp)         ((fp)->index == FCOE_IDX((fp)->bp))
 #define IS_FCOE_IDX(idx)       ((idx) == FCOE_IDX(bp))
 
-
 /* MC hsi */
 #define MAX_FETCH_BD           13      /* HW max BDs per packet */
 #define RX_COPY_THRESH         92
@@ -613,7 +603,7 @@ struct bnx2x_fastpath {
  * START_BD(splitted)  - includes unpaged data segment for GSO
  * PARSING_BD          - for TSO and CSUM data
  * PARSING_BD2         - for encapsulation data
- * Frag BDs            - decribes pages for frags
+ * Frag BDs            - describes pages for frags
  */
 #define BDS_PER_TX_PKT         4
 #define MAX_BDS_PER_TX_PKT     (MAX_SKB_FRAGS + BDS_PER_TX_PKT)
@@ -693,12 +683,10 @@ struct bnx2x_fastpath {
                                 FW_DROP_LEVEL(bp))
 #define RCQ_TH_HI(bp)          (RCQ_TH_LO(bp) + DROPLESS_FC_HEADROOM)
 
-
 /* This is needed for determining of last_max */
 #define SUB_S16(a, b)          (s16)((s16)(a) - (s16)(b))
 #define SUB_S32(a, b)          (s32)((s32)(a) - (s32)(b))
 
-
 #define BNX2X_SWCID_SHIFT      17
 #define BNX2X_SWCID_MASK       ((0x1 << BNX2X_SWCID_SHIFT) - 1)
 
@@ -723,7 +711,6 @@ struct bnx2x_fastpath {
                       DPM_TRIGER_TYPE); \
        } while (0)
 
-
 /* TX CSUM helpers */
 #define SKB_CS_OFF(skb)                (offsetof(struct tcphdr, check) - \
                                 skb->csum_offset)
@@ -766,7 +753,6 @@ struct bnx2x_fastpath {
 #define BNX2X_RX_SUM_FIX(cqe) \
        BNX2X_PRS_FLAG_OVERETH_IPV4(cqe->fast_path_cqe.pars_flags.flags)
 
-
 #define FP_USB_FUNC_OFF        \
                        offsetof(struct cstorm_status_block_u, func)
 #define FP_CSB_FUNC_OFF        \
@@ -900,14 +886,14 @@ struct bnx2x_common {
 #define CHIP_IS_E3A0(bp)               (CHIP_IS_E3(bp) && \
                                         (CHIP_REV(bp) == CHIP_REV_Ax))
 /* This define is used in two main places:
- * 1. In the early stages of nic_load, to know if to configrue Parser / Searcher
+ * 1. In the early stages of nic_load, to know if to configure Parser / Searcher
  * to nic-only mode or to offload mode. Offload mode is configured if either the
  * chip is E1x (where MIC_MODE register is not applicable), or if cnic already
  * registered for this port (which means that the user wants storage services).
  * 2. During cnic-related load, to know if offload mode is already configured in
- * the HW or needs to be configrued.
+ * the HW or needs to be configured.
  * Since the transition from nic-mode to offload-mode in HW causes traffic
- * coruption, nic-mode is configured only in ports on which storage services
+ * corruption, nic-mode is configured only in ports on which storage services
  * where never requested.
  */
 #define CONFIGURE_NIC_MODE(bp)         (!CHIP_IS_E1x(bp) && !CNIC_ENABLED(bp))
@@ -1008,14 +994,14 @@ extern struct workqueue_struct *bnx2x_wq;
  * If the maximum number of FP-SB available is X then:
  * a. If CNIC is supported it consumes 1 FP-SB thus the max number of
  *    regular L2 queues is Y=X-1
- * b. in MF mode the actual number of L2 queues is Y= (X-1/MF_factor)
+ * b. In MF mode the actual number of L2 queues is Y= (X-1/MF_factor)
  * c. If the FCoE L2 queue is supported the actual number of L2 queues
  *    is Y+1
  * d. The number of irqs (MSIX vectors) is either Y+1 (one extra for
  *    slow-path interrupts) or Y+2 if CNIC is supported (one additional
  *    FP interrupt context for the CNIC).
  * e. The number of HW context (CID count) is always X or X+1 if FCoE
- *    L2 queue is supported. the cid for the FCoE L2 queue is always X.
+ *    L2 queue is supported. The cid for the FCoE L2 queue is always X.
  */
 
 /* fast-path interrupt contexts E1x */
@@ -1068,7 +1054,6 @@ struct bnx2x_slowpath {
                struct eth_classify_rules_ramrod_data   e2;
        } mac_rdata;
 
-
        union {
                struct tstorm_eth_mac_filter_config     e1x;
                struct eth_filter_rules_ramrod_data     e2;
@@ -1119,7 +1104,6 @@ struct bnx2x_slowpath {
 #define bnx2x_sp_mapping(bp, var) \
                (bp->slowpath_mapping + offsetof(struct bnx2x_slowpath, var))
 
-
 /* attn group wiring */
 #define MAX_DYNAMIC_ATTN_GRPS          8
 
@@ -1225,7 +1209,6 @@ enum {
        BNX2X_SP_RTNL_HYPERVISOR_VLAN,
 };
 
-
 struct bnx2x_prev_path_list {
        struct list_head list;
        u8 bus;
@@ -1585,7 +1568,7 @@ struct bnx2x {
        struct mutex            cnic_mutex;
        struct bnx2x_vlan_mac_obj iscsi_l2_mac_obj;
 
-       /* Start index of the "special" (CNIC related) L2 cleints */
+       /* Start index of the "special" (CNIC related) L2 clients */
        u8                              cnic_base_cl_id;
 
        int                     dmae_ready;
@@ -1699,7 +1682,7 @@ struct bnx2x {
        /* operation indication for the sp_rtnl task */
        unsigned long                           sp_rtnl_state;
 
-       /* DCBX Negotation results */
+       /* DCBX Negotiation results */
        struct dcbx_features                    dcbx_local_feat;
        u32                                     dcbx_error;
 
@@ -1755,7 +1738,6 @@ extern int num_queues;
 #define FUNC_FLG_SPQ           0x0010
 #define FUNC_FLG_LEADING       0x0020  /* PF only */
 
-
 struct bnx2x_func_init_params {
        /* dma */
        dma_addr_t      fw_stat_map;    /* valid iff FUNC_FLG_STATS */
@@ -1853,9 +1835,6 @@ struct bnx2x_func_init_params {
 
 #define skip_queue(bp, idx)    (NO_FCOE(bp) && IS_FCOE_IDX(idx))
 
-
-
-
 /**
  * bnx2x_set_mac_one - configure a single MAC address
  *
@@ -1921,7 +1900,6 @@ u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
 void bnx2x_prep_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae,
                               u8 src_type, u8 dst_type);
 int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae);
-void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, int msglvl);
 
 /* FLR related routines */
 u32 bnx2x_flr_clnup_poll_count(struct bnx2x *bp);
@@ -1937,6 +1915,8 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 void bnx2x_update_coalesce(struct bnx2x *bp);
 int bnx2x_get_cur_phy_idx(struct bnx2x *bp);
 
+bool bnx2x_port_after_undi(struct bnx2x *bp);
+
 static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
                           int wait)
 {
@@ -1998,7 +1978,6 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
 #define UNLOAD_CLOSE                   1
 #define UNLOAD_RECOVERY                        2
 
-
 /* DMAE command defines */
 #define DMAE_TIMEOUT                   -1
 #define DMAE_PCI_ERROR                 -2      /* E2 and onward */
@@ -2062,7 +2041,8 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
 #define DMAE_LEN32_WR_MAX(bp)          (CHIP_IS_E1(bp) ? 0x400 : 0x2000)
 
 #define DMAE_COMP_VAL                  0x60d0d0ae /* E2 and on - upper bit
-                                                       indicates eror */
+                                                   * indicates error
+                                                   */
 
 #define MAX_DMAE_C_PER_PORT            8
 #define INIT_DMAE_C(bp)                        (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
@@ -2100,7 +2080,6 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
 #define SP_DESC_CNT            (BCM_PAGE_SIZE / sizeof(struct eth_spe))
 #define MAX_SP_DESC_CNT                        (SP_DESC_CNT - 1)
 
-
 #define BNX2X_BTR                      4
 #define MAX_SPQ_PENDING                        8
 
@@ -2137,6 +2116,8 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
 #define ATTN_HARD_WIRED_MASK           0xff00
 #define ATTENTION_ID                   4
 
+#define IS_MF_STORAGE_ONLY(bp) (IS_MF_STORAGE_SD(bp) || \
+                                IS_MF_FCOE_AFEX(bp))
 
 /* stuff added to make the code fit 80Col */
 
@@ -2338,4 +2319,9 @@ enum {
 
 #define NUM_MACS       8
 
+enum bnx2x_pci_bus_speed {
+       BNX2X_PCI_LINK_SPEED_2500 = 2500,
+       BNX2X_PCI_LINK_SPEED_5000 = 5000,
+       BNX2X_PCI_LINK_SPEED_8000 = 8000
+};
 #endif /* bnx2x.h */
index 638e55435b04f474ff841698cc46cc09f6da1a6f..4e42bdd7c5222bb84422605641a86c425444aedc 100644 (file)
@@ -124,7 +124,7 @@ static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta)
        int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp);
 
        /* Queue pointer cannot be re-set on an fp-basis, as moving pointer
-        * backward along the array could cause memory to be overriden
+        * backward along the array could cause memory to be overridden
         */
        for (cos = 1; cos < bp->max_cos; cos++) {
                for (i = 0; i < old_eth_num - delta; i++) {
@@ -165,7 +165,6 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
                         BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
 
-
        nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
 #ifdef BNX2X_STOP_ON_ERROR
        if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) {
@@ -259,7 +258,7 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata)
        smp_mb();
 
        if (unlikely(netif_tx_queue_stopped(txq))) {
-               /* Taking tx_lock() is needed to prevent reenabling the queue
+               /* Taking tx_lock() is needed to prevent re-enabling the queue
                 * while it's empty. This could have happen if rx_action() gets
                 * suspended in bnx2x_tx_int() after the condition before
                 * netif_tx_wake_queue(), while tx_action (bnx2x_start_xmit()):
@@ -572,7 +571,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                        return err;
                }
 
-               /* Unmap the page as we r going to pass it to the stack */
+               /* Unmap the page as we're going to pass it to the stack */
                dma_unmap_page(&bp->pdev->dev,
                               dma_unmap_addr(&old_rx_pg, mapping),
                               SGE_PAGES, DMA_FROM_DEVICE);
@@ -733,7 +732,6 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                        dev_kfree_skb_any(skb);
                }
 
-
                /* put new data in bin */
                rx_buf->data = new_data;
 
@@ -899,7 +897,6 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                                                cqe_fp);
 
                                goto next_rx;
-
                        }
                        queue = cqe->end_agg_cqe.queue_index;
                        tpa_info = &fp->tpa_info[queue];
@@ -1004,7 +1001,6 @@ reuse_rx:
                                               le16_to_cpu(cqe_fp->vlan_tag));
                napi_gro_receive(&fp->napi, skb);
 
-
 next_rx:
                rx_buf->data = NULL;
 
@@ -1118,7 +1114,7 @@ static void bnx2x_fill_report_data(struct bnx2x *bp,
 
        memset(data, 0, sizeof(*data));
 
-       /* Fill the report data: efective line speed */
+       /* Fill the report data: effective line speed */
        data->line_speed = line_speed;
 
        /* Link is down */
@@ -1161,7 +1157,7 @@ void bnx2x_link_report(struct bnx2x *bp)
  *
  * @bp:                driver handle
  *
- * None atomic inmlementation.
+ * None atomic implementation.
  * Should be called under the phy_lock.
  */
 void __bnx2x_link_report(struct bnx2x *bp)
@@ -1304,7 +1300,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
                   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
 
                if (!fp->disable_tpa) {
-                       /* Fill the per-aggregtion pool */
+                       /* Fill the per-aggregation pool */
                        for (i = 0; i < MAX_AGG_QS(bp); i++) {
                                struct bnx2x_agg_info *tpa_info =
                                        &fp->tpa_info[i];
@@ -1829,7 +1825,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
        }
 
        /* select a non-FCoE queue */
-       return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
+       return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
 }
 
 void bnx2x_set_num_queues(struct bnx2x *bp)
@@ -1862,7 +1858,7 @@ void bnx2x_set_num_queues(struct bnx2x *bp)
  *
  * If the actual number of Tx queues (for each CoS) is less than 16 then there
  * will be the holes at the end of each group of 16 ETh L2 indices (0..15,
- * 16..31,...) with indicies that are not coupled with any real Tx queue.
+ * 16..31,...) with indices that are not coupled with any real Tx queue.
  *
  * The proper configuration of skb->queue_mapping is handled by
  * bnx2x_select_queue() and __skb_tx_hash().
@@ -1924,7 +1920,7 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
                                  ETH_OVREHEAD +
                                  mtu +
                                  BNX2X_FW_RX_ALIGN_END;
-               /* Note : rx_buf_size doesnt take into account NET_SKB_PAD */
+               /* Note : rx_buf_size doesn't take into account NET_SKB_PAD */
                if (fp->rx_buf_size + NET_SKB_PAD <= PAGE_SIZE)
                        fp->rx_frag_size = fp->rx_buf_size + NET_SKB_PAD;
                else
@@ -1937,7 +1933,7 @@ static int bnx2x_init_rss_pf(struct bnx2x *bp)
        int i;
        u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
 
-       /* Prepare the initial contents fo the indirection table if RSS is
+       /* Prepare the initial contents for the indirection table if RSS is
         * enabled
         */
        for (i = 0; i < sizeof(bp->rss_conf_obj.ind_table); i++)
@@ -2015,7 +2011,7 @@ static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
 
 /*
  * Cleans the object that have internal lists without sending
- * ramrods. Should be run when interrutps are disabled.
+ * ramrods. Should be run when interrupts are disabled.
  */
 void bnx2x_squeeze_objects(struct bnx2x *bp)
 {
@@ -2166,10 +2162,10 @@ static int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
        bp->fw_stats_data_mapping = bp->fw_stats_mapping +
                bp->fw_stats_req_sz;
 
-       DP(BNX2X_MSG_SP, "statistics request base address set to %x %x",
+       DP(BNX2X_MSG_SP, "statistics request base address set to %x %x\n",
           U64_HI(bp->fw_stats_req_mapping),
           U64_LO(bp->fw_stats_req_mapping));
-       DP(BNX2X_MSG_SP, "statistics data base address set to %x %x",
+       DP(BNX2X_MSG_SP, "statistics data base address set to %x %x\n",
           U64_HI(bp->fw_stats_data_mapping),
           U64_LO(bp->fw_stats_data_mapping));
        return 0;
@@ -2183,6 +2179,8 @@ alloc_mem_err:
 /* send load request to mcp and analyze response */
 static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code)
 {
+       u32 param;
+
        /* init fw_seq */
        bp->fw_seq =
                (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
@@ -2195,9 +2193,13 @@ static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code)
                 DRV_PULSE_SEQ_MASK);
        BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
 
+       param = DRV_MSG_CODE_LOAD_REQ_WITH_LFA;
+
+       if (IS_MF_SD(bp) && bnx2x_port_after_undi(bp))
+               param |= DRV_MSG_CODE_LOAD_REQ_FORCE_LFA;
+
        /* load request */
-       (*load_code) = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ,
-                                       DRV_MSG_CODE_LOAD_REQ_WITH_LFA);
+       (*load_code) = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, param);
 
        /* if mcp fails to respond we must abort */
        if (!(*load_code)) {
@@ -2238,7 +2240,7 @@ 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",
+                       BNX2X_ERR("bnx2x with FW %x was already loaded which mismatches my %x FW. Aborting\n",
                                  loaded_fw, my_fw);
                        return -EBUSY;
                }
@@ -2316,10 +2318,10 @@ static void bnx2x_nic_load_afex_dcc(struct bnx2x *bp, int load_code)
 static void bnx2x_bz_fp(struct bnx2x *bp, int index)
 {
        struct bnx2x_fastpath *fp = &bp->fp[index];
-
        int cos;
        struct napi_struct orig_napi = fp->napi;
        struct bnx2x_agg_info *orig_tpa_info = fp->tpa_info;
+
        /* bzero bnx2x_fastpath contents */
        if (fp->tpa_info)
                memset(fp->tpa_info, 0, ETH_MAX_AGGREGATION_QUEUES_E1H_E2 *
@@ -2345,8 +2347,7 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
                        fp->txdata_ptr[cos] = &bp->bnx2x_txq[cos *
                                BNX2X_NUM_ETH_QUEUES(bp) + index];
 
-       /*
-        * set the tpa flag for each queue. The tpa flag determines the queue
+       /* set the tpa flag for each queue. The tpa flag determines the queue
         * minimal size so it must be set prior to queue memory allocation
         */
        fp->disable_tpa = !(bp->flags & TPA_ENABLE_FLAG ||
@@ -2429,7 +2430,6 @@ int bnx2x_load_cnic(struct bnx2x *bp)
        if (bp->state == BNX2X_STATE_OPEN)
                bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
 
-
        DP(NETIF_MSG_IFUP, "Ending successfully CNIC-related load\n");
 
        return 0;
@@ -2472,6 +2472,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 
        bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
 
+       /* zero the structure w/o any lock, before SP handler is initialized */
        memset(&bp->last_reported_link, 0, sizeof(bp->last_reported_link));
        __set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
                &bp->last_reported_link.link_report_flags);
@@ -2536,8 +2537,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        }
 
        /* configure multi cos mappings in kernel.
-        * this configuration may be overriden by a multi class queue discipline
-        * or by a dcbx negotiation result.
+        * this configuration may be overridden by a multi class queue
+        * discipline or by a dcbx negotiation result.
         */
        bnx2x_setup_tc(bp->dev, bp->max_cos);
 
@@ -2696,7 +2697,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        /* Start the Tx */
        switch (load_mode) {
        case LOAD_NORMAL:
-               /* Tx queue should be only reenabled */
+               /* Tx queue should be only re-enabled */
                netif_tx_wake_all_queues(bp->dev);
                break;
 
@@ -2841,7 +2842,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
        }
 
        /* Nothing to do during unload if previous bnx2x_nic_load()
-        * have not completed succesfully - all resourses are released.
+        * have not completed successfully - all resources are released.
         *
         * we can get here only after unsuccessful ndo_* callback, during which
         * dev->IFF_UP flag is still on.
@@ -2890,10 +2891,9 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
                /* Send the UNLOAD_REQUEST to the MCP */
                bnx2x_send_unload_req(bp, unload_mode);
 
-               /*
-                * Prevent transactions to host from the functions on the
+               /* Prevent transactions to host from the functions on the
                 * engine that doesn't reset global blocks in case of global
-                * attention once gloabl blocks are reset and gates are opened
+                * attention once global blocks are reset and gates are opened
                 * (the engine which leader will perform the recovery
                 * last).
                 */
@@ -2914,7 +2914,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
        }
 
        /*
-        * At this stage no more interrupts will arrive so we may safly clean
+        * At this stage no more interrupts will arrive so we may safely clean
         * the queueable objects here in case they failed to get cleaned so far.
         */
        if (IS_PF(bp))
@@ -2955,7 +2955,6 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
                        bnx2x_set_reset_global(bp);
        }
 
-
        /* The last driver must disable a "close the gate" if there is no
         * parity attention or "process kill" pending.
         */
@@ -3586,7 +3585,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        DP(NETIF_MSG_TX_QUEUED, "indices: txq %d, fp %d, txdata %d\n",
           txq_index, fp_index, txdata_index); */
 
-       /* enable this debug print to view the tranmission details
+       /* enable this debug print to view the transmission details
        DP(NETIF_MSG_TX_QUEUED,
           "transmitting packet cid %d fp index %d txdata_index %d tx_data ptr %p fp pointer %p\n",
           txdata->cid, fp_index, txdata_index, txdata, fp); */
@@ -3968,7 +3967,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
        /* setup tc must be called under rtnl lock */
        ASSERT_RTNL();
 
-       /* no traffic classes requested. aborting */
+       /* no traffic classes requested. Aborting */
        if (!num_tc) {
                netdev_reset_tc(dev);
                return 0;
@@ -3976,7 +3975,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
 
        /* requested to support too many traffic classes */
        if (num_tc > bp->max_cos) {
-               BNX2X_ERR("support for too many traffic classes requested: %d. max supported is %d\n",
+               BNX2X_ERR("support for too many traffic classes requested: %d. Max supported is %d\n",
                          num_tc, bp->max_cos);
                return -EINVAL;
        }
@@ -3995,8 +3994,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
                   prio, bp->prio_to_cos[prio]);
        }
 
-
-       /* Use this configuration to diffrentiate tc0 from other COSes
+       /* Use this configuration to differentiate tc0 from other COSes
           This can be used for ets or pfc, and save the effort of setting
           up a multio class queue disc or negotiating DCBX with a switch
        netdev_set_prio_tc_map(dev, 0, 0);
@@ -4472,7 +4470,6 @@ int bnx2x_alloc_mem_bp(struct bnx2x *bp)
 alloc_err:
        bnx2x_free_mem_bp(bp);
        return -ENOMEM;
-
 }
 
 int bnx2x_reload_if_running(struct net_device *dev)
@@ -4514,7 +4511,6 @@ int bnx2x_get_cur_phy_idx(struct bnx2x *bp)
        }
 
        return sel_phy_idx;
-
 }
 int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
 {
@@ -4602,6 +4598,7 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
 {
        struct bnx2x *bp = netdev_priv(dev);
        u32 flags = bp->flags;
+       u32 changes;
        bool bnx2x_reload = false;
 
        if (features & NETIF_F_LRO)
@@ -4626,10 +4623,16 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
                }
        }
 
-       if (flags ^ bp->flags) {
-               bp->flags = flags;
+       changes = flags ^ bp->flags;
+
+       /* if GRO is changed while LRO is enabled, don't force a reload */
+       if ((changes & GRO_ENABLE_FLAG) && (flags & TPA_ENABLE_FLAG))
+               changes &= ~GRO_ENABLE_FLAG;
+
+       if (changes)
                bnx2x_reload = true;
-       }
+
+       bp->flags = flags;
 
        if (bnx2x_reload) {
                if (bp->recovery_state == BNX2X_RECOVERY_DONE)
@@ -4724,7 +4727,6 @@ int bnx2x_resume(struct pci_dev *pdev)
        return rc;
 }
 
-
 void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
                              u32 cid)
 {
@@ -4742,7 +4744,6 @@ static void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
                                    u8 fw_sb_id, u8 sb_index,
                                    u8 ticks)
 {
-
        u32 addr = BAR_CSTRORM_INTMEM +
                   CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(fw_sb_id, sb_index);
        REG_WR8(bp, addr, ticks);
index 151675d66b0d4d1f5b80289bb8697c43c69fb301..650bb52155a84629659a34b5fa5e0759791acae7 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 
-
 #include "bnx2x.h"
 #include "bnx2x_sriov.h"
 
@@ -50,13 +49,15 @@ extern int int_mode;
                } \
        } while (0)
 
-#define BNX2X_PCI_ALLOC(x, y, size)                            \
-do {                                                           \
-       x = dma_alloc_coherent(&bp->pdev->dev, size, y,         \
-                              GFP_KERNEL | __GFP_ZERO);        \
-       if (x == NULL)                                          \
-               goto alloc_mem_err;                             \
-} while (0)
+#define BNX2X_PCI_ALLOC(x, y, size) \
+       do { \
+               x = dma_alloc_coherent(&bp->pdev->dev, size, y, \
+                                      GFP_KERNEL | __GFP_ZERO); \
+               if (x == NULL) \
+                       goto alloc_mem_err; \
+               DP(NETIF_MSG_HW, "BNX2X_PCI_ALLOC: Physical %Lx Virtual %p\n", \
+                  (unsigned long long)(*y), x); \
+       } while (0)
 
 #define BNX2X_ALLOC(x, size) \
        do { \
@@ -494,9 +495,6 @@ void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
 /* Error handling */
 void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
 
-/* validate currect fw is loaded */
-bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err);
-
 /* dev_close main block */
 int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link);
 
@@ -1171,7 +1169,6 @@ static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
 
 static inline u8 bnx2x_cnic_fw_sb_id(struct bnx2x *bp)
 {
-
        /* the 'first' id is allocated for the cnic */
        return bp->base_fw_ndsb;
 }
@@ -1181,7 +1178,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);
@@ -1334,8 +1330,8 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
        int fpp = SGE_PAGE_SIZE / (mtu - ETH_MAX_TPA_HEADER_SIZE);
 
        /*
-        * 1. number of frags should not grow above MAX_SKB_FRAGS
-        * 2. frag must fit the page
+        * 1. Number of frags should not grow above MAX_SKB_FRAGS
+        * 2. Frag must fit the page
         */
        return mtu <= SGE_PAGE_SIZE && (U_ETH_SGL_SIZE * fpp) <= MAX_SKB_FRAGS;
 }
index 4b077a7f16af11d1bc3e66bc544044d428a4d8ad..0c94df47e0e8ee46d273488413be3d56d9c29ef6 100644 (file)
@@ -253,7 +253,6 @@ static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
 
        memset(&pg_help_data, 0, sizeof(struct pg_help_data));
 
-
        if (GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR))
                DP(BNX2X_MSG_DCB, "DCBX_LOCAL_ETS_ERROR\n");
 
@@ -298,7 +297,6 @@ static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
 static void  bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
                                        struct dcbx_pfc_feature *pfc, u32 error)
 {
-
        if (GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR))
                DP(BNX2X_MSG_DCB, "DCBX_LOCAL_PFC_ERROR\n");
 
@@ -367,7 +365,6 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
        struct lldp_remote_mib *remote_mib ;
        struct lldp_local_mib  *local_mib;
 
-
        switch (read_mib_type) {
        case DCBX_READ_LOCAL_MIB:
                mib_size = sizeof(struct lldp_local_mib);
@@ -629,7 +626,6 @@ static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
        return 0;
 }
 
-
 #ifdef BCM_DCBNL
 static inline
 u8 bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry *ent)
@@ -691,7 +687,7 @@ static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp)
        }
 
        /* setup tc must be called under rtnl lock, but we can't take it here
-        * as we are handling an attetntion on a work queue which must be
+        * as we are handling an attention on a work queue which must be
         * flushed at some rtnl-locked contexts (e.g. if down)
         */
        if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
@@ -711,7 +707,7 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
                         */
                        bnx2x_dcbnl_update_applist(bp, true);
 
-                       /* Read rmeote mib if dcbx is in the FW */
+                       /* Read remote mib if dcbx is in the FW */
                        if (bnx2x_dcbx_read_shmem_remote_mib(bp))
                                return;
 #endif
@@ -742,7 +738,7 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
                        bnx2x_dcbx_update_tc_mapping(bp);
 
                        /*
-                        * allow other funtions to update their netdevices
+                        * allow other functions to update their netdevices
                         * accordingly
                         */
                        if (IS_MF(bp))
@@ -864,7 +860,7 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
                           i, DCBX_PRI_PG_GET(af->ets.pri_pg_tbl, i));
                }
 
-               /*For IEEE admin_recommendation_bw_precentage
+               /*For IEEE admin_recommendation_bw_percentage
                 *For IEEE admin_recommendation_ets_pg */
                af->pfc.pri_en_bitmap = (u8)dp->admin_pfc_bitmap;
                for (i = 0; i < DCBX_CONFIG_MAX_APP_PROTOCOL; i++) {
@@ -896,13 +892,11 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
                }
 
                af->app.default_pri = (u8)dp->admin_default_priority;
-
        }
 
        /* Write the data. */
        bnx2x_write_data(bp, (u32 *)&admin_mib, offset,
                         sizeof(struct lldp_admin_mib));
-
 }
 
 void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
@@ -1076,7 +1070,7 @@ static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
        bool pg_found  = false;
        u32 i, traf_type, add_traf_type, add_pg;
        u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
-       struct pg_entry_help_data *data = help_data->data; /*shotcut*/
+       struct pg_entry_help_data *data = help_data->data; /*shortcut*/
 
        /* Set to invalid */
        for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
@@ -1172,7 +1166,8 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
                                DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry));
                else
                        /* If we join a group and one is strict
-                        * than the bw rulls */
+                        * than the bw rules
+                        */
                        cos_data->data[entry].strict =
                                                BNX2X_DCBX_STRICT_COS_HIGHEST;
        }
@@ -1181,7 +1176,6 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
                BNX2X_ERR("dcbx error: Both groups must have priorities\n");
 }
 
-
 #ifndef POWER_OF_2
 #define POWER_OF_2(x)  ((0 != x) && (0 == (x & (x-1))))
 #endif
@@ -1284,7 +1278,7 @@ static void bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(struct bnx2x *bp,
                } else {
                        /* If there are only pauseable priorities or
                         * only non-pauseable,* the lower priorities go
-                        * to the first queue and the higherpriorities go
+                        * to the first queue and the higher priorities go
                         * to the second queue.
                         */
                        cos_data->data[0].pausable =
@@ -1484,7 +1478,7 @@ static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
                 * queue and one priority goes to the second queue.
                 *
                 * We will join this two cases:
-                * if one is BW limited it will go to the secoend queue
+                * if one is BW limited it will go to the second queue
                 * otherwise the last priority will get it
                 */
 
@@ -1504,7 +1498,8 @@ static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
                                    false == b_found_strict)
                                        /* last entry will be handled separately
                                         * If no priority is strict than last
-                                        * enty goes to last queue.*/
+                                        * entry goes to last queue.
+                                        */
                                        entry = 1;
                                cos_data->data[entry].pri_join_mask |=
                                                                pri_tested;
@@ -1516,7 +1511,8 @@ static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
                                b_found_strict = true;
                                cos_data->data[1].pri_join_mask |= pri_tested;
                                /* If we join a group and one is strict
-                                * than the bw rulls */
+                                * than the bw rules
+                                */
                                cos_data->data[1].strict =
                                        BNX2X_DCBX_STRICT_COS_HIGHEST;
                        }
@@ -1524,7 +1520,6 @@ static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
        }
 }
 
-
 static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x *bp,
                                       struct pg_help_data *help_data,
                                       struct dcbx_ets_feature *ets,
@@ -1533,7 +1528,6 @@ static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x *bp,
                                       u32 pri_join_mask,
                                       u8 num_of_dif_pri)
 {
-
        /* default E2 settings */
        cos_data->num_of_cos = DCBX_COS_MAX_NUM_E2;
 
@@ -1629,7 +1623,6 @@ static u8 bnx2x_dcbx_cee_fill_strict_pri(struct bnx2x *bp,
                                         u8 num_spread_of_entries,
                                         u8 strict_app_pris)
 {
-
        if (bnx2x_dcbx_spread_strict_pri(bp, cos_data, entry,
                                         num_spread_of_entries,
                                         strict_app_pris)) {
@@ -1848,7 +1841,7 @@ static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
 
 void bnx2x_dcbx_pmf_update(struct bnx2x *bp)
 {
-       /* if we need to syncronize DCBX result from prev PMF
+       /* if we need to synchronize DCBX result from prev PMF
         * read it from shmem and update bp and netdev accordingly
         */
        if (SHMEM2_HAS(bp, drv_flags) &&
@@ -1876,7 +1869,6 @@ void bnx2x_dcbx_pmf_update(struct bnx2x *bp)
                 * dcbx negotiation.
                 */
                bnx2x_dcbx_update_tc_mapping(bp);
-
        }
 }
 
@@ -1943,14 +1935,14 @@ static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
                return;
 
        /**
-        * bw_pct ingnored -    band-width percentage devision between user
+        * bw_pct ignored -     band-width percentage devision between user
         *                      priorities within the same group is not
         *                      standard and hence not supported
         *
-        * prio_type igonred -  priority levels within the same group are not
+        * prio_type ignored -  priority levels within the same group are not
         *                      standard and hence are not supported. According
         *                      to the standard pgid 15 is dedicated to strict
-        *                      prioirty traffic (on the port level).
+        *                      priority traffic (on the port level).
         *
         * up_map ignored
         */
@@ -1995,14 +1987,14 @@ static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device *netdev, int prio,
        DP(BNX2X_MSG_DCB, "prio = %d\n", prio);
 
        /**
-        * bw_pct ingnored -    band-width percentage devision between user
+        * bw_pct ignored -     band-width percentage devision between user
         *                      priorities within the same group is not
         *                      standard and hence not supported
         *
-        * prio_type igonred -  priority levels within the same group are not
+        * prio_type ignored -  priority levels within the same group are not
         *                      standard and hence are not supported. According
         *                      to the standard pgid 15 is dedicated to strict
-        *                      prioirty traffic (on the port level).
+        *                      priority traffic (on the port level).
         *
         * up_map ignored
         */
@@ -2389,7 +2381,7 @@ static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                default:
-                       BNX2X_ERR("Non valid featrue-ID\n");
+                       BNX2X_ERR("Non valid feature-ID\n");
                        rval = 1;
                        break;
                }
@@ -2430,7 +2422,7 @@ static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,
                                flags & DCB_FEATCFG_WILLING ? 1 : 0;
                        break;
                default:
-                       BNX2X_ERR("Non valid featrue-ID\n");
+                       BNX2X_ERR("Non valid feature-ID\n");
                        rval = 1;
                        break;
                }
index d153f44cf8f99540c3988a1dd76ca777c10d5fcd..125bd1b6586ffc1f96b5fc946a4ee5a4613ce5a4 100644 (file)
@@ -134,8 +134,6 @@ enum {
 #define PFC_BRB1_REG_HIGH_LLFC_LOW_THRESHOLD                   130
 #define PFC_BRB1_REG_HIGH_LLFC_HIGH_THRESHOLD                  170
 
-
-
 struct cos_entry_help_data {
        u32                     pri_join_mask;
        u32                     cos_bw;
@@ -170,7 +168,6 @@ struct cos_help_data {
                        (!(IS_DCBX_PFC_PRI_ONLY_NON_PAUSE((bp), (pg_pri)) || \
                         IS_DCBX_PFC_PRI_ONLY_PAUSE((bp), (pg_pri))))
 
-
 struct pg_entry_help_data {
        u8      num_of_dif_pri;
        u8      pg;
index bff5e33eaa1496bc6d9b93d58b2cfc4ef40fbbd6..12eb4baee9f642e444bbb162d038911776b4d852 100644 (file)
  * consent.
  */
 
-
-/* This struct holds a signature to ensure the dump returned from the driver
- * match the meta data file inserted to grc_dump.tcl
- * The signature is time stamp, diag version and grc_dump version
- */
-
 #ifndef BNX2X_DUMP_H
 #define BNX2X_DUMP_H
 
@@ -28,7 +22,6 @@
 #define DRV_DUMP_USTORM_WAITP_ADDRESS    0x338a80
 #define DRV_DUMP_CSTORM_WAITP_ADDRESS    0x238a80
 
-
 /* Possible Chips */
 #define DUMP_CHIP_E1 1
 #define DUMP_CHIP_E1H 2
index ce1a91618677c13e232f4b017485722857e35520..7c6faebb1838bbcea2277d70a6a63202addaf9f8 100644 (file)
@@ -320,7 +320,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
        speed = ethtool_cmd_speed(cmd);
 
-       /* If recieved a request for an unknown duplex, assume full*/
+       /* If received a request for an unknown duplex, assume full*/
        if (cmd->duplex == DUPLEX_UNKNOWN)
                cmd->duplex = DUPLEX_FULL;
 
@@ -733,7 +733,6 @@ static bool bnx2x_is_reg_in_chip(struct bnx2x *bp,
                return false;
 }
 
-
 static bool bnx2x_is_wreg_in_chip(struct bnx2x *bp,
        const struct wreg_addr *wreg_info)
 {
@@ -850,7 +849,7 @@ static int __bnx2x_get_preset_regs(struct bnx2x *bp, u32 *p, u32 preset)
 
        /* Paged registers are supported in E2 & E3 only */
        if (CHIP_IS_E2(bp) || CHIP_IS_E3(bp)) {
-               /* Read "paged" registes */
+               /* Read "paged" registers */
                bnx2x_read_pages_regs(bp, p, preset);
        }
 
@@ -1155,8 +1154,8 @@ static int bnx2x_get_eeprom_len(struct net_device *dev)
        return bp->common.flash_size;
 }
 
-/* Per pf misc lock must be aquired before the per port mcp lock. Otherwise, had
- * we done things the other way around, if two pfs from the same port would
+/* Per pf misc lock must be acquired before the per port mcp lock. Otherwise,
+ * had we done things the other way around, if two pfs from the same port would
  * attempt to access nvram at the same time, we could run into a scenario such
  * as:
  * pf A takes the port lock.
@@ -1381,12 +1380,29 @@ static int bnx2x_nvram_read32(struct bnx2x *bp, u32 offset, u32 *buf,
        return rc;
 }
 
+static bool bnx2x_is_nvm_accessible(struct bnx2x *bp)
+{
+       int rc = 1;
+       u16 pm = 0;
+       struct net_device *dev = pci_get_drvdata(bp->pdev);
+
+       if (bp->pm_cap)
+               rc = pci_read_config_word(bp->pdev,
+                                         bp->pm_cap + PCI_PM_CTRL, &pm);
+
+       if ((rc && !netif_running(dev)) ||
+           (!rc && ((pm & PCI_PM_CTRL_STATE_MASK) != PCI_D0)))
+               return false;
+
+       return true;
+}
+
 static int bnx2x_get_eeprom(struct net_device *dev,
                            struct ethtool_eeprom *eeprom, u8 *eebuf)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
-       if (!netif_running(dev)) {
+       if (!bnx2x_is_nvm_accessible(bp)) {
                DP(BNX2X_MSG_ETHTOOL  | BNX2X_MSG_NVM,
                   "cannot access eeprom when the interface is down\n");
                return -EAGAIN;
@@ -1411,7 +1427,7 @@ static int bnx2x_get_module_eeprom(struct net_device *dev,
        u8 *user_data = data;
        unsigned int start_addr = ee->offset, xfer_size = 0;
 
-       if (!netif_running(dev)) {
+       if (!bnx2x_is_nvm_accessible(bp)) {
                DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
                   "cannot access eeprom when the interface is down\n");
                return -EAGAIN;
@@ -1474,7 +1490,7 @@ static int bnx2x_get_module_info(struct net_device *dev,
        int phy_idx, rc;
        u8 sff8472_comp, diag_type;
 
-       if (!netif_running(dev)) {
+       if (!bnx2x_is_nvm_accessible(bp)) {
                DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
                   "cannot access eeprom when the interface is down\n");
                return -EAGAIN;
@@ -1676,7 +1692,8 @@ static int bnx2x_set_eeprom(struct net_device *dev,
        int port = BP_PORT(bp);
        int rc = 0;
        u32 ext_phy_config;
-       if (!netif_running(dev)) {
+
+       if (!bnx2x_is_nvm_accessible(bp)) {
                DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
                   "cannot access eeprom when the interface is down\n");
                return -EAGAIN;
@@ -1921,6 +1938,19 @@ static const char bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF][ETH_GSTRING_LEN] = {
        "link_test (online)         "
 };
 
+enum {
+       BNX2X_PRI_FLAG_ISCSI,
+       BNX2X_PRI_FLAG_FCOE,
+       BNX2X_PRI_FLAG_STORAGE,
+       BNX2X_PRI_FLAG_LEN,
+};
+
+static const char bnx2x_private_arr[BNX2X_PRI_FLAG_LEN][ETH_GSTRING_LEN] = {
+       "iSCSI offload support",
+       "FCoE offload support",
+       "Storage only interface"
+};
+
 static u32 bnx2x_eee_to_adv(u32 eee_adv)
 {
        u32 modes = 0;
@@ -2041,7 +2071,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata)
                                    EEE_MODE_OVERRIDE_NVRAM |
                                    EEE_MODE_OUTPUT_TIME;
 
-       /* Restart link to propogate changes */
+       /* Restart link to propagate changes */
        if (netif_running(dev)) {
                bnx2x_stats_handle(bp, STATS_EVENT_STOP);
                bnx2x_force_link_reset(bp);
@@ -2160,7 +2190,7 @@ static int bnx2x_test_registers(struct bnx2x *bp)
                { BNX2X_CHIP_MASK_ALL, 0xffffffff, 0, 0x00000000 }
        };
 
-       if (!netif_running(bp->dev)) {
+       if (!bnx2x_is_nvm_accessible(bp)) {
                DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
                   "cannot access eeprom when the interface is down\n");
                return rc;
@@ -2264,7 +2294,7 @@ static int bnx2x_test_memory(struct bnx2x *bp)
                { NULL, 0xffffffff, {0, 0, 0, 0} }
        };
 
-       if (!netif_running(bp->dev)) {
+       if (!bnx2x_is_nvm_accessible(bp)) {
                DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
                   "cannot access eeprom when the interface is down\n");
                return rc;
@@ -2978,32 +3008,47 @@ static int bnx2x_num_stat_queues(struct bnx2x *bp)
 static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       int i, num_stats;
+       int i, num_strings = 0;
 
        switch (stringset) {
        case ETH_SS_STATS:
                if (is_multi(bp)) {
-                       num_stats = bnx2x_num_stat_queues(bp) *
-                                               BNX2X_NUM_Q_STATS;
+                       num_strings = bnx2x_num_stat_queues(bp) *
+                                     BNX2X_NUM_Q_STATS;
                } else
-                       num_stats = 0;
+                       num_strings = 0;
                if (IS_MF_MODE_STAT(bp)) {
                        for (i = 0; i < BNX2X_NUM_STATS; i++)
                                if (IS_FUNC_STAT(i))
-                                       num_stats++;
+                                       num_strings++;
                } else
-                       num_stats += BNX2X_NUM_STATS;
+                       num_strings += BNX2X_NUM_STATS;
 
-               return num_stats;
+               return num_strings;
 
        case ETH_SS_TEST:
                return BNX2X_NUM_TESTS(bp);
 
+       case ETH_SS_PRIV_FLAGS:
+               return BNX2X_PRI_FLAG_LEN;
+
        default:
                return -EINVAL;
        }
 }
 
+static u32 bnx2x_get_private_flags(struct net_device *dev)
+{
+       struct bnx2x *bp = netdev_priv(dev);
+       u32 flags = 0;
+
+       flags |= (!(bp->flags & NO_ISCSI_FLAG) ? 1 : 0) << BNX2X_PRI_FLAG_ISCSI;
+       flags |= (!(bp->flags & NO_FCOE_FLAG)  ? 1 : 0) << BNX2X_PRI_FLAG_FCOE;
+       flags |= (!!IS_MF_STORAGE_ONLY(bp)) << BNX2X_PRI_FLAG_STORAGE;
+
+       return flags;
+}
+
 static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
 {
        struct bnx2x *bp = netdev_priv(dev);
@@ -3026,7 +3071,6 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
                        }
                }
 
-
                for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
                        if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
                                continue;
@@ -3045,6 +3089,12 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
                        start = 4;
                memcpy(buf, bnx2x_tests_str_arr + start,
                       ETH_GSTRING_LEN * BNX2X_NUM_TESTS(bp));
+               break;
+
+       case ETH_SS_PRIV_FLAGS:
+               memcpy(buf, bnx2x_private_arr,
+                      ETH_GSTRING_LEN * BNX2X_PRI_FLAG_LEN);
+               break;
        }
 }
 
@@ -3106,17 +3156,12 @@ static int bnx2x_set_phys_id(struct net_device *dev,
 {
        struct bnx2x *bp = netdev_priv(dev);
 
-       if (!netif_running(dev)) {
+       if (!bnx2x_is_nvm_accessible(bp)) {
                DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
                   "cannot access eeprom when the interface is down\n");
                return -EAGAIN;
        }
 
-       if (!bp->port.pmf) {
-               DP(BNX2X_MSG_ETHTOOL, "Interface is not pmf\n");
-               return -EOPNOTSUPP;
-       }
-
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
                return 1;       /* cycle on/off once per second */
@@ -3148,7 +3193,6 @@ static int bnx2x_set_phys_id(struct net_device *dev,
 
 static int bnx2x_get_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
 {
-
        switch (info->flow_type) {
        case TCP_V4_FLOW:
        case TCP_V6_FLOW:
@@ -3384,7 +3428,6 @@ static int bnx2x_set_channels(struct net_device *dev,
 {
        struct bnx2x *bp = netdev_priv(dev);
 
-
        DP(BNX2X_MSG_ETHTOOL,
           "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n",
           channels->rx_count, channels->tx_count, channels->other_count,
@@ -3445,6 +3488,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
        .set_pauseparam         = bnx2x_set_pauseparam,
        .self_test              = bnx2x_self_test,
        .get_sset_count         = bnx2x_get_sset_count,
+       .get_priv_flags         = bnx2x_get_private_flags,
        .get_strings            = bnx2x_get_strings,
        .set_phys_id            = bnx2x_set_phys_id,
        .get_ethtool_stats      = bnx2x_get_ethtool_stats,
index 12f00a40cdf0e8c280f404d663378729f9cf3975..5ef3f964e544ebf443ad201efd73fcfe94385119 100644 (file)
@@ -1323,6 +1323,8 @@ struct drv_func_mb {
        #define DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET     0x00000002
 
        #define DRV_MSG_CODE_LOAD_REQ_WITH_LFA          0x0000100a
+       #define DRV_MSG_CODE_LOAD_REQ_FORCE_LFA         0x00002000
+
        u32 fw_mb_header;
        #define FW_MSG_CODE_MASK                        0xffff0000
        #define FW_MSG_CODE_DRV_LOAD_COMMON             0x10100000
index b4c9dea93a5362ecfa899c6b3a247d6432fcb4fd..658b9fd0275fce1ea44e1a4e3d9c3ada93399f22 100644 (file)
@@ -93,7 +93,6 @@ 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);
 MODULE_PARM_DESC(num_queues,
@@ -103,8 +102,6 @@ static int disable_tpa;
 module_param(disable_tpa, int, 0);
 MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");
 
-#define INT_MODE_INTx                  1
-#define INT_MODE_MSI                   2
 int int_mode;
 module_param(int_mode, int, 0);
 MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
@@ -122,8 +119,6 @@ static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, " Default debug msglevel");
 
-
-
 struct workqueue_struct *bnx2x_wq;
 
 struct bnx2x_mac_vals {
@@ -376,9 +371,11 @@ static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr)
 #define DMAE_DP_DST_PCI                "pci dst_addr [%x:%08x]"
 #define DMAE_DP_DST_NONE       "dst_addr [none]"
 
-void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, int msglvl)
+static void bnx2x_dp_dmae(struct bnx2x *bp,
+                         struct dmae_command *dmae, int msglvl)
 {
        u32 src_type = dmae->opcode & DMAE_COMMAND_SRC;
+       int i;
 
        switch (dmae->opcode & DMAE_COMMAND_DST) {
        case DMAE_CMD_DST_PCI:
@@ -434,6 +431,10 @@ void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, int msglvl)
                           dmae->comp_val);
                break;
        }
+
+       for (i = 0; i < (sizeof(struct dmae_command)/4); i++)
+               DP(msglvl, "DMAE RAW [%02d]: 0x%08x\n",
+                  i, *(((u32 *)dmae) + i));
 }
 
 /* copy command into DMAE command memory and set DMAE command go */
@@ -508,8 +509,9 @@ int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae)
        int cnt = CHIP_REV_IS_SLOW(bp) ? (400000) : 4000;
        int rc = 0;
 
-       /*
-        * Lock the dmae channel. Disable BHs to prevent a dead-lock
+       bnx2x_dp_dmae(bp, dmae, BNX2X_MSG_DMAE);
+
+       /* Lock the dmae channel. Disable BHs to prevent a dead-lock
         * as long as this code is called both from syscall context and
         * from ndo_set_rx_mode() flow that may be called from BH.
         */
@@ -548,6 +550,7 @@ unlock:
 void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
                      u32 len32)
 {
+       int rc;
        struct dmae_command dmae;
 
        if (!bp->dmae_ready) {
@@ -571,11 +574,16 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
        dmae.len = len32;
 
        /* issue the command and wait for completion */
-       bnx2x_issue_dmae_with_comp(bp, &dmae);
+       rc = bnx2x_issue_dmae_with_comp(bp, &dmae);
+       if (rc) {
+               BNX2X_ERR("DMAE returned failure %d\n", rc);
+               bnx2x_panic();
+       }
 }
 
 void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
 {
+       int rc;
        struct dmae_command dmae;
 
        if (!bp->dmae_ready) {
@@ -603,7 +611,11 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
        dmae.len = len32;
 
        /* issue the command and wait for completion */
-       bnx2x_issue_dmae_with_comp(bp, &dmae);
+       rc = bnx2x_issue_dmae_with_comp(bp, &dmae);
+       if (rc) {
+               BNX2X_ERR("DMAE returned failure %d\n", rc);
+               bnx2x_panic();
+       };
 }
 
 static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
@@ -811,8 +823,8 @@ static void bnx2x_hc_int_disable(struct bnx2x *bp)
        u32 val = REG_RD(bp, addr);
 
        /* in E1 we must use only PCI configuration space to disable
-        * MSI/MSIX capablility
-        * It's forbitten to disable IGU_PF_CONF_MSI_MSIX_EN in HC block
+        * MSI/MSIX capability
+        * It's forbidden to disable IGU_PF_CONF_MSI_MSIX_EN in HC block
         */
        if (CHIP_IS_E1(bp)) {
                /* Since IGU_PF_CONF_MSI_MSIX_EN still always on
@@ -839,7 +851,7 @@ static void bnx2x_hc_int_disable(struct bnx2x *bp)
 
        REG_WR(bp, addr, val);
        if (REG_RD(bp, addr) != val)
-               BNX2X_ERR("BUG! proper val not read from IGU!\n");
+               BNX2X_ERR("BUG! Proper val not read from IGU!\n");
 }
 
 static void bnx2x_igu_int_disable(struct bnx2x *bp)
@@ -857,7 +869,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp)
 
        REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
        if (REG_RD(bp, IGU_REG_PF_CONFIGURATION) != val)
-               BNX2X_ERR("BUG! proper val not read from IGU!\n");
+               BNX2X_ERR("BUG! Proper val not read from IGU!\n");
 }
 
 static void bnx2x_int_disable(struct bnx2x *bp)
@@ -917,7 +929,6 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
               sp_sb_data.p_func.vf_valid,
               sp_sb_data.state);
 
-
        for_each_eth_queue(bp, i) {
                struct bnx2x_fastpath *fp = &bp->fp[i];
                int loop;
@@ -1016,7 +1027,7 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
                                hc_sm_p[j].timer_value);
                }
 
-               /* Indecies data */
+               /* Indices data */
                for (j = 0; j < loop; j++) {
                        pr_cont("INDEX[%d] flags (0x%x) timeout (0x%x)\n", j,
                               hc_index_p[j].flags,
@@ -1027,6 +1038,7 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
 #ifdef BNX2X_STOP_ON_ERROR
 
        /* event queue */
+       BNX2X_ERR("eq cons %x prod %x\n", bp->eq_cons, bp->eq_prod);
        for (i = 0; i < NUM_EQ_DESC; i++) {
                u32 *data = (u32 *)&bp->eq_ring[i].message.data;
 
@@ -1111,7 +1123,7 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int)
  * bnx2x_pf_flr_clnup() is called during nic_load in the per function HW
  * initialization.
  */
-#define FLR_WAIT_USEC          10000   /* 10 miliseconds */
+#define FLR_WAIT_USEC          10000   /* 10 milliseconds */
 #define FLR_WAIT_INTERVAL      50      /* usec */
 #define        FLR_POLL_CNT            (FLR_WAIT_USEC/FLR_WAIT_INTERVAL) /* 200 */
 
@@ -1290,7 +1302,6 @@ void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count)
        for (i = 0; i < ARRAY_SIZE(cmd_regs); i++)
                bnx2x_pbf_pN_cmd_flushed(bp, &cmd_regs[i], poll_count);
 
-
        /* Verify the transmission buffers are flushed P0, P1, P4 */
        for (i = 0; i < ARRAY_SIZE(buf_regs); i++)
                bnx2x_pbf_pN_buf_flushed(bp, &buf_regs[i], poll_count);
@@ -1305,11 +1316,9 @@ void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count)
 #define OP_GEN_AGG_VECT(index) \
        (((index) << SDM_OP_GEN_AGG_VECT_IDX_SHIFT) & SDM_OP_GEN_AGG_VECT_IDX)
 
-
 int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func, u32 poll_cnt)
 {
        u32 op_gen_command = 0;
-
        u32 comp_addr = BAR_CSTRORM_INTMEM +
                        CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(clnup_func);
        int ret = 0;
@@ -1334,7 +1343,7 @@ int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func, u32 poll_cnt)
                bnx2x_panic();
                return 1;
        }
-       /* Zero completion for nxt FLR */
+       /* Zero completion for next FLR */
        REG_WR(bp, comp_addr, 0);
 
        return ret;
@@ -1352,7 +1361,6 @@ u8 bnx2x_is_pcie_pending(struct pci_dev *dev)
 */
 static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt)
 {
-
        /* wait for CFC PF usage-counter to zero (includes all the VFs) */
        if (bnx2x_flr_clnup_poll_hw_counter(bp,
                        CFC_REG_NUM_LCIDS_INSIDE_PF,
@@ -1360,7 +1368,6 @@ static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt)
                        poll_cnt))
                return 1;
 
-
        /* Wait for DQ PF usage-counter to zero (until DQ cleanup) */
        if (bnx2x_flr_clnup_poll_hw_counter(bp,
                        DORQ_REG_PF_USAGE_CNT,
@@ -1390,7 +1397,7 @@ static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt)
        /* Wait DMAE PF usage counter to zero */
        if (bnx2x_flr_clnup_poll_hw_counter(bp,
                        dmae_reg_go_c[INIT_DMAE_C(bp)],
-                       "DMAE dommand register timed out",
+                       "DMAE command register timed out",
                        poll_cnt))
                return 1;
 
@@ -1770,7 +1777,7 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
                break;
 
        case (RAMROD_CMD_ID_ETH_TERMINATE):
-               DP(BNX2X_MSG_SP, "got MULTI[%d] teminate ramrod\n", cid);
+               DP(BNX2X_MSG_SP, "got MULTI[%d] terminate ramrod\n", cid);
                drv_cmd = BNX2X_Q_CMD_TERMINATE;
                break;
 
@@ -1947,7 +1954,7 @@ int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource)
                if (lock_status & resource_bit)
                        return 0;
 
-               msleep(5);
+               usleep_range(5000, 10000);
        }
        BNX2X_ERR("Timeout\n");
        return -EAGAIN;
@@ -1982,8 +1989,8 @@ int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource)
        /* Validating that the resource is currently taken */
        lock_status = REG_RD(bp, hw_lock_control_reg);
        if (!(lock_status & resource_bit)) {
-               BNX2X_ERR("lock_status 0x%x resource_bit 0x%x. unlock was called but lock wasn't taken!\n",
-                  lock_status, resource_bit);
+               BNX2X_ERR("lock_status 0x%x resource_bit 0x%x. Unlock was called but lock wasn't taken!\n",
+                         lock_status, resource_bit);
                return -EFAULT;
        }
 
@@ -1991,7 +1998,6 @@ int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource)
        return 0;
 }
 
-
 int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port)
 {
        /* The GPIO should be swapped if swap register is set and active */
@@ -2347,14 +2353,13 @@ u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes)
        return rc;
 }
 
-
 /* Calculates the sum of vn_min_rates.
    It's needed for further normalizing of the min_rates.
    Returns:
      sum of vn_min_rates.
        or
      0 - if all the min_rates are 0.
-     In the later case fainess algorithm should be deactivated.
+     In the later case fairness algorithm should be deactivated.
      If not all min_rates are zero then those that are zeroes will be set to 1.
  */
 static void bnx2x_calc_vn_min(struct bnx2x *bp,
@@ -2419,7 +2424,6 @@ static void bnx2x_calc_vn_max(struct bnx2x *bp, int vn,
        input->vnic_max_rate[vn] = vn_max_rate;
 }
 
-
 static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp)
 {
        if (CHIP_REV_IS_SLOW(bp))
@@ -2435,7 +2439,7 @@ void bnx2x_read_mf_cfg(struct bnx2x *bp)
        int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1);
 
        if (BP_NOMCP(bp))
-               return; /* what should be the default bvalue in this case */
+               return; /* what should be the default value in this case */
 
        /* For 2 port configuration the absolute function number formula
         * is:
@@ -2901,7 +2905,6 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
        return rc;
 }
 
-
 static void storm_memset_func_cfg(struct bnx2x *bp,
                                 struct tstorm_eth_function_common_config *tcfg,
                                 u16 abs_fid)
@@ -2935,7 +2938,7 @@ void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
 }
 
 /**
- * bnx2x_get_tx_only_flags - Return common flags
+ * bnx2x_get_common_flags - Return common flags
  *
  * @bp         device handle
  * @fp         queue handle
@@ -3006,7 +3009,6 @@ static unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
        if (IS_MF_AFEX(bp))
                __set_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, &flags);
 
-
        return flags | bnx2x_get_common_flags(bp, fp, true);
 }
 
@@ -3082,7 +3084,7 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
         * placed on the BD (not including paddings).
         */
        rxq_init->buf_sz = fp->rx_buf_size - BNX2X_FW_RX_ALIGN_START -
-               BNX2X_FW_RX_ALIGN_END - IP_HEADER_ALIGNMENT_PADDING;
+                          BNX2X_FW_RX_ALIGN_END - IP_HEADER_ALIGNMENT_PADDING;
 
        rxq_init->cl_qzone_id = fp->cl_qzone_id;
        rxq_init->tpa_agg_sz = tpa_agg_size;
@@ -3124,7 +3126,7 @@ static void bnx2x_pf_tx_q_prep(struct bnx2x *bp,
        txq_init->fw_sb_id = fp->fw_sb_id;
 
        /*
-        * set the tss leading client id for TX classfication ==
+        * set the tss leading client id for TX classification ==
         * leading RSS client id
         */
        txq_init->tss_leading_cl_id = bnx2x_fp(bp, 0, cl_id);
@@ -3196,7 +3198,6 @@ static void bnx2x_pf_init(struct bnx2x *bp)
        storm_memset_eq_data(bp, &eq_data, BP_FUNC(bp));
 }
 
-
 static void bnx2x_e1h_disable(struct bnx2x *bp)
 {
        int port = BP_PORT(bp);
@@ -3212,7 +3213,7 @@ static void bnx2x_e1h_enable(struct bnx2x *bp)
 
        REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
 
-       /* Tx queue should be only reenabled */
+       /* Tx queue should be only re-enabled */
        netif_tx_wake_all_queues(bp->dev);
 
        /*
@@ -3540,10 +3541,8 @@ static bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type)
                return true;
        else
                return false;
-
 }
 
-
 /**
  * bnx2x_sp_post - place a single command on an SP ring
  *
@@ -3608,14 +3607,13 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
        /*
         * It's ok if the actual decrement is issued towards the memory
         * somewhere between the spin_lock and spin_unlock. Thus no
-        * more explict memory barrier is needed.
+        * more explicit memory barrier is needed.
         */
        if (common)
                atomic_dec(&bp->eq_spq_left);
        else
                atomic_dec(&bp->cq_spq_left);
 
-
        DP(BNX2X_MSG_SP,
           "SPQE[%x] (%x:%x)  (cmd, common?) (%d,%d)  hw_cid %x  data (%x:%x) type(0x%x) left (CQ, EQ) (%x,%x)\n",
           bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping),
@@ -3637,15 +3635,14 @@ static int bnx2x_acquire_alr(struct bnx2x *bp)
 
        might_sleep();
        for (j = 0; j < 1000; j++) {
-               val = (1UL << 31);
-               REG_WR(bp, GRCBASE_MCP + 0x9c, val);
-               val = REG_RD(bp, GRCBASE_MCP + 0x9c);
-               if (val & (1L << 31))
+               REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, MCPR_ACCESS_LOCK_LOCK);
+               val = REG_RD(bp, MCP_REG_MCPR_ACCESS_LOCK);
+               if (val & MCPR_ACCESS_LOCK_LOCK)
                        break;
 
-               msleep(5);
+               usleep_range(5000, 10000);
        }
-       if (!(val & (1L << 31))) {
+       if (!(val & MCPR_ACCESS_LOCK_LOCK)) {
                BNX2X_ERR("Cannot acquire MCP access lock register\n");
                rc = -EBUSY;
        }
@@ -3656,7 +3653,7 @@ static int bnx2x_acquire_alr(struct bnx2x *bp)
 /* release split MCP access lock register */
 static void bnx2x_release_alr(struct bnx2x *bp)
 {
-       REG_WR(bp, GRCBASE_MCP + 0x9c, 0);
+       REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, 0);
 }
 
 #define BNX2X_DEF_SB_ATT_IDX   0x0001
@@ -3678,7 +3675,7 @@ static u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
                rc |= BNX2X_DEF_SB_IDX;
        }
 
-       /* Do not reorder: indecies reading should complete before handling */
+       /* Do not reorder: indices reading should complete before handling */
        barrier();
        return rc;
 }
@@ -3827,8 +3824,7 @@ static void bnx2x_fan_failure(struct bnx2x *bp)
        netdev_err(bp->dev, "Fan Failure on Network Controller has caused the driver to shutdown the card to prevent permanent damage.\n"
                            "Please contact OEM Support for assistance\n");
 
-       /*
-        * Schedule device reset (unload)
+       /* Schedule device reset (unload)
         * This is due to some boards consuming sufficient power when driver is
         * up to overheat if fan fails.
         */
@@ -3836,7 +3832,6 @@ static void bnx2x_fan_failure(struct bnx2x *bp)
        set_bit(BNX2X_SP_RTNL_FAN_FAILURE, &bp->sp_rtnl_state);
        smp_mb__after_clear_bit();
        schedule_delayed_work(&bp->sp_rtnl_task, 0);
-
 }
 
 static void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
@@ -4106,7 +4101,7 @@ static void bnx2x_clear_reset_global(struct bnx2x *bp)
  */
 static bool bnx2x_reset_is_global(struct bnx2x *bp)
 {
-       u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+       u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
 
        DP(NETIF_MSG_HW, "GEN_REG_VAL=0x%08x\n", val);
        return (val & BNX2X_GLOBAL_RESET_BIT) ? true : false;
@@ -4157,7 +4152,7 @@ void bnx2x_set_reset_in_progress(struct bnx2x *bp)
  */
 bool bnx2x_reset_is_done(struct bnx2x *bp, int engine)
 {
-       u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+       u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
        u32 bit = engine ?
                BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
 
@@ -4260,13 +4255,18 @@ static bool bnx2x_get_load_status(struct bnx2x *bp, int engine)
        return val != 0;
 }
 
+static void _print_parity(struct bnx2x *bp, u32 reg)
+{
+       pr_cont(" [0x%08x] ", REG_RD(bp, reg));
+}
+
 static void _print_next_block(int idx, const char *blk)
 {
        pr_cont("%s%s", idx ? ", " : "", blk);
 }
 
-static int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
-                                          bool print)
+static int bnx2x_check_blocks_with_parity0(struct bnx2x *bp, u32 sig,
+                                           int par_num, bool print)
 {
        int i = 0;
        u32 cur_bit = 0;
@@ -4275,33 +4275,54 @@ static int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
                if (sig & cur_bit) {
                        switch (cur_bit) {
                        case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "BRB");
+                                       _print_parity(bp,
+                                                     BRB1_REG_BRB1_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "PARSER");
+                                       _print_parity(bp, PRS_REG_PRS_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "TSDM");
+                                       _print_parity(bp,
+                                                     TSDM_REG_TSDM_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++,
                                                          "SEARCHER");
+                                       _print_parity(bp, SRC_REG_SRC_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "TCM");
+                                       _print_parity(bp,
+                                                     TCM_REG_TCM_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "TSEMI");
+                                       _print_parity(bp,
+                                                     TSEM_REG_TSEM_PRTY_STS_0);
+                                       _print_parity(bp,
+                                                     TSEM_REG_TSEM_PRTY_STS_1);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "XPB");
+                                       _print_parity(bp, GRCBASE_XPB +
+                                                         PB_REG_PB_PRTY_STS);
+                               }
                                break;
                        }
 
@@ -4313,8 +4334,9 @@ static int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
        return par_num;
 }
 
-static int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
-                                          bool *global, bool print)
+static int bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
+                                           int par_num, bool *global,
+                                           bool print)
 {
        int i = 0;
        u32 cur_bit = 0;
@@ -4323,37 +4345,66 @@ static int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
                if (sig & cur_bit) {
                        switch (cur_bit) {
                        case AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "PBF");
+                                       _print_parity(bp, PBF_REG_PBF_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "QM");
+                                       _print_parity(bp, QM_REG_QM_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "TM");
+                                       _print_parity(bp, TM_REG_TM_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "XSDM");
+                                       _print_parity(bp,
+                                                     XSDM_REG_XSDM_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "XCM");
+                                       _print_parity(bp, XCM_REG_XCM_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "XSEMI");
+                                       _print_parity(bp,
+                                                     XSEM_REG_XSEM_PRTY_STS_0);
+                                       _print_parity(bp,
+                                                     XSEM_REG_XSEM_PRTY_STS_1);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++,
                                                          "DOORBELLQ");
+                                       _print_parity(bp,
+                                                     DORQ_REG_DORQ_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "NIG");
+                                       if (CHIP_IS_E1x(bp)) {
+                                               _print_parity(bp,
+                                                       NIG_REG_NIG_PRTY_STS);
+                                       } else {
+                                               _print_parity(bp,
+                                                       NIG_REG_NIG_PRTY_STS_0);
+                                               _print_parity(bp,
+                                                       NIG_REG_NIG_PRTY_STS_1);
+                                       }
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR:
                                if (print)
@@ -4362,32 +4413,52 @@ static int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
                                *global = true;
                                break;
                        case AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "DEBUG");
+                                       _print_parity(bp, DBG_REG_DBG_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "USDM");
+                                       _print_parity(bp,
+                                                     USDM_REG_USDM_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "UCM");
+                                       _print_parity(bp, UCM_REG_UCM_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "USEMI");
+                                       _print_parity(bp,
+                                                     USEM_REG_USEM_PRTY_STS_0);
+                                       _print_parity(bp,
+                                                     USEM_REG_USEM_PRTY_STS_1);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "UPB");
+                                       _print_parity(bp, GRCBASE_UPB +
+                                                         PB_REG_PB_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "CSDM");
+                                       _print_parity(bp,
+                                                     CSDM_REG_CSDM_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "CCM");
+                                       _print_parity(bp, CCM_REG_CCM_PRTY_STS);
+                               }
                                break;
                        }
 
@@ -4399,8 +4470,8 @@ static int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
        return par_num;
 }
 
-static int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
-                                          bool print)
+static int bnx2x_check_blocks_with_parity2(struct bnx2x *bp, u32 sig,
+                                           int par_num, bool print)
 {
        int i = 0;
        u32 cur_bit = 0;
@@ -4409,12 +4480,23 @@ static int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
                if (sig & cur_bit) {
                        switch (cur_bit) {
                        case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "CSEMI");
+                                       _print_parity(bp,
+                                                     CSEM_REG_CSEM_PRTY_STS_0);
+                                       _print_parity(bp,
+                                                     CSEM_REG_CSEM_PRTY_STS_1);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "PXP");
+                                       _print_parity(bp, PXP_REG_PXP_PRTY_STS);
+                                       _print_parity(bp,
+                                                     PXP2_REG_PXP2_PRTY_STS_0);
+                                       _print_parity(bp,
+                                                     PXP2_REG_PXP2_PRTY_STS_1);
+                               }
                                break;
                        case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR:
                                if (print)
@@ -4422,24 +4504,42 @@ static int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
                                        "PXPPCICLOCKCLIENT");
                                break;
                        case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "CFC");
+                                       _print_parity(bp,
+                                                     CFC_REG_CFC_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "CDU");
+                                       _print_parity(bp, CDU_REG_CDU_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "DMAE");
+                                       _print_parity(bp,
+                                                     DMAE_REG_DMAE_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "IGU");
+                                       if (CHIP_IS_E1x(bp))
+                                               _print_parity(bp,
+                                                       HC_REG_HC_PRTY_STS);
+                                       else
+                                               _print_parity(bp,
+                                                       IGU_REG_IGU_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "MISC");
+                                       _print_parity(bp,
+                                                     MISC_REG_MISC_PRTY_STS);
+                               }
                                break;
                        }
 
@@ -4493,8 +4593,8 @@ static int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
        return par_num;
 }
 
-static int bnx2x_check_blocks_with_parity4(u32 sig, int par_num,
-                                          bool print)
+static int bnx2x_check_blocks_with_parity4(struct bnx2x *bp, u32 sig,
+                                           int par_num, bool print)
 {
        int i = 0;
        u32 cur_bit = 0;
@@ -4503,12 +4603,18 @@ static int bnx2x_check_blocks_with_parity4(u32 sig, int par_num,
                if (sig & cur_bit) {
                        switch (cur_bit) {
                        case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "PGLUE_B");
+                                       _print_parity(bp,
+                                               PGLUE_B_REG_PGLUE_B_PRTY_STS);
+                               }
                                break;
                        case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR:
-                               if (print)
+                               if (print) {
                                        _print_next_block(par_num++, "ATC");
+                                       _print_parity(bp,
+                                                     ATC_REG_ATC_PRTY_STS);
+                               }
                                break;
                        }
 
@@ -4539,15 +4645,15 @@ static bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
                if (print)
                        netdev_err(bp->dev,
                                   "Parity errors detected in blocks: ");
-               par_num = bnx2x_check_blocks_with_parity0(
+               par_num = bnx2x_check_blocks_with_parity0(bp,
                        sig[0] & HW_PRTY_ASSERT_SET_0, par_num, print);
-               par_num = bnx2x_check_blocks_with_parity1(
+               par_num = bnx2x_check_blocks_with_parity1(bp,
                        sig[1] & HW_PRTY_ASSERT_SET_1, par_num, global, print);
-               par_num = bnx2x_check_blocks_with_parity2(
+               par_num = bnx2x_check_blocks_with_parity2(bp,
                        sig[2] & HW_PRTY_ASSERT_SET_2, par_num, print);
                par_num = bnx2x_check_blocks_with_parity3(
                        sig[3] & HW_PRTY_ASSERT_SET_3, par_num, global, print);
-               par_num = bnx2x_check_blocks_with_parity4(
+               par_num = bnx2x_check_blocks_with_parity4(bp,
                        sig[4] & HW_PRTY_ASSERT_SET_4, par_num, print);
 
                if (print)
@@ -4591,7 +4697,6 @@ bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print)
        return bnx2x_parity_attn(bp, global, print, attn.sig);
 }
 
-
 static void bnx2x_attn_int_deasserted4(struct bnx2x *bp, u32 attn)
 {
        u32 val;
@@ -4643,7 +4748,6 @@ static void bnx2x_attn_int_deasserted4(struct bnx2x *bp, u32 attn)
                (u32)(attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR |
                    AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)));
        }
-
 }
 
 static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
@@ -4878,7 +4982,6 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
                BNX2X_ERR("Failed to schedule new commands: %d\n", rc);
        else if (rc > 0)
                DP(BNX2X_MSG_SP, "Scheduled next pending commands...\n");
-
 }
 
 static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start);
@@ -5009,7 +5112,7 @@ static void bnx2x_eq_int(struct bnx2x *bp)
        hw_cons = le16_to_cpu(*bp->eq_cons_sb);
 
        /* The hw_cos range is 1-255, 257 - the sw_cons range is 0-254, 256.
-        * when we get the the next-page we nned to adjust so the loop
+        * when we get the next-page we need to adjust so the loop
         * condition below will be met. The next element is the size of a
         * regular element and hence incrementing by 1
         */
@@ -5075,8 +5178,6 @@ static void bnx2x_eq_int(struct bnx2x *bp)
                        if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL))
                                break;
 
-
-
                        goto next_spqe;
 
                case EVENT_RING_OPCODE_STOP_TRAFFIC:
@@ -5218,7 +5319,7 @@ static void bnx2x_sp_task(struct work_struct *work)
 
        DP(BNX2X_MSG_SP, "sp task invoked\n");
 
-       /* make sure the atomic interupt_occurred has been written */
+       /* make sure the atomic interrupt_occurred has been written */
        smp_rmb();
        if (atomic_read(&bp->interrupt_occurred)) {
 
@@ -5265,7 +5366,6 @@ static void bnx2x_sp_task(struct work_struct *work)
                /* ack status block only if something was actually handled */
                bnx2x_ack_sb(bp, bp->igu_dsb_id, ATTENTION_ID,
                             le16_to_cpu(bp->def_att_idx), IGU_INT_ENABLE, 1);
-
        }
 
        /* must be called after the EQ processing (since eq leads to sriov
@@ -5316,7 +5416,6 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
 
 /* end of slow path */
 
-
 void bnx2x_drv_pulse(struct bnx2x *bp)
 {
        SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
@@ -5382,7 +5481,6 @@ static void bnx2x_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
        else
                for (i = 0; i < len; i++)
                        REG_WR8(bp, addr + i, fill);
-
 }
 
 /* helper: writes FP SP data to FW - data_size in dwords */
@@ -5461,10 +5559,8 @@ static void bnx2x_zero_sp_sb(struct bnx2x *bp)
        bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
                        CSTORM_SP_SYNC_BLOCK_OFFSET(func), 0,
                        CSTORM_SP_SYNC_BLOCK_SIZE);
-
 }
 
-
 static void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm,
                                           int igu_sb_id, int igu_seg_id)
 {
@@ -5474,7 +5570,6 @@ static void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm,
        hc_sm->time_to_expire = 0xFFFFFFFF;
 }
 
-
 /* allocates state machine ids. */
 static void bnx2x_map_sb_state_machines(struct hc_index_data *index_data)
 {
@@ -5700,7 +5795,7 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
        bp->eq_cons = 0;
        bp->eq_prod = NUM_EQ_DESC;
        bp->eq_cons_sb = BNX2X_EQ_INDEX;
-       /* we want a warning message before it gets rought... */
+       /* we want a warning message before it gets wrought... */
        atomic_set(&bp->eq_spq_left,
                min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
 }
@@ -5784,7 +5879,7 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode,
 
                break;
        case BNX2X_RX_MODE_PROMISC:
-               /* According to deffinition of SI mode, iface in promisc mode
+               /* According to definition of SI mode, iface in promisc mode
                 * should receive matched and unmatched (in resolution of port)
                 * unicast packets.
                 */
@@ -5927,7 +6022,7 @@ static void bnx2x_init_eth_fp(struct bnx2x *bp, int fp_idx)
        /* init shortcut */
        fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp);
 
-       /* Setup SB indicies */
+       /* Setup SB indices */
        fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
 
        /* Configure Queue State object */
@@ -5983,6 +6078,8 @@ static void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
                                    BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
        }
 
+       *txdata->tx_cons_sb = cpu_to_le16(0);
+
        SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
        txdata->tx_db.data.zero_fill1 = 0;
        txdata->tx_db.data.prod = 0;
@@ -6001,6 +6098,7 @@ static void bnx2x_init_tx_rings_cnic(struct bnx2x *bp)
        for_each_tx_queue_cnic(bp, i)
                bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[0]);
 }
+
 static void bnx2x_init_tx_rings(struct bnx2x *bp)
 {
        int i;
@@ -6043,11 +6141,6 @@ void bnx2x_pre_irq_nic_init(struct bnx2x *bp)
        bnx2x_init_rx_rings(bp);
        bnx2x_init_tx_rings(bp);
 
-       if (IS_VF(bp)) {
-               bnx2x_memset_stats(bp);
-               return;
-       }
-
        if (IS_PF(bp)) {
                /* Initialize MOD_ABS interrupts */
                bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
@@ -6058,6 +6151,8 @@ void bnx2x_pre_irq_nic_init(struct bnx2x *bp)
                bnx2x_init_def_sb(bp);
                bnx2x_update_dsb_idx(bp);
                bnx2x_init_sp_ring(bp);
+       } else {
+               bnx2x_memset_stats(bp);
        }
 }
 
@@ -6236,7 +6331,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
                if (val == 0x10)
                        break;
 
-               msleep(10);
+               usleep_range(10000, 20000);
                count--;
        }
        if (val != 0x10) {
@@ -6251,7 +6346,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
                if (val == 1)
                        break;
 
-               msleep(10);
+               usleep_range(10000, 20000);
                count--;
        }
        if (val != 0x1) {
@@ -6292,7 +6387,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
                if (val == 0xb0)
                        break;
 
-               msleep(10);
+               usleep_range(10000, 20000);
                count--;
        }
        if (val != 0xb0) {
@@ -6681,7 +6776,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
  *                 stay set)
  *             f.  If this is VNIC 3 of a port then also init
  *                 first_timers_ilt_entry to zero and last_timers_ilt_entry
- *                 to the last enrty in the ILT.
+ *                 to the last entry in the ILT.
  *
  *     Notes:
  *     Currently the PF error in the PGLC is non recoverable.
@@ -6772,7 +6867,6 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
 
        bnx2x_init_block(bp, BLOCK_QM, PHASE_COMMON);
 
-
        /* QM queues pointers table */
        bnx2x_qm_init_ptr_table(bp, bp->qm_cid_count, INITOP_SET);
 
@@ -7013,7 +7107,6 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
        u32 low, high;
        u32 val;
 
-
        DP(NETIF_MSG_HW, "starting port init  port %d\n", port);
 
        REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
@@ -7078,7 +7171,6 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
                            BRB1_REG_MAC_GUARANTIED_1 :
                            BRB1_REG_MAC_GUARANTIED_0), 40);
 
-
        bnx2x_init_block(bp, BLOCK_PRS, init_phase);
        if (CHIP_IS_E3B0(bp)) {
                if (IS_MF_AFEX(bp)) {
@@ -7150,8 +7242,8 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 
        bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase);
        /* init aeu_mask_attn_func_0/1:
-        *  - SF mode: bits 3-7 are masked. only bits 0-2 are in use
-        *  - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
+        *  - SF mode: bits 3-7 are masked. Only bits 0-2 are in use
+        *  - MF mode: bit 3 is masked. Bits 0-2 are in use as in SF
         *             bits 4-7 are used for "per vn group attention" */
        val = IS_MF(bp) ? 0xF7 : 0x7;
        /* Enable DCBX attention for all but E1 */
@@ -7275,7 +7367,6 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id, bool is_pf)
        while (!(REG_RD(bp, igu_addr_ack) & sb_bit) && --cnt)
                msleep(20);
 
-
        if (!(REG_RD(bp, igu_addr_ack) & sb_bit)) {
                DP(NETIF_MSG_HW,
                   "Unable to finish IGU cleanup: idu_sb_id %d offset %d bit %d (cnt %d)\n",
@@ -7295,7 +7386,6 @@ static void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
                bnx2x_ilt_wr(bp, i, 0);
 }
 
-
 static void bnx2x_init_searcher(struct bnx2x *bp)
 {
        int port = BP_PORT(bp);
@@ -7331,7 +7421,6 @@ static int bnx2x_reset_nic_mode(struct bnx2x *bp)
        int rc, i, port = BP_PORT(bp);
        int vlan_en = 0, mac_en[NUM_MACS];
 
-
        /* Close input from network */
        if (bp->mf_mode == SINGLE_FUNCTION) {
                bnx2x_set_rx_filter(&bp->link_params, 0);
@@ -7406,7 +7495,7 @@ int bnx2x_init_hw_func_cnic(struct bnx2x *bp)
        bnx2x_ilt_init_op_cnic(bp, INITOP_SET);
 
        if (CONFIGURE_NIC_MODE(bp)) {
-               /* Configrue searcher as part of function hw init */
+               /* Configure searcher as part of function hw init */
                bnx2x_init_searcher(bp);
 
                /* Reset NIC mode */
@@ -7479,8 +7568,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
        } else {
                /* Set NIC mode */
                REG_WR(bp, PRS_REG_NIC_MODE, 1);
-               DP(NETIF_MSG_IFUP, "NIC MODE configrued\n");
-
+               DP(NETIF_MSG_IFUP, "NIC MODE configured\n");
        }
 
        if (!CHIP_IS_E1x(bp)) {
@@ -7677,7 +7765,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
                        }
                        bnx2x_igu_clear_sb(bp, bp->igu_dsb_id);
 
-                       /* !!! these should become driver const once
+                       /* !!! These should become driver const once
                           rf-tool supports split-68 const */
                        REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_LSB, 0);
                        REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_MSB, 0);
@@ -7734,7 +7822,6 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
        return 0;
 }
 
-
 void bnx2x_free_mem_cnic(struct bnx2x *bp)
 {
        bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_FREE);
@@ -7779,7 +7866,6 @@ void bnx2x_free_mem(struct bnx2x *bp)
        bnx2x_iov_free_mem(bp);
 }
 
-
 int bnx2x_alloc_mem_cnic(struct bnx2x *bp)
 {
        if (!CHIP_IS_E1x(bp))
@@ -7793,7 +7879,7 @@ int bnx2x_alloc_mem_cnic(struct bnx2x *bp)
                                       host_hc_status_block_e1x));
 
        if (CONFIGURE_NIC_MODE(bp) && !bp->t2)
-               /* allocate searcher T2 table, as it wan't allocated before */
+               /* allocate searcher T2 table, as it wasn't allocated before */
                BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
 
        /* write address to which L5 should insert its values */
@@ -8068,7 +8154,6 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
                   ilt_client->page_size,
                   ilt_client->flags,
                   ilog2(ilt_client->page_size >> 12));
-
        }
 
        if (CNIC_SUPPORT(bp)) {
@@ -8124,7 +8209,6 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
 static void bnx2x_pf_q_prep_init(struct bnx2x *bp,
        struct bnx2x_fastpath *fp, struct bnx2x_queue_init_params *init_params)
 {
-
        u8 cos;
        int cxt_index, cxt_offset;
 
@@ -8133,7 +8217,7 @@ static void bnx2x_pf_q_prep_init(struct bnx2x *bp,
                __set_bit(BNX2X_Q_FLG_HC, &init_params->rx.flags);
                __set_bit(BNX2X_Q_FLG_HC, &init_params->tx.flags);
 
-               /* If HC is supporterd, enable host coalescing in the transition
+               /* If HC is supported, enable host coalescing in the transition
                 * to INIT state.
                 */
                __set_bit(BNX2X_Q_FLG_HC_EN, &init_params->rx.flags);
@@ -8205,7 +8289,6 @@ static int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        return bnx2x_queue_state_change(bp, q_params);
 }
 
-
 /**
  * bnx2x_setup_queue - setup queue
  *
@@ -8254,7 +8337,6 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 
        DP(NETIF_MSG_IFUP, "init complete\n");
 
-
        /* Now move the Queue to the SETUP state... */
        memset(setup_params, 0, sizeof(*setup_params));
 
@@ -8315,7 +8397,6 @@ static int bnx2x_stop_queue(struct bnx2x *bp, int index)
        /* We want to wait for completion in this context */
        __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
 
-
        /* close tx-only connections */
        for (tx_index = FIRST_TX_ONLY_COS_INDEX;
             tx_index < fp->max_cos;
@@ -8369,7 +8450,6 @@ static int bnx2x_stop_queue(struct bnx2x *bp, int index)
        return bnx2x_queue_state_change(bp, &q_params);
 }
 
-
 static void bnx2x_reset_func(struct bnx2x *bp)
 {
        int port = BP_PORT(bp);
@@ -8422,7 +8502,7 @@ static void bnx2x_reset_func(struct bnx2x *bp)
                 * scan to complete
                 */
                for (i = 0; i < 200; i++) {
-                       msleep(10);
+                       usleep_range(10000, 20000);
                        if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4))
                                break;
                }
@@ -8623,14 +8703,14 @@ static int bnx2x_func_wait_started(struct bnx2x *bp)
 
        /*
         * (assumption: No Attention from MCP at this stage)
-        * PMF probably in the middle of TXdisable/enable transaction
+        * PMF probably in the middle of TX disable/enable transaction
         * 1. Sync IRS for default SB
-        * 2. Sync SP queue - this guarantes us that attention handling started
-        * 3. Wait, that TXdisable/enable transaction completes
+        * 2. Sync SP queue - this guarantees us that attention handling started
+        * 3. Wait, that TX disable/enable transaction completes
         *
-        * 1+2 guranty that if DCBx attention was scheduled it already changed
-        * pending bit of transaction from STARTED-->TX_STOPPED, if we alredy
-        * received complettion for the transaction the state is TX_STOPPED.
+        * 1+2 guarantee that if DCBx attention was scheduled it already changed
+        * pending bit of transaction from STARTED-->TX_STOPPED, if we already
+        * received completion for the transaction the state is TX_STOPPED.
         * State will return to STARTED after completion of TX_STOPPED-->STARTED
         * transaction.
         */
@@ -8660,7 +8740,7 @@ static int bnx2x_func_wait_started(struct bnx2x *bp)
                struct bnx2x_func_state_params func_params = {NULL};
 
                DP(NETIF_MSG_IFDOWN,
-                  "Hmmm... unexpected function state! Forcing STARTED-->TX_ST0PPED-->STARTED\n");
+                  "Hmmm... Unexpected function state! Forcing STARTED-->TX_ST0PPED-->STARTED\n");
 
                func_params.f_obj = &bp->func_obj;
                __set_bit(RAMROD_DRV_CLR_ONLY,
@@ -8740,7 +8820,6 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link)
 
        bnx2x_iov_chip_cleanup(bp);
 
-
        /*
         * Send the UNLOAD_REQUEST to the MCP. This will return if
         * this function should perform FUNC, PORT or COMMON HW
@@ -8750,7 +8829,7 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link)
 
        /*
         * (assumption: No Attention from MCP at this stage)
-        * PMF probably in the middle of TXdisable/enable transaction
+        * PMF probably in the middle of TX disable/enable transaction
         */
        rc = bnx2x_func_wait_started(bp);
        if (rc) {
@@ -8813,7 +8892,6 @@ unload_error:
        if (rc)
                BNX2X_ERR("HW_RESET failed\n");
 
-
        /* Report UNLOAD_DONE to MCP */
        bnx2x_send_unload_done(bp, keep_link);
 }
@@ -9179,7 +9257,6 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
        if (!CHIP_IS_E1x(bp) && bnx2x_er_poll_igu_vq(bp))
                return -EAGAIN;
 
-
        /* TBD: Indicate that "process kill" is in progress to MCP */
 
        /* Clear "unprepared" bit */
@@ -9367,7 +9444,7 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
                                 * the first leader that performs a
                                 * leader_reset() reset the global blocks in
                                 * order to clear global attentions. Otherwise
-                                * the the gates will remain closed for that
+                                * the gates will remain closed for that
                                 * engine.
                                 */
                                if (load_status ||
@@ -9480,14 +9557,12 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work)
                return;
        }
 
-       /* if stop on error is defined no recovery flows should be executed */
+       if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) {
 #ifdef BNX2X_STOP_ON_ERROR
-       BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined so reset not done to allow debug dump,\n"
-                 "you will need to reboot when done\n");
-       goto sp_rtnl_not_reset;
+               BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined so reset not done to allow debug dump,\n"
+                         "you will need to reboot when done\n");
+               goto sp_rtnl_not_reset;
 #endif
-
-       if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) {
                /*
                 * Clear all pending SP commands as we are going to reset the
                 * function anyway.
@@ -9502,6 +9577,12 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work)
        }
 
        if (test_and_clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state)) {
+#ifdef BNX2X_STOP_ON_ERROR
+               BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined so reset not done to allow debug dump,\n"
+                         "you will need to reboot when done\n");
+               goto sp_rtnl_not_reset;
+#endif
+
                /*
                 * Clear all pending SP commands as we are going to reset the
                 * function anyway.
@@ -9647,7 +9728,6 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
                        wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
                        REG_WR(bp, vals->bmac_addr, wb_data[0]);
                        REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]);
-
                }
                BNX2X_DEV_INFO("Disable emac Rx\n");
                vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4;
@@ -9681,7 +9761,6 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
 
        if (mac_stopped)
                msleep(20);
-
 }
 
 #define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4))
@@ -9780,6 +9859,21 @@ static bool bnx2x_prev_is_path_marked(struct bnx2x *bp)
        return rc;
 }
 
+bool bnx2x_port_after_undi(struct bnx2x *bp)
+{
+       struct bnx2x_prev_path_list *entry;
+       bool val;
+
+       down(&bnx2x_prev_sem);
+
+       entry = bnx2x_prev_path_get_entry(bp);
+       val = !!(entry && (entry->undi & (1 << BP_PORT(bp))));
+
+       up(&bnx2x_prev_sem);
+
+       return val;
+}
+
 static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi)
 {
        struct bnx2x_prev_path_list *tmp_list;
@@ -9839,7 +9933,6 @@ static int bnx2x_do_flr(struct bnx2x *bp)
        u16 status;
        struct pci_dev *dev = bp->pdev;
 
-
        if (CHIP_IS_E1x(bp)) {
                BNX2X_DEV_INFO("FLR not supported in E1/E1H\n");
                return -EINVAL;
@@ -9986,7 +10079,6 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
 
                if (!timer_count)
                        BNX2X_ERR("Failed to empty BRB, hope for the best\n");
-
        }
 
        /* No packets are in the pipeline, path is ready for reset */
@@ -10036,7 +10128,6 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
 {
        int time_counter = 10;
        u32 rc, fw, hw_lock_reg, hw_lock_val;
-       struct bnx2x_prev_path_list *prev_list;
        BNX2X_DEV_INFO("Entering Previous Unload Flow\n");
 
        /* clear hw from errors which may have resulted from an interrupted
@@ -10049,7 +10140,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
                      (MISC_REG_DRIVER_CONTROL_1 + BP_FUNC(bp) * 8) :
                      (MISC_REG_DRIVER_CONTROL_7 + (BP_FUNC(bp) - 6) * 8);
 
-       hw_lock_val = (REG_RD(bp, hw_lock_reg));
+       hw_lock_val = REG_RD(bp, hw_lock_reg);
        if (hw_lock_val) {
                if (hw_lock_val & HW_LOCK_RESOURCE_NVRAM) {
                        BNX2X_DEV_INFO("Release Previously held NVRAM lock\n");
@@ -10064,7 +10155,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
 
        if (MCPR_ACCESS_LOCK_LOCK & REG_RD(bp, MCP_REG_MCPR_ACCESS_LOCK)) {
                BNX2X_DEV_INFO("Release previously held alr\n");
-               REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, 0);
+               bnx2x_release_alr(bp);
        }
 
        do {
@@ -10093,7 +10184,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
                        break;
                }
 
-               /* non-common reply from MCP night require looping */
+               /* non-common reply from MCP might require looping */
                rc = bnx2x_prev_unload_uncommon(bp);
                if (rc != BNX2X_PREV_WAIT_NEEDED)
                        break;
@@ -10107,8 +10198,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
        }
 
        /* Mark function if its port was used to boot from SAN */
-       prev_list = bnx2x_prev_path_get_entry(bp);
-       if (prev_list && (prev_list->undi & (1 << BP_PORT(bp))))
+       if (bnx2x_port_after_undi(bp))
                bp->link_params.feature_config_flags |=
                        FEATURE_CONFIG_BOOT_FROM_SAN;
 
@@ -10192,8 +10282,6 @@ static void bnx2x_get_common_hwinfo(struct bnx2x *bp)
 
        bnx2x_init_shmem(bp);
 
-
-
        bp->common.shmem2_base = REG_RD(bp, (BP_PATH(bp) ?
                                        MISC_REG_GENERIC_CR_1 :
                                        MISC_REG_GENERIC_CR_0));
@@ -10454,7 +10542,6 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
                if (!(bp->link_params.speed_cap_mask[idx] &
                                        PORT_HW_CFG_SPEED_CAPABILITY_D0_10G))
                        bp->port.supported[idx] &= ~SUPPORTED_10000baseT_Full;
-
        }
 
        BNX2X_DEV_INFO("supported 0x%x 0x%x\n", bp->port.supported[0],
@@ -10765,7 +10852,6 @@ void bnx2x_get_iscsi_info(struct bnx2x *bp)
         */
        if (!bp->cnic_eth_dev.max_iscsi_conn)
                bp->flags |= no_flags;
-
 }
 
 static void bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
@@ -10782,12 +10868,56 @@ static void bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
        bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
                MF_CFG_RD(bp, func_ext_config[func].fcoe_wwn_node_name_lower);
 }
+
+static int bnx2x_shared_fcoe_funcs(struct bnx2x *bp)
+{
+       u8 count = 0;
+
+       if (IS_MF(bp)) {
+               u8 fid;
+
+               /* iterate over absolute function ids for this path: */
+               for (fid = BP_PATH(bp); fid < E2_FUNC_MAX * 2; fid += 2) {
+                       if (IS_MF_SD(bp)) {
+                               u32 cfg = MF_CFG_RD(bp,
+                                                   func_mf_config[fid].config);
+
+                               if (!(cfg & FUNC_MF_CFG_FUNC_HIDE) &&
+                                   ((cfg & FUNC_MF_CFG_PROTOCOL_MASK) ==
+                                           FUNC_MF_CFG_PROTOCOL_FCOE))
+                                       count++;
+                       } else {
+                               u32 cfg = MF_CFG_RD(bp,
+                                                   func_ext_config[fid].
+                                                                     func_cfg);
+
+                               if ((cfg & MACP_FUNC_CFG_FLAGS_ENABLED) &&
+                                   (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD))
+                                       count++;
+                       }
+               }
+       } else { /* SF */
+               int port, port_cnt = CHIP_MODE_IS_4_PORT(bp) ? 2 : 1;
+
+               for (port = 0; port < port_cnt; port++) {
+                       u32 lic = SHMEM_RD(bp,
+                                          drv_lic_key[port].max_fcoe_conn) ^
+                                 FW_ENCODE_32BIT_PATTERN;
+                       if (lic)
+                               count++;
+               }
+       }
+
+       return count;
+}
+
 static void bnx2x_get_fcoe_info(struct bnx2x *bp)
 {
        int port = BP_PORT(bp);
        int func = BP_ABS_FUNC(bp);
        u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
                                drv_lic_key[port].max_fcoe_conn);
+       u8 num_fcoe_func = bnx2x_shared_fcoe_funcs(bp);
 
        if (!CNIC_SUPPORT(bp)) {
                bp->flags |= NO_FCOE_FLAG;
@@ -10801,9 +10931,10 @@ static void bnx2x_get_fcoe_info(struct bnx2x *bp)
 
        /* Calculate the number of maximum allowed FCoE tasks */
        bp->cnic_eth_dev.max_fcoe_exchanges = MAX_NUM_FCOE_TASKS_PER_ENGINE;
-       if (IS_MF(bp) || CHIP_MODE_IS_4_PORT(bp))
-               bp->cnic_eth_dev.max_fcoe_exchanges /=
-                                               MAX_FCOE_FUNCS_PER_ENGINE;
+
+       /* check if FCoE resources must be shared between different functions */
+       if (num_fcoe_func)
+               bp->cnic_eth_dev.max_fcoe_exchanges /= num_fcoe_func;
 
        /* Read the WWN: */
        if (!IS_MF(bp)) {
@@ -11031,7 +11162,7 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
        } else {
                bp->common.int_block = INT_BLOCK_IGU;
 
-               /* do not allow device reset during IGU info preocessing */
+               /* do not allow device reset during IGU info processing */
                bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
 
                val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
@@ -11110,7 +11241,7 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
                                E1H_FUNC_MAX * sizeof(struct drv_func_mb);
                /*
                 * get mf configuration:
-                * 1. existence of MF configuration
+                * 1. Existence of MF configuration
                 * 2. MAC address must be legal (check only upper bytes)
                 *    for  Switch-Independent mode;
                 *    OVLAN must be legal for Switch-Dependent mode
@@ -11384,7 +11515,6 @@ static int bnx2x_init_bp(struct bnx2x *bp)
        mutex_init(&bp->fw_mb_mutex);
        spin_lock_init(&bp->stats_lock);
 
-
        INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
        INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
        INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
@@ -11393,7 +11523,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
                if (rc)
                        return rc;
        } else {
-               random_ether_addr(bp->dev->dev_addr);
+               eth_zero_addr(bp->dev->dev_addr);
        }
 
        bnx2x_set_modes_bitmap(bp);
@@ -11417,7 +11547,6 @@ static int bnx2x_init_bp(struct bnx2x *bp)
                bnx2x_prev_unload(bp);
        }
 
-
        if (CHIP_REV_IS_FPGA(bp))
                dev_err(&bp->pdev->dev, "FPGA detected\n");
 
@@ -11489,7 +11618,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
 
        /* We need at least one default status block for slow-path events,
         * second status block for the L2 queue, and a third status block for
-        * CNIC if supproted.
+        * CNIC if supported.
         */
        if (CNIC_SUPPORT(bp))
                bp->min_msix_vec_cnt = 3;
@@ -11500,7 +11629,6 @@ static int bnx2x_init_bp(struct bnx2x *bp)
        return rc;
 }
 
-
 /****************************************************************************
 * General service functions
 ****************************************************************************/
@@ -11585,9 +11713,6 @@ static int bnx2x_close(struct net_device *dev)
        /* Unload the driver, release IRQs */
        bnx2x_nic_unload(bp, UNLOAD_CLOSE, false);
 
-       /* Power off */
-       bnx2x_set_power_state(bp, PCI_D3hot);
-
        return 0;
 }
 
@@ -11852,6 +11977,10 @@ static int bnx2x_validate_addr(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
+       /* query the bulletin board for mac address configured by the PF */
+       if (IS_VF(bp))
+               bnx2x_sample_bulletin(bp);
+
        if (!bnx2x_is_valid_ether_addr(bp, dev->dev_addr)) {
                BNX2X_ERR("Non-valid Ethernet address\n");
                return -EADDRNOTAVAIL;
@@ -11878,7 +12007,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
        .ndo_setup_tc           = bnx2x_setup_tc,
 #ifdef CONFIG_BNX2X_SRIOV
        .ndo_set_vf_mac         = bnx2x_set_vf_mac,
-       .ndo_set_vf_vlan        = bnx2x_set_vf_vlan,
+       .ndo_set_vf_vlan        = bnx2x_set_vf_vlan,
        .ndo_get_vf_config      = bnx2x_get_vf_config,
 #endif
 #ifdef NETDEV_FCOE_WWNN
@@ -12094,15 +12223,26 @@ err_out:
        return rc;
 }
 
-static void bnx2x_get_pcie_width_speed(struct bnx2x *bp, int *width, int *speed)
+static void bnx2x_get_pcie_width_speed(struct bnx2x *bp, int *width,
+                                      enum bnx2x_pci_bus_speed *speed)
 {
-       u32 val = 0;
+       u32 link_speed, val = 0;
 
        pci_read_config_dword(bp->pdev, PCICFG_LINK_CONTROL, &val);
        *width = (val & PCICFG_LINK_WIDTH) >> PCICFG_LINK_WIDTH_SHIFT;
 
-       /* return value of 1=2.5GHz 2=5GHz */
-       *speed = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
+       link_speed = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
+
+       switch (link_speed) {
+       case 3:
+               *speed = BNX2X_PCI_LINK_SPEED_8000;
+               break;
+       case 2:
+               *speed = BNX2X_PCI_LINK_SPEED_5000;
+               break;
+       default:
+               *speed = BNX2X_PCI_LINK_SPEED_2500;
+       }
 }
 
 static int bnx2x_check_firmware(struct bnx2x *bp)
@@ -12327,7 +12467,6 @@ static void bnx2x_release_firmware(struct bnx2x *bp)
        bp->firmware = NULL;
 }
 
-
 static struct bnx2x_func_sp_drv_ops bnx2x_func_sp_drv = {
        .init_hw_cmn_chip = bnx2x_init_hw_common_chip,
        .init_hw_cmn      = bnx2x_init_hw_common,
@@ -12465,7 +12604,8 @@ static int bnx2x_init_one(struct pci_dev *pdev,
 {
        struct net_device *dev = NULL;
        struct bnx2x *bp;
-       int pcie_width, pcie_speed;
+       int pcie_width;
+       enum bnx2x_pci_bus_speed pcie_speed;
        int rc, max_non_def_sbs;
        int rx_count, tx_count, rss_count, doorbell_size;
        int max_cos_est;
@@ -12605,7 +12745,6 @@ static int bnx2x_init_one(struct pci_dev *pdev,
        }
        BNX2X_DEV_INFO("device name after netdev register %s\n", dev->name);
 
-
        if (!NO_FCOE(bp)) {
                /* Add storage MAC address */
                rtnl_lock();
@@ -12617,15 +12756,15 @@ static int bnx2x_init_one(struct pci_dev *pdev,
        BNX2X_DEV_INFO("got pcie width %d and speed %d\n",
                       pcie_width, pcie_speed);
 
-       BNX2X_DEV_INFO(
-               "%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n",
-                   board_info[ent->driver_data].name,
-                   (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
-                   pcie_width,
-                   ((!CHIP_IS_E2(bp) && pcie_speed == 2) ||
-                    (CHIP_IS_E2(bp) && pcie_speed == 1)) ?
-                   "5GHz (Gen2)" : "2.5GHz",
-                   dev->base_addr, bp->pdev->irq, dev->dev_addr);
+       BNX2X_DEV_INFO("%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n",
+                      board_info[ent->driver_data].name,
+                      (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
+                      pcie_width,
+                      pcie_speed == BNX2X_PCI_LINK_SPEED_2500 ? "2.5GHz" :
+                      pcie_speed == BNX2X_PCI_LINK_SPEED_5000 ? "5.0GHz" :
+                      pcie_speed == BNX2X_PCI_LINK_SPEED_8000 ? "8.0GHz" :
+                      "Unknown",
+                      dev->base_addr, bp->pdev->irq, dev->dev_addr);
 
        return 0;
 
@@ -12647,17 +12786,11 @@ init_one_exit:
        return rc;
 }
 
-static void bnx2x_remove_one(struct pci_dev *pdev)
+static void __bnx2x_remove(struct pci_dev *pdev,
+                          struct net_device *dev,
+                          struct bnx2x *bp,
+                          bool remove_netdev)
 {
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct bnx2x *bp;
-
-       if (!dev) {
-               dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n");
-               return;
-       }
-       bp = netdev_priv(dev);
-
        /* Delete storage MAC address */
        if (!NO_FCOE(bp)) {
                rtnl_lock();
@@ -12670,7 +12803,15 @@ static void bnx2x_remove_one(struct pci_dev *pdev)
        bnx2x_dcbnl_update_applist(bp, true);
 #endif
 
-       unregister_netdev(dev);
+       /* Close the interface - either directly or implicitly */
+       if (remove_netdev) {
+               unregister_netdev(dev);
+       } else {
+               rtnl_lock();
+               if (netif_running(dev))
+                       bnx2x_close(dev);
+               rtnl_unlock();
+       }
 
        /* Power on: we can't let PCI layer write to us while we are in D3 */
        if (IS_PF(bp))
@@ -12692,6 +12833,12 @@ static void bnx2x_remove_one(struct pci_dev *pdev)
        if (IS_VF(bp))
                bnx2x_vfpf_release(bp);
 
+       /* Assumes no further PCIe PM changes will occur */
+       if (system_state == SYSTEM_POWER_OFF) {
+               pci_wake_from_d3(pdev, bp->wol);
+               pci_set_power_state(pdev, PCI_D3hot);
+       }
+
        if (bp->regview)
                iounmap(bp->regview);
 
@@ -12706,7 +12853,8 @@ static void bnx2x_remove_one(struct pci_dev *pdev)
        }
        bnx2x_free_mem_bp(bp);
 
-       free_netdev(dev);
+       if (remove_netdev)
+               free_netdev(dev);
 
        if (atomic_read(&pdev->enable_cnt) == 1)
                pci_release_regions(pdev);
@@ -12715,6 +12863,20 @@ static void bnx2x_remove_one(struct pci_dev *pdev)
        pci_set_drvdata(pdev, NULL);
 }
 
+static void bnx2x_remove_one(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct bnx2x *bp;
+
+       if (!dev) {
+               dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n");
+               return;
+       }
+       bp = netdev_priv(dev);
+
+       __bnx2x_remove(pdev, dev, bp, true);
+}
+
 static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
 {
        bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
@@ -12747,19 +12909,6 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
        return 0;
 }
 
-static void bnx2x_eeh_recover(struct bnx2x *bp)
-{
-       u32 val;
-
-       mutex_init(&bp->port.phy_mutex);
-
-
-       val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]);
-       if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
-               != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
-               BNX2X_ERR("BAD MCP validity signature\n");
-}
-
 /**
  * bnx2x_io_error_detected - called when PCI error is detected
  * @pdev: Pointer to PCI device
@@ -12828,6 +12977,10 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev)
 
        if (netif_running(dev)) {
                BNX2X_ERR("IO slot reset --> driver unload\n");
+
+               /* MCP should have been reset; Need to wait for validity */
+               bnx2x_init_shmem(bp);
+
                if (IS_PF(bp) && SHMEM2_HAS(bp, drv_capabilities_flag)) {
                        u32 v;
 
@@ -12849,7 +13002,7 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev)
 
                bnx2x_prev_unload(bp);
 
-               /* We should have resetted the engine, so It's fair to
+               /* We should have reseted the engine, so It's fair to
                 * assume the FW will no longer write to the bnx2x driver.
                 */
                bnx2x_squeeze_objects(bp);
@@ -12886,8 +13039,6 @@ static void bnx2x_io_resume(struct pci_dev *pdev)
 
        rtnl_lock();
 
-       bnx2x_eeh_recover(bp);
-
        bp->fw_seq = SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
                                                        DRV_MSG_SEQ_NUMBER_MASK;
 
@@ -12905,6 +13056,29 @@ static const struct pci_error_handlers bnx2x_err_handler = {
        .resume         = bnx2x_io_resume,
 };
 
+static void bnx2x_shutdown(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct bnx2x *bp;
+
+       if (!dev)
+               return;
+
+       bp = netdev_priv(dev);
+       if (!bp)
+               return;
+
+       rtnl_lock();
+       netif_device_detach(dev);
+       rtnl_unlock();
+
+       /* Don't remove the netdevice, as there are scenarios which will cause
+        * the kernel to hang, e.g., when trying to remove bnx2i while the
+        * rootfs is mounted from SAN.
+        */
+       __bnx2x_remove(pdev, dev, bp, false);
+}
+
 static struct pci_driver bnx2x_pci_driver = {
        .name        = DRV_MODULE_NAME,
        .id_table    = bnx2x_pci_tbl,
@@ -12916,6 +13090,7 @@ static struct pci_driver bnx2x_pci_driver = {
 #ifdef CONFIG_BNX2X_SRIOV
        .sriov_configure = bnx2x_sriov_configure,
 #endif
+       .shutdown    = bnx2x_shutdown,
 };
 
 static int __init bnx2x_init(void)
@@ -12941,11 +13116,12 @@ static int __init bnx2x_init(void)
 static void __exit bnx2x_cleanup(void)
 {
        struct list_head *pos, *q;
+
        pci_unregister_driver(&bnx2x_pci_driver);
 
        destroy_workqueue(bnx2x_wq);
 
-       /* Free globablly allocated resources */
+       /* Free globally allocated resources */
        list_for_each_safe(pos, q, &bnx2x_prev_list) {
                struct bnx2x_prev_path_list *tmp =
                        list_entry(pos, struct bnx2x_prev_path_list, list);
@@ -12968,7 +13144,7 @@ module_exit(bnx2x_cleanup);
  * @bp:                driver handle
  * @set:       set or clear the CAM entry
  *
- * This function will wait until the ramdord completion returns.
+ * This function will wait until the ramrod completion returns.
  * Return 0 if success, -ENODEV if ramrod doesn't return.
  */
 static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp)
@@ -12996,7 +13172,6 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
        BUG_ON(bp->cnic_spq_pending < count);
        bp->cnic_spq_pending -= count;
 
-
        for (; bp->cnic_kwq_pending; bp->cnic_kwq_pending--) {
                u16 type =  (le16_to_cpu(bp->cnic_kwq_cons->hdr.type)
                                & SPE_HDR_CONN_TYPE) >>
@@ -13169,7 +13344,6 @@ static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err)
        bnx2x_cnic_sp_post(bp, 0);
 }
 
-
 /* Called with netif_addr_lock_bh() taken.
  * Sets an rx_mode config for an iSCSI ETH client.
  * Doesn't block.
@@ -13210,7 +13384,6 @@ static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start)
        }
 }
 
-
 static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
 {
        struct bnx2x *bp = netdev_priv(dev);
@@ -13398,7 +13571,6 @@ void bnx2x_setup_cnic_info(struct bnx2x *bp)
 {
        struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
 
-
        cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) +
                             bnx2x_cid_ilt_lines(bp);
        cp->starting_cid = bnx2x_cid_ilt_lines(bp) * ILT_PAGE_CIDS;
@@ -13434,7 +13606,6 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
                        BNX2X_ERR("CNIC-related load failed\n");
                        return rc;
                }
-
        }
 
        bp->cnic_enabled = true;
index d22bc40091ec47738a0132dd549c095645f90702..8e627b886d7b1b401676b3e10f0c6cb573c3e78d 100644 (file)
@@ -35,6 +35,8 @@
 #define ATC_REG_ATC_INT_STS_CLR                                         0x1101c0
 /* [RW 5] Parity mask register #0 read/write */
 #define ATC_REG_ATC_PRTY_MASK                                   0x1101d8
+/* [R 5] Parity register #0 read */
+#define ATC_REG_ATC_PRTY_STS                                    0x1101cc
 /* [RC 5] Parity register #0 read clear */
 #define ATC_REG_ATC_PRTY_STS_CLR                                0x1101d0
 /* [RW 19] Interrupt mask register #0 read/write */
 #define PBF_REG_PBF_INT_STS                                     0x1401c8
 /* [RW 20] Parity mask register #0 read/write */
 #define PBF_REG_PBF_PRTY_MASK                                   0x1401e4
+/* [R 28] Parity register #0 read */
+#define PBF_REG_PBF_PRTY_STS                                    0x1401d8
 /* [RC 20] Parity register #0 read clear */
 #define PBF_REG_PBF_PRTY_STS_CLR                                0x1401dc
 /* [RW 16] The Ethernet type value for L2 tag 0 */
 #define TM_REG_TM_INT_STS                                       0x1640f0
 /* [RW 7] Parity mask register #0 read/write */
 #define TM_REG_TM_PRTY_MASK                                     0x16410c
+/* [R 7] Parity register #0 read */
+#define TM_REG_TM_PRTY_STS                                      0x164100
 /* [RC 7] Parity register #0 read clear */
 #define TM_REG_TM_PRTY_STS_CLR                                  0x164104
 /* [RW 8] The event id for aggregated interrupt 0 */
index 32a9609cc98bcd36e56b0193bba3a3508424f5cb..8f03c984550f328c88764d83f04813b344445b1d 100644 (file)
@@ -35,9 +35,9 @@
 /**
  * bnx2x_exe_queue_init - init the Exe Queue object
  *
- * @o:         poiter to the object
+ * @o:         pointer to the object
  * @exe_len:   length
- * @owner:     poiter to the owner
+ * @owner:     pointer to the owner
  * @validate:  validate function pointer
  * @optimize:  optimize function pointer
  * @exec:      execute function pointer
@@ -142,7 +142,6 @@ free_and_exit:
        spin_unlock_bh(&o->lock);
 
        return rc;
-
 }
 
 static inline void __bnx2x_exe_queue_reset_pending(
@@ -163,13 +162,11 @@ static inline void __bnx2x_exe_queue_reset_pending(
 static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp,
                                                 struct bnx2x_exe_queue_obj *o)
 {
-
        spin_lock_bh(&o->lock);
 
        __bnx2x_exe_queue_reset_pending(bp, o);
 
        spin_unlock_bh(&o->lock);
-
 }
 
 /**
@@ -179,7 +176,7 @@ static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp,
  * @o:                 queue
  * @ramrod_flags:      flags
  *
- * (Atomicy is ensured using the exe_queue->lock).
+ * (Atomicity is ensured using the exe_queue->lock).
  */
 static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
                                       struct bnx2x_exe_queue_obj *o,
@@ -192,8 +189,7 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
 
        spin_lock_bh(&o->lock);
 
-       /*
-        * Next step should not be performed until the current is finished,
+       /* Next step should not be performed until the current is finished,
         * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
         * properly clear object internals without sending any command to the FW
         * which also implies there won't be any completion to clear the
@@ -209,8 +205,7 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
                }
        }
 
-       /*
-        * Run through the pending commands list and create a next
+       /* Run through the pending commands list and create a next
         * execution chunk.
         */
        while (!list_empty(&o->exe_queue)) {
@@ -220,8 +215,7 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
 
                if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
                        cur_len += elem->cmd_len;
-                       /*
-                        * Prevent from both lists being empty when moving an
+                       /* Prevent from both lists being empty when moving an
                         * element. This will allow the call of
                         * bnx2x_exe_queue_empty() without locking.
                         */
@@ -241,14 +235,12 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
 
        rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags);
        if (rc < 0)
-               /*
-                *  In case of an error return the commands back to the queue
-                *  and reset the pending_comp.
+               /* In case of an error return the commands back to the queue
+                * and reset the pending_comp.
                 */
                list_splice_init(&o->pending_comp, &o->exe_queue);
        else if (!rc)
-               /*
-                * If zero is returned, means there are no outstanding pending
+               /* If zero is returned, means there are no outstanding pending
                 * completions and we may dismiss the pending list.
                 */
                __bnx2x_exe_queue_reset_pending(bp, o);
@@ -308,7 +300,6 @@ static inline int bnx2x_state_wait(struct bnx2x *bp, int state,
        /* can take a while if any port is running */
        int cnt = 5000;
 
-
        if (CHIP_REV_IS_EMUL(bp))
                cnt *= 20;
 
@@ -456,7 +447,6 @@ static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
                        DP(BNX2X_MSG_SP, "copied element number %d to address %p element was:\n",
                           counter, next);
                        next += stride + size;
-
                }
        }
        return counter * ETH_ALEN;
@@ -518,7 +508,6 @@ static int bnx2x_check_vlan_mac_add(struct bnx2x *bp,
        return 0;
 }
 
-
 /* check_del() callbacks */
 static struct bnx2x_vlan_mac_registry_elem *
        bnx2x_check_mac_del(struct bnx2x *bp,
@@ -609,7 +598,6 @@ static bool bnx2x_check_move_always_err(
        return false;
 }
 
-
 static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
 {
        struct bnx2x_raw_obj *raw = &o->raw;
@@ -626,7 +614,6 @@ 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)
 {
@@ -693,7 +680,7 @@ static inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp,
  *
  * @cid:       connection id
  * @type:      BNX2X_FILTER_XXX_PENDING
- * @hdr:       poiter to header to setup
+ * @hdr:       pointer to header to setup
  * @rule_cnt:
  *
  * currently we always configure one rule and echo field to contain a CID and an
@@ -707,7 +694,6 @@ static inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type,
        hdr->rule_cnt = (u8)rule_cnt;
 }
 
-
 /* hw_config() callbacks */
 static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
                                 struct bnx2x_vlan_mac_obj *o,
@@ -723,8 +709,7 @@ static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
        unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags;
        u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac;
 
-       /*
-        * Set LLH CAM entry: currently only iSCSI and ETH macs are
+       /* Set LLH CAM entry: currently only iSCSI and ETH macs are
         * relevant. In addition, current implementation is tuned for a
         * single ETH MAC.
         *
@@ -879,8 +864,7 @@ static void bnx2x_set_one_mac_e1x(struct bnx2x *bp,
        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,
+       /* 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) ?
@@ -960,7 +944,6 @@ static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
        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));
@@ -969,7 +952,7 @@ static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
        bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
                                      &rule_entry->pair.header);
 
-       /* Set VLAN and MAC themselvs */
+       /* 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,
@@ -1021,8 +1004,7 @@ static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
        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,
+       /* 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) ?
@@ -1046,7 +1028,7 @@ static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
  *
  * @bp:                device handle
  * @p:         command parameters
- * @ppos:      pointer to the cooky
+ * @ppos:      pointer to the cookie
  *
  * reconfigure next MAC/VLAN/VLAN-MAC element from the
  * previously configured elements list.
@@ -1054,7 +1036,7 @@ static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
  * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is        taken
  * into an account
  *
- * pointer to the cooky  - that should be given back in the next call to make
+ * pointer to the cookie  - that should be given back in the next call to make
  * function handle the next element. If *ppos is set to NULL it will restart the
  * iterator. If returned *ppos == NULL this means that the last element has been
  * handled.
@@ -1102,8 +1084,7 @@ static int bnx2x_vlan_mac_restore(struct bnx2x *bp,
        return bnx2x_config_vlan_mac(bp, p);
 }
 
-/*
- * bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a
+/* bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a
  * pointer to an element with a specific criteria and NULL if such an element
  * hasn't been found.
  */
@@ -1187,8 +1168,7 @@ static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp,
                return rc;
        }
 
-       /*
-        * Check if there is a pending ADD command for this
+       /* Check if there is a pending ADD command for this
         * MAC/VLAN/VLAN-MAC. Return an error if there is.
         */
        if (exeq->get(exeq, elem)) {
@@ -1196,8 +1176,7 @@ static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp,
                return -EEXIST;
        }
 
-       /*
-        * TODO: Check the pending MOVE from other objects where this
+       /* TODO: Check the pending MOVE from other objects where this
         * object is a destination object.
         */
 
@@ -1240,8 +1219,7 @@ static inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp,
                return -EEXIST;
        }
 
-       /*
-        * Check if there are pending DEL or MOVE commands for this
+       /* Check if there are pending DEL or MOVE commands for this
         * MAC/VLAN/VLAN-MAC. Return an error if so.
         */
        memcpy(&query_elem, elem, sizeof(query_elem));
@@ -1292,8 +1270,7 @@ static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp,
        struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue;
        struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue;
 
-       /*
-        * Check if we can perform this operation based on the current registry
+       /* Check if we can perform this operation based on the current registry
         * state.
         */
        if (!src_o->check_move(bp, src_o, dest_o,
@@ -1302,8 +1279,7 @@ static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp,
                return -EINVAL;
        }
 
-       /*
-        * Check if there is an already pending DEL or MOVE command for the
+       /* Check if there is an already pending DEL or MOVE command for the
         * source object or ADD command for a destination object. Return an
         * error if so.
         */
@@ -1392,7 +1368,7 @@ static int bnx2x_remove_vlan_mac(struct bnx2x *bp,
 }
 
 /**
- * bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
+ * bnx2x_wait_vlan_mac - passively wait for 5 seconds until all work completes.
  *
  * @bp:                device handle
  * @o:         bnx2x_vlan_mac_obj
@@ -1550,9 +1526,8 @@ static inline int bnx2x_vlan_mac_get_registry_elem(
 
                /* Get a new CAM offset */
                if (!o->get_cam_offset(o, &reg_elem->cam_offset)) {
-                       /*
-                        * This shell never happen, because we have checked the
-                        * CAM availiability in the 'validate'.
+                       /* This shall never happen, because we have checked the
+                        * CAM availability in the 'validate'.
                         */
                        WARN_ON(1);
                        kfree(reg_elem);
@@ -1599,8 +1574,7 @@ static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
        struct bnx2x_vlan_mac_registry_elem *reg_elem;
        enum bnx2x_vlan_mac_cmd cmd;
 
-       /*
-        * If DRIVER_ONLY execution is requested, cleanup a registry
+       /* If DRIVER_ONLY execution is requested, cleanup a registry
         * and exit. Otherwise send a ramrod to FW.
         */
        if (!drv_only) {
@@ -1609,11 +1583,10 @@ static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
                /* Set pending */
                r->set_pending(r);
 
-               /* Fill tha ramrod data */
+               /* Fill the ramrod data */
                list_for_each_entry(elem, exe_chunk, link) {
                        cmd = elem->cmd_data.vlan_mac.cmd;
-                       /*
-                        * We will add to the target object in MOVE command, so
+                       /* We will add to the target object in MOVE command, so
                         * change the object for a CAM search.
                         */
                        if (cmd == BNX2X_VLAN_MAC_MOVE)
@@ -1646,12 +1619,11 @@ static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
                                idx++;
                }
 
-               /*
-                *  No need for an explicit memory barrier here as long we would
-                *  need to ensure the ordering of writing to the SPQ element
-                *  and updating of the SPQ producer which involves a memory
-                *  read and we will have to put a full memory barrier there
-                *  (inside bnx2x_sp_post()).
+               /* No need for an explicit memory barrier here as long we would
+                * need to ensure the ordering of writing to the SPQ element
+                * and updating of the SPQ producer which involves a memory
+                * read and we will have to put a full memory barrier there
+                * (inside bnx2x_sp_post()).
                 */
 
                rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid,
@@ -1766,8 +1738,7 @@ int bnx2x_config_vlan_mac(
                        return rc;
        }
 
-       /*
-        * If nothing will be executed further in this iteration we want to
+       /* If nothing will be executed further in this iteration we want to
         * return PENDING if there are pending commands
         */
        if (!bnx2x_exe_queue_empty(&o->exe_queue))
@@ -1786,13 +1757,11 @@ int bnx2x_config_vlan_mac(
                        return rc;
        }
 
-       /*
-        * RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
+       /* RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
         * then user want to wait until the last command is done.
         */
        if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
-               /*
-                * Wait maximum for the current exe_queue length iterations plus
+               /* Wait maximum for the current exe_queue length iterations plus
                 * one (for the current pending command).
                 */
                int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1;
@@ -1818,8 +1787,6 @@ int bnx2x_config_vlan_mac(
        return rc;
 }
 
-
-
 /**
  * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec
  *
@@ -1829,7 +1796,7 @@ int bnx2x_config_vlan_mac(
  * @ramrod_flags:      execution flags to be used for this deletion
  *
  * if the last operation has completed successfully and there are no
- * moreelements left, positive value if the last operation has completed
+ * more elements left, positive value if the last operation has completed
  * successfully and there are more previously configured elements, negative
  * value is current operation has failed.
  */
@@ -1870,8 +1837,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        p.ramrod_flags = *ramrod_flags;
        p.user_req.cmd = BNX2X_VLAN_MAC_DEL;
 
-       /*
-        * Add all but the last VLAN-MAC to the execution queue without actually
+       /* Add all but the last VLAN-MAC to the execution queue without actually
         * execution anything.
         */
        __clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags);
@@ -1934,7 +1900,6 @@ static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o,
                           state, pstate, type);
 }
 
-
 void bnx2x_init_mac_obj(struct bnx2x *bp,
                        struct bnx2x_vlan_mac_obj *mac_obj,
                        u8 cl_id, u32 cid, u8 func_id, void *rdata,
@@ -2048,8 +2013,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
        /* 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
+       /* 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.
         */
@@ -2092,7 +2056,6 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
                                     bnx2x_execute_vlan_mac,
                                     bnx2x_exeq_get_vlan_mac);
        }
-
 }
 
 /* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
@@ -2117,12 +2080,12 @@ static int bnx2x_set_rx_mode_e1x(struct bnx2x *bp,
        struct tstorm_eth_mac_filter_config *mac_filters =
                (struct tstorm_eth_mac_filter_config *)p->rdata;
 
-       /* initial seeting is drop-all */
+       /* initial setting is drop-all */
        u8 drop_all_ucast = 1, drop_all_mcast = 1;
        u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
        u8 unmatched_unicast = 0;
 
-    /* In e1x there we only take into account rx acceot flag since tx switching
+    /* In e1x there we only take into account rx accept flag since tx switching
      * isn't enabled. */
        if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags))
                /* accept matched ucast */
@@ -2245,7 +2208,6 @@ static inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp,
        }
 
        cmd->state = cpu_to_le16(state);
-
 }
 
 static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
@@ -2286,9 +2248,7 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
                                               false);
        }
 
-
-       /*
-        * If FCoE Queue configuration has been requested configure the Rx and
+       /* If FCoE Queue configuration has been requested configure the Rx and
         * internal switching modes for this queue in separate rules.
         *
         * FCoE queue shell never be set to ACCEPT_ALL packets of any sort:
@@ -2324,8 +2284,7 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
                }
        }
 
-       /*
-        * Set the ramrod header (most importantly - number of rules to
+       /* Set the ramrod header (most importantly - number of rules to
         * configure).
         */
        bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx);
@@ -2334,12 +2293,11 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
                         data->header.rule_cnt, p->rx_accept_flags,
                         p->tx_accept_flags);
 
-       /*
-        *  No need for an explicit memory barrier here as long we would
-        *  need to ensure the ordering of writing to the SPQ element
-        *  and updating of the SPQ producer which involves a memory
-        *  read and we will have to put a full memory barrier there
-        *  (inside bnx2x_sp_post()).
+       /* No need for an explicit memory barrier here as long we would
+        * need to ensure the ordering of writing to the SPQ element
+        * and updating of the SPQ producer which involves a memory
+        * read and we will have to put a full memory barrier there
+        * (inside bnx2x_sp_post()).
         */
 
        /* Send a ramrod */
@@ -2476,7 +2434,7 @@ static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
                cur_mac = (struct bnx2x_mcast_mac_elem *)
                          ((u8 *)new_cmd + sizeof(*new_cmd));
 
-               /* Push the MACs of the current command into the pendig command
+               /* Push the MACs of the current command into the pending command
                 * MACs list: FIFO
                 */
                list_for_each_entry(pos, &p->mcast_list, link) {
@@ -2909,7 +2867,6 @@ static int bnx2x_mcast_validate_e2(struct bnx2x *bp,
        default:
                BNX2X_ERR("Unknown command: %d\n", cmd);
                return -EINVAL;
-
        }
 
        /* Increase the total number of MACs pending to be configured */
@@ -3034,20 +2991,18 @@ static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
        if (!o->total_pending_num)
                bnx2x_mcast_refresh_registry_e2(bp, o);
 
-       /*
-        * If CLEAR_ONLY was requested - don't send a ramrod and clear
+       /* If CLEAR_ONLY was requested - don't send a ramrod and clear
         * RAMROD_PENDING status immediately.
         */
        if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
                raw->clear_pending(raw);
                return 0;
        } else {
-               /*
-                *  No need for an explicit memory barrier here as long we would
-                *  need to ensure the ordering of writing to the SPQ element
-                *  and updating of the SPQ producer which involves a memory
-                *  read and we will have to put a full memory barrier there
-                *  (inside bnx2x_sp_post()).
+               /* No need for an explicit memory barrier here as long we would
+                * need to ensure the ordering of writing to the SPQ element
+                * and updating of the SPQ producer which involves a memory
+                * read and we will have to put a full memory barrier there
+                * (inside bnx2x_sp_post()).
                 */
 
                /* Send a ramrod */
@@ -3121,7 +3076,7 @@ static inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp,
        }
 }
 
-/* On 57711 we write the multicast MACs' aproximate match
+/* On 57711 we write the multicast MACs' approximate match
  * table by directly into the TSTORM's internal RAM. So we don't
  * really need to handle any tricks to make it work.
  */
@@ -3223,7 +3178,6 @@ static int bnx2x_mcast_validate_e1(struct bnx2x *bp,
        default:
                BNX2X_ERR("Unknown command: %d\n", cmd);
                return -EINVAL;
-
        }
 
        /* We want to ensure that commands are executed one by one for 57710.
@@ -3245,7 +3199,7 @@ static void bnx2x_mcast_revert_e1(struct bnx2x *bp,
 
        /* If current command hasn't been handled yet and we are
         * here means that it's meant to be dropped and we have to
-        * update the number of outstandling MACs accordingly.
+        * update the number of outstanding MACs accordingly.
         */
        if (p->mcast_list_len)
                o->total_pending_num -= o->max_cmd_len;
@@ -3342,7 +3296,6 @@ static inline int bnx2x_mcast_handle_restore_cmd_e1(
        return -1;
 }
 
-
 static inline int bnx2x_mcast_handle_pending_cmds_e1(
        struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p)
 {
@@ -3352,7 +3305,6 @@ static inline int bnx2x_mcast_handle_pending_cmds_e1(
        union bnx2x_mcast_config_data cfg_data = {NULL};
        int cnt = 0;
 
-
        /* If nothing to be done - return */
        if (list_empty(&o->pending_cmds_head))
                return 0;
@@ -3523,20 +3475,18 @@ static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
        if (rc)
                return rc;
 
-       /*
-        * If CLEAR_ONLY was requested - don't send a ramrod and clear
+       /* If CLEAR_ONLY was requested - don't send a ramrod and clear
         * RAMROD_PENDING status immediately.
         */
        if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
                raw->clear_pending(raw);
                return 0;
        } else {
-               /*
-                *  No need for an explicit memory barrier here as long we would
-                *  need to ensure the ordering of writing to the SPQ element
-                *  and updating of the SPQ producer which involves a memory
-                *  read and we will have to put a full memory barrier there
-                *  (inside bnx2x_sp_post()).
+               /* No need for an explicit memory barrier here as long we would
+                * need to ensure the ordering of writing to the SPQ element
+                * and updating of the SPQ producer which involves a memory
+                * read and we will have to put a full memory barrier there
+                * (inside bnx2x_sp_post()).
                 */
 
                /* Send a ramrod */
@@ -3550,7 +3500,6 @@ static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
                /* Ramrod completion is pending */
                return 1;
        }
-
 }
 
 static int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o)
@@ -3848,7 +3797,6 @@ static bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o,
        return true;
 }
 
-
 static bool bnx2x_credit_pool_get_entry(
        struct bnx2x_credit_pool_obj *o,
        int *offset)
@@ -3999,8 +3947,7 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
 
        } else {
 
-               /*
-                * CAM credit is equaly divided between all active functions
+               /* CAM credit is equaly divided between all active functions
                 * on the PATH.
                 */
                if ((func_num > 0)) {
@@ -4009,8 +3956,7 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
                        else
                                cam_sz = BNX2X_CAM_SIZE_EMUL;
 
-                       /*
-                        * No need for CAM entries handling for 57712 and
+                       /* No need for CAM entries handling for 57712 and
                         * newer.
                         */
                        bnx2x_init_credit_pool(p, -1, cam_sz);
@@ -4018,7 +3964,6 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
                        /* this should never happen! Block MAC operations. */
                        bnx2x_init_credit_pool(p, 0, 0);
                }
-
        }
 }
 
@@ -4028,14 +3973,12 @@ void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
                                 u8 func_num)
 {
        if (CHIP_IS_E1x(bp)) {
-               /*
-                * There is no VLAN credit in HW on 57710 and 57711 only
+               /* There is no VLAN credit in HW on 57710 and 57711 only
                 * MAC / MAC-VLAN can be set
                 */
                bnx2x_init_credit_pool(p, 0, -1);
        } else {
-               /*
-                * CAM credit is equaly divided between all active functions
+               /* CAM credit is equally divided between all active functions
                 * on the PATH.
                 */
                if (func_num > 0) {
@@ -4051,7 +3994,7 @@ void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
 /**
  * bnx2x_debug_print_ind_table - prints the indirection table configuration.
  *
- * @bp:                driver hanlde
+ * @bp:                driver handle
  * @p:         pointer to rss configuration
  *
  * Prints it when NETIF_MSG_IFUP debug level is configured.
@@ -4164,12 +4107,11 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
                data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
        }
 
-       /*
-        *  No need for an explicit memory barrier here as long we would
-        *  need to ensure the ordering of writing to the SPQ element
-        *  and updating of the SPQ producer which involves a memory
-        *  read and we will have to put a full memory barrier there
-        *  (inside bnx2x_sp_post()).
+       /* No need for an explicit memory barrier here as long we would
+        * need to ensure the ordering of writing to the SPQ element
+        * and updating of the SPQ producer which involves a memory
+        * read and we will have to put a full memory barrier there
+        * (inside bnx2x_sp_post()).
         */
 
        /* Send a ramrod */
@@ -4215,7 +4157,6 @@ int bnx2x_config_rss(struct bnx2x *bp,
        return rc;
 }
 
-
 void bnx2x_init_rss_config_obj(struct bnx2x *bp,
                               struct bnx2x_rss_config_obj *rss_obj,
                               u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
@@ -4288,7 +4229,6 @@ int bnx2x_queue_state_change(struct bnx2x *bp,
        return !!test_bit(pending_bit, pending);
 }
 
-
 static int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj,
                                   struct bnx2x_queue_state_params *params)
 {
@@ -4337,7 +4277,7 @@ static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
        }
 
        if (o->next_tx_only >= o->max_cos)
-               /* >= becuase tx only must always be smaller than cos since the
+               /* >= because tx only must always be smaller than cos since the
                 * primary connection supports COS 0
                 */
                BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
@@ -4403,7 +4343,6 @@ static void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
        gen_data->mtu = cpu_to_le16(params->mtu);
        gen_data->func_id = o->func_id;
 
-
        gen_data->cos = params->cos;
 
        gen_data->traffic_type =
@@ -4530,7 +4469,6 @@ static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o,
                cpu_to_le16(params->silent_removal_value);
        rx_data->silent_vlan_mask =
                cpu_to_le16(params->silent_removal_mask);
-
 }
 
 /* initialize the general, tx and rx parts of a queue object */
@@ -4652,12 +4590,11 @@ static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
        /* Fill the ramrod data */
        bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
 
-       /*
-        *  No need for an explicit memory barrier here as long we would
-        *  need to ensure the ordering of writing to the SPQ element
-        *  and updating of the SPQ producer which involves a memory
-        *  read and we will have to put a full memory barrier there
-        *  (inside bnx2x_sp_post()).
+       /* No need for an explicit memory barrier here as long we would
+        * need to ensure the ordering of writing to the SPQ element
+        * and updating of the SPQ producer which involves a memory
+        * read and we will have to put a full memory barrier there
+        * (inside bnx2x_sp_post()).
         */
 
        return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
@@ -4681,12 +4618,11 @@ static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
        bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
        bnx2x_q_fill_setup_data_e2(bp, params, rdata);
 
-       /*
-        *  No need for an explicit memory barrier here as long we would
-        *  need to ensure the ordering of writing to the SPQ element
-        *  and updating of the SPQ producer which involves a memory
-        *  read and we will have to put a full memory barrier there
-        *  (inside bnx2x_sp_post()).
+       /* No need for an explicit memory barrier here as long we would
+        * need to ensure the ordering of writing to the SPQ element
+        * and updating of the SPQ producer which involves a memory
+        * read and we will have to put a full memory barrier there
+        * (inside bnx2x_sp_post()).
         */
 
        return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
@@ -4706,7 +4642,6 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
                &params->params.tx_only;
        u8 cid_index = tx_only_params->cid_index;
 
-
        if (cid_index >= o->max_cos) {
                BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
                          o->cl_id, cid_index);
@@ -4727,12 +4662,11 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
                         o->cids[cid_index], rdata->general.client_id,
                         rdata->general.sp_client_id, rdata->general.cos);
 
-       /*
-        *  No need for an explicit memory barrier here as long we would
-        *  need to ensure the ordering of writing to the SPQ element
-        *  and updating of the SPQ producer which involves a memory
-        *  read and we will have to put a full memory barrier there
-        *  (inside bnx2x_sp_post()).
+       /* No need for an explicit memory barrier here as long we would
+        * need to ensure the ordering of writing to the SPQ element
+        * and updating of the SPQ producer which involves a memory
+        * read and we will have to put a full memory barrier there
+        * (inside bnx2x_sp_post()).
         */
 
        return bnx2x_sp_post(bp, ramrod, o->cids[cid_index],
@@ -4761,7 +4695,7 @@ static void bnx2x_q_fill_update_data(struct bnx2x *bp,
                test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
                         &params->update_flags);
 
-       /* Outer VLAN sripping */
+       /* Outer VLAN stripping */
        data->outer_vlan_removal_enable_flg =
                test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, &params->update_flags);
        data->outer_vlan_removal_change_flg =
@@ -4816,19 +4750,17 @@ static inline int bnx2x_q_send_update(struct bnx2x *bp,
                return -EINVAL;
        }
 
-
        /* Clear the ramrod data */
        memset(rdata, 0, sizeof(*rdata));
 
        /* Fill the ramrod data */
        bnx2x_q_fill_update_data(bp, o, update_params, rdata);
 
-       /*
-        *  No need for an explicit memory barrier here as long we would
-        *  need to ensure the ordering of writing to the SPQ element
-        *  and updating of the SPQ producer which involves a memory
-        *  read and we will have to put a full memory barrier there
-        *  (inside bnx2x_sp_post()).
+       /* No need for an explicit memory barrier here as long we would
+        * need to ensure the ordering of writing to the SPQ element
+        * and updating of the SPQ producer which involves a memory
+        * read and we will have to put a full memory barrier there
+        * (inside bnx2x_sp_post()).
         */
 
        return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
@@ -5038,8 +4970,7 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp,
                 &params->params.update;
        u8 next_tx_only = o->num_tx_only;
 
-       /*
-        * Forget all pending for completion commands if a driver only state
+       /* Forget all pending for completion commands if a driver only state
         * transition has been requested.
         */
        if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
@@ -5047,8 +4978,7 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp,
                o->next_state = BNX2X_Q_STATE_MAX;
        }
 
-       /*
-        * Don't allow a next state transition if we are in the middle of
+       /* Don't allow a next state transition if we are in the middle of
         * the previous one.
         */
        if (o->pending) {
@@ -5257,8 +5187,7 @@ enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
        if (o->pending)
                return BNX2X_F_STATE_MAX;
 
-       /*
-        * unsure the order of reading of o->pending and o->state
+       /* unsure the order of reading of o->pending and o->state
         * o->pending should be read first
         */
        rmb();
@@ -5356,8 +5285,7 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
        enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
        enum bnx2x_func_cmd cmd = params->cmd;
 
-       /*
-        * Forget all pending for completion commands if a driver only state
+       /* Forget all pending for completion commands if a driver only state
         * transition has been requested.
         */
        if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
@@ -5365,8 +5293,7 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
                o->next_state = BNX2X_F_STATE_MAX;
        }
 
-       /*
-        * Don't allow a next state transition if we are in the middle of
+       /* Don't allow a next state transition if we are in the middle of
         * the previous one.
         */
        if (o->pending)
@@ -5539,7 +5466,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp,
                goto init_err;
        }
 
-       /* Handle the beginning of COMMON_XXX pases separatelly... */
+       /* Handle the beginning of COMMON_XXX pases separately... */
        switch (load_code) {
        case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
                rc = bnx2x_func_init_cmn_chip(bp, drv);
@@ -5573,7 +5500,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp,
 init_err:
        drv->gunzip_end(bp);
 
-       /* In case of success, complete the comand immediatelly: no ramrods
+       /* In case of success, complete the command immediately: no ramrods
         * have been sent.
         */
        if (!rc)
@@ -5598,7 +5525,7 @@ static inline void bnx2x_func_reset_func(struct bnx2x *bp,
 }
 
 /**
- * bnx2x_func_reset_port - reser HW at port stage
+ * bnx2x_func_reset_port - reset HW at port stage
  *
  * @bp:                device handle
  * @drv:
@@ -5620,7 +5547,7 @@ static inline void bnx2x_func_reset_port(struct bnx2x *bp,
 }
 
 /**
- * bnx2x_func_reset_cmn - reser HW at common stage
+ * bnx2x_func_reset_cmn - reset HW at common stage
  *
  * @bp:                device handle
  * @drv:
@@ -5636,7 +5563,6 @@ static inline void bnx2x_func_reset_cmn(struct bnx2x *bp,
        drv->reset_hw_cmn(bp);
 }
 
-
 static inline int bnx2x_func_hw_reset(struct bnx2x *bp,
                                      struct bnx2x_func_state_params *params)
 {
@@ -5663,7 +5589,7 @@ static inline int bnx2x_func_hw_reset(struct bnx2x *bp,
                break;
        }
 
-       /* Complete the comand immediatelly: no ramrods have been sent. */
+       /* Complete the command immediately: no ramrods have been sent. */
        o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET);
 
        return 0;
index 43c00bc84a08826368d58e6253f3070a37118a68..798dfe9967336fedc4a5e07806c7216c83a955ed 100644 (file)
@@ -34,8 +34,7 @@ enum {
        RAMROD_RESTORE,
         /* Execute the next command now */
        RAMROD_EXEC,
-       /*
-        * Don't add a new command and continue execution of posponed
+       /* Don't add a new command and continue execution of postponed
         * commands. If not set a new command will be added to the
         * pending commands list.
         */
@@ -129,8 +128,7 @@ enum bnx2x_vlan_mac_cmd {
 struct bnx2x_vlan_mac_data {
        /* Requested command: BNX2X_VLAN_MAC_XX */
        enum bnx2x_vlan_mac_cmd cmd;
-       /*
-        * used to contain the data related vlan_mac_flags bits from
+       /* used to contain the data related vlan_mac_flags bits from
         * ramrod parameters.
         */
        unsigned long vlan_mac_flags;
@@ -190,14 +188,10 @@ typedef struct bnx2x_exeq_elem *
                                     struct bnx2x_exeq_elem *elem);
 
 struct bnx2x_exe_queue_obj {
-       /*
-        * Commands pending for an execution.
-        */
+       /* Commands pending for an execution. */
        struct list_head        exe_queue;
 
-       /*
-        * Commands pending for an completion.
-        */
+       /* Commands pending for an completion. */
        struct list_head        pending_comp;
 
        spinlock_t              lock;
@@ -245,14 +239,13 @@ struct bnx2x_exe_queue_obj {
 };
 /***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
 /*
- * Element in the VLAN_MAC registry list having all currenty configured
+ * Element in the VLAN_MAC registry list having all currently configured
  * rules.
  */
 struct bnx2x_vlan_mac_registry_elem {
        struct list_head        link;
 
-       /*
-        * Used to store the cam offset used for the mac/vlan/vlan-mac.
+       /* Used to store the cam offset used for the mac/vlan/vlan-mac.
         * Relevant for 57710 and 57711 only. VLANs and MACs share the
         * same CAM for these chips.
         */
@@ -310,7 +303,7 @@ struct bnx2x_vlan_mac_obj {
         * @param n number of elements to get
         * @param buf buffer preallocated by caller into which elements
         *            will be copied. Note elements are 4-byte aligned
-        *            so buffer size must be able to accomodate the
+        *            so buffer size must be able to accommodate the
         *            aligned elements.
         *
         * @return number of copied bytes
@@ -395,7 +388,7 @@ struct bnx2x_vlan_mac_obj {
         * @param bp
         * @param p Command parameters (RAMROD_COMP_WAIT bit in
         *          ramrod_flags is only taken into an account)
-        * @param ppos a pointer to the cooky that should be given back in the
+        * @param ppos a pointer to the cookie that should be given back in the
         *        next call to make function handle the next element. If
         *        *ppos is set to NULL it will restart the iterator.
         *        If returned *ppos == NULL this means that the last
@@ -408,7 +401,7 @@ struct bnx2x_vlan_mac_obj {
                       struct bnx2x_vlan_mac_registry_elem **ppos);
 
        /**
-        * Should be called on a completion arival.
+        * Should be called on a completion arrival.
         *
         * @param bp
         * @param o
@@ -447,7 +440,7 @@ void bnx2x_set_mac_in_nig(struct bnx2x *bp,
 
 /** RX_MODE verbs:DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
 
-/* RX_MODE ramrod spesial flags: set in rx_mode_flags field in
+/* RX_MODE ramrod special flags: set in rx_mode_flags field in
  * a bnx2x_rx_mode_ramrod_params.
  */
 enum {
@@ -475,8 +468,7 @@ struct bnx2x_rx_mode_ramrod_params {
        unsigned long ramrod_flags;
        unsigned long rx_mode_flags;
 
-       /*
-        * rdata is either a pointer to eth_filter_rules_ramrod_data(e2) or to
+       /* rdata is either a pointer to eth_filter_rules_ramrod_data(e2) or to
         * a tstorm_eth_mac_filter_config (e1x).
         */
        void *rdata;
@@ -646,12 +638,11 @@ struct bnx2x_credit_pool_obj {
        /* Maximum allowed credit. put() will check against it. */
        int             pool_sz;
 
-       /*
-        *  Allocate a pool table statically.
+       /* Allocate a pool table statically.
         *
-        *  Currently the mamimum allowed size is MAX_MAC_CREDIT_E2(272)
+        * Currently the maximum allowed size is MAX_MAC_CREDIT_E2(272)
         *
-        *  The set bit in the table will mean that the entry is available.
+        * The set bit in the table will mean that the entry is available.
         */
 #define BNX2X_POOL_VEC_SIZE    (MAX_MAC_CREDIT_E2 / 64)
        u64             pool_mirror[BNX2X_POOL_VEC_SIZE];
@@ -832,7 +823,7 @@ enum {
        BNX2X_Q_FLG_TUN_INC_INNER_IP_ID
 };
 
-/* Queue type options: queue type may be a compination of below. */
+/* Queue type options: queue type may be a combination of below. */
 enum bnx2x_q_type {
        /** TODO: Consider moving both these flags into the init()
         *        ramrod params.
@@ -1002,10 +993,9 @@ struct bnx2x_queue_sp_obj {
        u8              cl_id;
        u8              func_id;
 
-       /*
-        * number of traffic classes supported by queue.
-        * The primary connection of the queue suppotrs the first traffic
-        * class. Any further traffic class is suppoted by a tx-only
+       /* number of traffic classes supported by queue.
+        * The primary connection of the queue supports the first traffic
+        * class. Any further traffic class is supported by a tx-only
         * connection.
         *
         * Therefore max_cos is also a number of valid entries in the cids
@@ -1021,7 +1011,7 @@ struct bnx2x_queue_sp_obj {
 
        /* BNX2X_Q_CMD_XX bits. This object implements "one
         * pending" paradigm but for debug and tracing purposes it's
-        * more convinient to have different bits for different
+        * more convenient to have different bits for different
         * commands.
         */
        unsigned long   pending;
@@ -1210,7 +1200,7 @@ struct bnx2x_func_sp_obj {
 
        /* BNX2X_FUNC_CMD_XX bits. This object implements "one
         * pending" paradigm but for debug and tracing purposes it's
-        * more convinient to have different bits for different
+        * more convenient to have different bits for different
         * commands.
         */
        unsigned long           pending;
@@ -1329,7 +1319,7 @@ void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
  *
  * @p: Command parameters
  *
- * Return: 0 - if operation was successfull and there is no pending completions,
+ * Return: 0 - if operation was successful and there is no pending completions,
  *         positive number - if there are pending completions,
  *         negative - if there were errors
  */
@@ -1361,7 +1351,7 @@ void bnx2x_init_mcast_obj(struct bnx2x *bp,
  * the current command will be enqueued to the tail of the
  * pending commands list.
  *
- * Return: 0 is operation was successfull and there are no pending completions,
+ * Return: 0 is operation was successful and there are no pending completions,
  *         negative if there were errors, positive if there are pending
  *         completions.
  */
@@ -1377,7 +1367,6 @@ void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
                                 struct bnx2x_credit_pool_obj *p, u8 func_id,
                                 u8 func_num);
 
-
 /****************** RSS CONFIGURATION ****************/
 void bnx2x_init_rss_config_obj(struct bnx2x *bp,
                               struct bnx2x_rss_config_obj *rss_obj,
index 2ce7c7471367812bc88375ab600211c7b2a437db..8a556dd888d5a3aa55b1e4ae06a3601f7bf5b389 100644 (file)
@@ -1341,7 +1341,7 @@ int bnx2x_vfop_qdown_cmd(struct bnx2x *bp,
  */
 
 /* internal vf enable - until vf is enabled internally all transactions
- * are blocked. this routine should always be called last with pretend.
+ * are blocked. This routine should always be called last with pretend.
  */
 static void bnx2x_vf_enable_internal(struct bnx2x *bp, u8 enable)
 {
@@ -1620,7 +1620,7 @@ next_vf_to_clean:
             i++)
                ;
 
-       DP(BNX2X_MSG_IOV, "next vf to cleanup: %d. num of vfs: %d\n", i,
+       DP(BNX2X_MSG_IOV, "next vf to cleanup: %d. Num of vfs: %d\n", i,
           BNX2X_NR_VIRTFN(bp));
 
        if (i < BNX2X_NR_VIRTFN(bp)) {
@@ -1743,7 +1743,7 @@ void bnx2x_iov_init_dq(struct bnx2x *bp)
        REG_WR(bp, DORQ_REG_VF_TYPE_MIN_MCID_0, 0);
        REG_WR(bp, DORQ_REG_VF_TYPE_MAX_MCID_0, 0x1ffff);
 
-       /* set the number of VF alllowed doorbells to the full DQ range */
+       /* set the number of VF allowed doorbells to the full DQ range */
        REG_WR(bp, DORQ_REG_VF_NORM_MAX_CID_COUNT, 0x20000);
 
        /* set the VF doorbell threshold */
@@ -2403,7 +2403,7 @@ int bnx2x_iov_eq_sp_event(struct bnx2x *bp, union event_ring_elem *elem)
 
        /* extract vf and rxq index from vf_cid - relies on the following:
         * 1. vfid on cid reflects the true abs_vfid
-        * 2. the max number of VFs (per path) is 64
+        * 2. The max number of VFs (per path) is 64
         */
        qidx = cid & ((1 << BNX2X_VF_CID_WND)-1);
        abs_vfid = (cid >> BNX2X_VF_CID_WND) & (BNX2X_MAX_NUM_OF_VFS-1);
@@ -2461,7 +2461,7 @@ static struct bnx2x_virtf *bnx2x_vf_by_cid(struct bnx2x *bp, int vf_cid)
 {
        /* extract the vf from vf_cid - relies on the following:
         * 1. vfid on cid reflects the true abs_vfid
-        * 2. the max number of VFs (per path) is 64
+        * 2. The max number of VFs (per path) is 64
         */
        int abs_vfid = (vf_cid >> BNX2X_VF_CID_WND) & (BNX2X_MAX_NUM_OF_VFS-1);
        return bnx2x_vf_by_abs_fid(bp, abs_vfid);
@@ -2480,7 +2480,7 @@ void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid,
        if (vf) {
                /* extract queue index from vf_cid - relies on the following:
                 * 1. vfid on cid reflects the true abs_vfid
-                * 2. the max number of VFs (per path) is 64
+                * 2. The max number of VFs (per path) is 64
                 */
                int q_index = vf_cid & ((1 << BNX2X_VF_CID_WND)-1);
                *q_obj = &bnx2x_vfq(vf, q_index, sp_obj);
@@ -2705,7 +2705,7 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
        }
 
        /* static allocation:
-        * the global maximum number are fixed per VF. fail the request if
+        * the global maximum number are fixed per VF. Fail the request if
         * requested number exceed these globals
         */
        if (!bnx2x_vf_chk_avail_resc(bp, vf, resc)) {
@@ -2890,7 +2890,7 @@ int bnx2x_vfop_close_cmd(struct bnx2x *bp,
        return -ENOMEM;
 }
 
-/* VF release can be called either: 1. the VF was acquired but
+/* VF release can be called either: 1. The VF was acquired but
  * not enabled 2. the vf was enabled or in the process of being
  * enabled
  */
@@ -3024,7 +3024,6 @@ void bnx2x_unlock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
 
 int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param)
 {
-
        struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev));
 
        DP(BNX2X_MSG_IOV, "bnx2x_sriov_configure called with %d, BNX2X_NR_VIRTFN(bp) was %d\n",
@@ -3032,7 +3031,7 @@ int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param)
 
        /* HW channel is only operational when PF is up */
        if (bp->state != BNX2X_STATE_OPEN) {
-               BNX2X_ERR("VF num configurtion via sysfs not supported while PF is down");
+               BNX2X_ERR("VF num configuration via sysfs not supported while PF is down\n");
                return -EINVAL;
        }
 
@@ -3141,7 +3140,7 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
                        /* mac configured by ndo so its in bulletin board */
                        memcpy(&ivi->mac, bulletin->mac, ETH_ALEN);
                else
-                       /* funtion has not been loaded yet. Show mac as 0s */
+                       /* function has not been loaded yet. Show mac as 0s */
                        memset(&ivi->mac, 0, ETH_ALEN);
 
                /* vlan */
@@ -3149,7 +3148,7 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
                        /* vlan configured by ndo so its in bulletin board */
                        memcpy(&ivi->vlan, &bulletin->vlan, VLAN_HLEN);
                else
-                       /* funtion has not been loaded yet. Show vlans as 0s */
+                       /* function has not been loaded yet. Show vlans as 0s */
                        memset(&ivi->vlan, 0, VLAN_HLEN);
        }
 
@@ -3189,7 +3188,7 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
                return -EINVAL;
        }
 
-       /* update PF's copy of the VF's bulletin. will no longer accept mac
+       /* update PF's copy of the VF's bulletin. Will no longer accept mac
         * configuration requests from vf unless match this mac
         */
        bulletin->valid_bitmap |= 1 << MAC_ADDR_VALID;
@@ -3358,8 +3357,11 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
        return 0;
 }
 
-/* crc is the first field in the bulletin board. compute the crc over the
- * entire bulletin board excluding the crc field itself
+/* crc is the first field in the bulletin board. Compute the crc over the
+ * entire bulletin board excluding the crc field itself. Use the length field
+ * as the Bulletin Board was posted by a PF with possibly a different version
+ * from the vf which will sample it. Therefore, the length is computed by the
+ * PF and the used blindly by the VF.
  */
 u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
                          struct pf_vf_bulletin_content *bulletin)
@@ -3389,7 +3391,7 @@ enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
                        if (bulletin.crc == bnx2x_crc_vf_bulletin(bp,
                                                                  &bulletin))
                                break;
-                       BNX2X_ERR("bad crc on bulletin board. contained %x computed %x\n",
+                       BNX2X_ERR("bad crc on bulletin board. Contained %x computed %x\n",
                                  bulletin.crc,
                                  bnx2x_crc_vf_bulletin(bp, &bulletin));
                }
@@ -3452,7 +3454,7 @@ int bnx2x_open_epilog(struct bnx2x *bp)
         * register_netdevice which must have rtnl lock taken. As we are holding
         * the lock right now, that could only work if the probe would not take
         * the lock. However, as the probe of the vf may be called from other
-        * contexts as well (such as passthrough to vm failes) it can't assume
+        * contexts as well (such as passthrough to vm fails) it can't assume
         * the lock is being held for it. Using delayed work here allows the
         * probe code to simply take the lock (i.e. wait for it to be released
         * if it is being held). We only want to do this if the number of VFs
index d67ddc554c0f27065c7912996230d2aafb6ea89f..f08c604a4fbdf19799d2c4a3efbceced35309623 100644 (file)
@@ -197,7 +197,7 @@ struct bnx2x_virtf {
 
        u8 state;
 #define VF_FREE                0       /* VF ready to be acquired holds no resc */
-#define VF_ACQUIRED    1       /* VF aquired, but not initalized */
+#define VF_ACQUIRED    1       /* VF acquired, but not initialized */
 #define VF_ENABLED     2       /* VF Enabled */
 #define VF_RESET       3       /* VF FLR'd, pending cleanup */
 
@@ -496,7 +496,7 @@ enum {
                else if ((next) == VFOP_VERIFY_PEND)                    \
                        BNX2X_ERR("expected pending\n");                \
                else {                                                  \
-                       DP(BNX2X_MSG_IOV, "no ramrod. scheduling\n");   \
+                       DP(BNX2X_MSG_IOV, "no ramrod. Scheduling\n");   \
                        atomic_set(&vf->op_in_progress, 1);             \
                        queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);  \
                        return;                                         \
@@ -722,7 +722,6 @@ u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
                          struct pf_vf_bulletin_content *bulletin);
 int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf);
 
-
 enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp);
 
 /* VF side vfpf channel functions */
index 2ca3d94fcec2ba5f5f11db647d4454ddeafa34ad..98366abd02bda520cf1876189cced5926175288f 100644 (file)
@@ -1002,7 +1002,6 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
                qstats->valid_bytes_received_lo =
                                        qstats->total_bytes_received_lo;
 
-
                UPDATE_EXTEND_TSTAT(rcv_ucast_pkts,
                                        total_unicast_packets_received);
                UPDATE_EXTEND_TSTAT(rcv_mcast_pkts,
index d117f472816c39effa4f48f4928f52ff373436ba..853824d258e88d3b75f277fbb482357445f3260f 100644 (file)
@@ -40,7 +40,6 @@ struct nig_stats {
        u32 egress_mac_pkt1_hi;
 };
 
-
 enum bnx2x_stats_event {
        STATS_EVENT_PMF = 0,
        STATS_EVENT_LINK_UP,
@@ -208,7 +207,6 @@ struct bnx2x_eth_stats {
        u32 eee_tx_lpi;
 };
 
-
 struct bnx2x_eth_q_stats {
        u32 total_unicast_bytes_received_hi;
        u32 total_unicast_bytes_received_lo;
@@ -331,7 +329,6 @@ struct bnx2x_fw_port_stats_old {
         u32 mac_discard;
 };
 
-
 /****************************************************************************
 * Macros
 ****************************************************************************/
@@ -536,7 +533,6 @@ struct bnx2x_fw_port_stats_old {
                SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
        } while (0)
 
-
 /* forward */
 struct bnx2x;
 
index 928b074d7d80bdf9b71ea2a7e5121d9c393050ba..861809d3154b70753779604e6ecd7838bc635bae 100644 (file)
@@ -233,7 +233,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
 
                attempts++;
 
-               /* test whether the PF accepted our request. If not, humble the
+               /* test whether the PF accepted our request. If not, humble
                 * the request and try again.
                 */
                if (bp->acquire_resp.hdr.status == PFVF_STATUS_SUCCESS) {
@@ -333,7 +333,7 @@ int bnx2x_vfpf_release(struct bnx2x *bp)
                DP(BNX2X_MSG_SP, "vf released\n");
        } else {
                /* PF reports error */
-               BNX2X_ERR("PF failed our release request - are we out of sync? response status: %d\n",
+               BNX2X_ERR("PF failed our release request - are we out of sync? Response status: %d\n",
                          resp->hdr.status);
                rc = -EAGAIN;
                goto out;
@@ -787,7 +787,7 @@ static inline void bnx2x_set_vf_mbxs_valid(struct bnx2x *bp)
                storm_memset_vf_mbx_valid(bp, bnx2x_vf(bp, i, abs_vfid));
 }
 
-/* enable vf_pf mailbox (aka vf-pf-chanell) */
+/* enable vf_pf mailbox (aka vf-pf-channel) */
 void bnx2x_vf_enable_mbx(struct bnx2x *bp, u8 abs_vfid)
 {
        bnx2x_vf_flr_clnup_epilog(bp, abs_vfid);
@@ -844,7 +844,6 @@ static int bnx2x_copy32_vf_dmae(struct bnx2x *bp, u8 from_vf,
                dmae.dst_addr_hi = vf_addr_hi;
        }
        dmae.len = len32;
-       bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_DMAE);
 
        /* issue the command and wait for completion */
        return bnx2x_issue_dmae_with_comp(bp, &dmae);
@@ -1072,7 +1071,7 @@ static void bnx2x_vf_mbx_set_q_flags(struct bnx2x *bp, u32 mbx_q_flags,
        if (mbx_q_flags & VFPF_QUEUE_FLG_DHC)
                __set_bit(BNX2X_Q_FLG_DHC, sp_q_flags);
 
-       /* outer vlan removal is set according to the PF's multi fuction mode */
+       /* outer vlan removal is set according to PF's multi function mode */
        if (IS_MF_SD(bp))
                __set_bit(BNX2X_Q_FLG_OV, sp_q_flags);
 }
@@ -1104,7 +1103,7 @@ static void bnx2x_vf_mbx_setup_q(struct bnx2x *bp, struct bnx2x_virtf *vf,
                struct bnx2x_queue_init_params *init_p;
                struct bnx2x_queue_setup_params *setup_p;
 
-               /* reinit the VF operation context */
+               /* re-init the VF operation context */
                memset(&vf->op_params.qctor, 0 , sizeof(vf->op_params.qctor));
                setup_p = &vf->op_params.qctor.prep_qsetup;
                init_p =  &vf->op_params.qctor.qstate.params.init;
@@ -1588,8 +1587,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
                 * support them. Or this may be because someone wrote a crappy
                 * VF driver and is sending garbage over the channel.
                 */
-               BNX2X_ERR("unknown TLV. type %d length %d. first 20 bytes of mailbox buffer:\n",
-                         mbx->first_tlv.tl.type, mbx->first_tlv.tl.length);
+               BNX2X_ERR("unknown TLV. type %d length %d vf->state was %d. first 20 bytes of mailbox buffer:\n",
+                         mbx->first_tlv.tl.type, mbx->first_tlv.tl.length,
+                         vf->state);
                for (i = 0; i < 20; i++)
                        DP_CONT(BNX2X_MSG_IOV, "%x ",
                                mbx->msg->req.tlv_buf_size.tlv_buffer[i]);
@@ -1605,8 +1605,11 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
                        bnx2x_vf_mbx_resp(bp, vf);
                } else {
                        /* can't send a response since this VF is unknown to us
-                        * just unlock the channel and be done with.
+                        * just ack the FW to release the mailbox and unlock
+                        * the channel.
                         */
+                       storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
+                       mmiowb();
                        bnx2x_unlock_vf_pf_channel(bp, vf,
                                                   mbx->first_tlv.tl.type);
                }
index 6b0dc131b20ea3fd057fdd8c1fa98243ecbdf42c..d78d4cf140ed6d20a0e513d3c974740cf6c145cd 100644 (file)
@@ -5622,7 +5622,7 @@ static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event,
 static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
                                                         void *ptr)
 {
-       struct net_device *netdev = ptr;
+       struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
        struct cnic_dev *dev;
        int new_dev = 0;
 
index e80bfb60c3efb922a76149ce81b9a120c60fe9ce..c2777712da991dd72b876eac74fb991c73b12010 100644 (file)
@@ -2197,7 +2197,7 @@ static const struct net_device_ops sbmac_netdev_ops = {
 
 static int sbmac_init(struct platform_device *pldev, long long base)
 {
-       struct net_device *dev = dev_get_drvdata(&pldev->dev);
+       struct net_device *dev = platform_get_drvdata(pldev);
        int idx = pldev->id;
        struct sbmac_softc *sc = netdev_priv(dev);
        unsigned char *eaddr;
@@ -2275,7 +2275,7 @@ static int sbmac_init(struct platform_device *pldev, long long base)
                       dev->name);
                goto free_mdio;
        }
-       dev_set_drvdata(&pldev->dev, sc->mii_bus);
+       platform_set_drvdata(pldev, sc->mii_bus);
 
        err = register_netdev(dev);
        if (err) {
@@ -2300,7 +2300,6 @@ static int sbmac_init(struct platform_device *pldev, long long base)
        return 0;
 unreg_mdio:
        mdiobus_unregister(sc->mii_bus);
-       dev_set_drvdata(&pldev->dev, NULL);
 free_mdio:
        mdiobus_free(sc->mii_bus);
 uninit_ctx:
@@ -2624,7 +2623,7 @@ static int sbmac_probe(struct platform_device *pldev)
                goto out_unmap;
        }
 
-       dev_set_drvdata(&pldev->dev, dev);
+       platform_set_drvdata(pldev, dev);
        SET_NETDEV_DEV(dev, &pldev->dev);
 
        sc = netdev_priv(dev);
@@ -2649,7 +2648,7 @@ out_out:
 
 static int __exit sbmac_remove(struct platform_device *pldev)
 {
-       struct net_device *dev = dev_get_drvdata(&pldev->dev);
+       struct net_device *dev = platform_get_drvdata(pldev);
        struct sbmac_softc *sc = netdev_priv(dev);
 
        unregister_netdev(dev);
index 0f493c8dc28b631039cf87ad266e7ffa19601e69..28a645fc68bf8852c6ba5f1260ced7dced0a3dfa 100644 (file)
@@ -965,9 +965,6 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
 
                event = APE_EVENT_STATUS_STATE_UNLOAD;
                break;
-       case RESET_KIND_SUSPEND:
-               event = APE_EVENT_STATUS_STATE_SUSPEND;
-               break;
        default:
                return;
        }
@@ -1314,8 +1311,8 @@ static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable)
 
        if (err)
                return err;
-       if (enable)
 
+       if (enable)
                val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA;
        else
                val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA;
@@ -1739,10 +1736,6 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
                        break;
                }
        }
-
-       if (kind == RESET_KIND_INIT ||
-           kind == RESET_KIND_SUSPEND)
-               tg3_ape_driver_state_change(tp, kind);
 }
 
 /* tp->lock is held. */
@@ -1764,9 +1757,6 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind)
                        break;
                }
        }
-
-       if (kind == RESET_KIND_SHUTDOWN)
-               tg3_ape_driver_state_change(tp, kind);
 }
 
 /* tp->lock is held. */
@@ -2320,6 +2310,46 @@ static void tg3_phy_apply_otp(struct tg3 *tp)
        tg3_phy_toggle_auxctl_smdsp(tp, false);
 }
 
+static void tg3_eee_pull_config(struct tg3 *tp, struct ethtool_eee *eee)
+{
+       u32 val;
+       struct ethtool_eee *dest = &tp->eee;
+
+       if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+               return;
+
+       if (eee)
+               dest = eee;
+
+       if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, TG3_CL45_D7_EEERES_STAT, &val))
+               return;
+
+       /* Pull eee_active */
+       if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
+           val == TG3_CL45_D7_EEERES_STAT_LP_100TX) {
+               dest->eee_active = 1;
+       } else
+               dest->eee_active = 0;
+
+       /* Pull lp advertised settings */
+       if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE, &val))
+               return;
+       dest->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+
+       /* Pull advertised and eee_enabled settings */
+       if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &val))
+               return;
+       dest->eee_enabled = !!val;
+       dest->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+
+       /* Pull tx_lpi_enabled */
+       val = tr32(TG3_CPMU_EEE_MODE);
+       dest->tx_lpi_enabled = !!(val & TG3_CPMU_EEEMD_LPI_IN_TX);
+
+       /* Pull lpi timer value */
+       dest->tx_lpi_timer = tr32(TG3_CPMU_EEE_DBTMR1) & 0xffff;
+}
+
 static void tg3_phy_eee_adjust(struct tg3 *tp, bool current_link_up)
 {
        u32 val;
@@ -2343,11 +2373,8 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, bool current_link_up)
 
                tw32(TG3_CPMU_EEE_CTRL, eeectl);
 
-               tg3_phy_cl45_read(tp, MDIO_MMD_AN,
-                                 TG3_CL45_D7_EEERES_STAT, &val);
-
-               if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
-                   val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
+               tg3_eee_pull_config(tp, NULL);
+               if (tp->eee.eee_active)
                        tp->setlpicnt = 2;
        }
 
@@ -4169,6 +4196,8 @@ static int tg3_power_down_prepare(struct tg3 *tp)
 
        tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
 
+       tg3_ape_driver_state_change(tp, RESET_KIND_SHUTDOWN);
+
        return 0;
 }
 
@@ -4269,6 +4298,16 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
                /* Advertise 1000-BaseT EEE ability */
                if (advertise & ADVERTISED_1000baseT_Full)
                        val |= MDIO_AN_EEE_ADV_1000T;
+
+               if (!tp->eee.eee_enabled) {
+                       val = 0;
+                       tp->eee.advertised = 0;
+               } else {
+                       tp->eee.advertised = advertise &
+                                            (ADVERTISED_100baseT_Full |
+                                             ADVERTISED_1000baseT_Full);
+               }
+
                err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
                if (err)
                        val = 0;
@@ -4513,26 +4552,23 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp)
 
 static bool tg3_phy_eee_config_ok(struct tg3 *tp)
 {
-       u32 val;
-       u32 tgtadv = 0;
-       u32 advertising = tp->link_config.advertising;
+       struct ethtool_eee eee;
 
        if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
                return true;
 
-       if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &val))
-               return false;
-
-       val &= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
-
+       tg3_eee_pull_config(tp, &eee);
 
-       if (advertising & ADVERTISED_100baseT_Full)
-               tgtadv |= MDIO_AN_EEE_ADV_100TX;
-       if (advertising & ADVERTISED_1000baseT_Full)
-               tgtadv |= MDIO_AN_EEE_ADV_1000T;
-
-       if (val != tgtadv)
-               return false;
+       if (tp->eee.eee_enabled) {
+               if (tp->eee.advertised != eee.advertised ||
+                   tp->eee.tx_lpi_timer != eee.tx_lpi_timer ||
+                   tp->eee.tx_lpi_enabled != eee.tx_lpi_enabled)
+                       return false;
+       } else {
+               /* EEE is disabled but we're advertising */
+               if (eee.advertised)
+                       return false;
+       }
 
        return true;
 }
@@ -4633,6 +4669,42 @@ static void tg3_clear_mac_status(struct tg3 *tp)
        udelay(40);
 }
 
+static void tg3_setup_eee(struct tg3 *tp)
+{
+       u32 val;
+
+       val = TG3_CPMU_EEE_LNKIDL_PCIE_NL0 |
+             TG3_CPMU_EEE_LNKIDL_UART_IDL;
+       if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0)
+               val |= TG3_CPMU_EEE_LNKIDL_APE_TX_MT;
+
+       tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, val);
+
+       tw32_f(TG3_CPMU_EEE_CTRL,
+              TG3_CPMU_EEE_CTRL_EXIT_20_1_US);
+
+       val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET |
+             (tp->eee.tx_lpi_enabled ? TG3_CPMU_EEEMD_LPI_IN_TX : 0) |
+             TG3_CPMU_EEEMD_LPI_IN_RX |
+             TG3_CPMU_EEEMD_EEE_ENABLE;
+
+       if (tg3_asic_rev(tp) != ASIC_REV_5717)
+               val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN;
+
+       if (tg3_flag(tp, ENABLE_APE))
+               val |= TG3_CPMU_EEEMD_APE_TX_DET_EN;
+
+       tw32_f(TG3_CPMU_EEE_MODE, tp->eee.eee_enabled ? val : 0);
+
+       tw32_f(TG3_CPMU_EEE_DBTMR1,
+              TG3_CPMU_DBTMR1_PCIEXIT_2047US |
+              (tp->eee.tx_lpi_timer & 0xffff));
+
+       tw32_f(TG3_CPMU_EEE_DBTMR2,
+              TG3_CPMU_DBTMR2_APE_TX_2047US |
+              TG3_CPMU_DBTMR2_TXIDXEQ_2047US);
+}
+
 static int tg3_setup_copper_phy(struct tg3 *tp, bool force_reset)
 {
        bool current_link_up;
@@ -4799,8 +4871,10 @@ static int tg3_setup_copper_phy(struct tg3 *tp, bool force_reset)
                         */
                        if (!eee_config_ok &&
                            (tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) &&
-                           !force_reset)
+                           !force_reset) {
+                               tg3_setup_eee(tp);
                                tg3_phy_reset(tp);
+                       }
                } else {
                        if (!(bmcr & BMCR_ANENABLE) &&
                            tp->link_config.speed == current_speed &&
@@ -6312,9 +6386,7 @@ static void tg3_tx_recover(struct tg3 *tp)
                    "Please report the problem to the driver maintainer "
                    "and include system chipset information.\n");
 
-       spin_lock(&tp->lock);
        tg3_flag_set(tp, TX_RECOVERY_PENDING);
-       spin_unlock(&tp->lock);
 }
 
 static inline u32 tg3_tx_avail(struct tg3_napi *tnapi)
@@ -9166,11 +9238,9 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
 }
 
 /* tp->lock is held. */
-static void tg3_rings_reset(struct tg3 *tp)
+static void tg3_tx_rcbs_disable(struct tg3 *tp)
 {
-       int i;
-       u32 stblk, txrcb, rxrcb, limit;
-       struct tg3_napi *tnapi = &tp->napi[0];
+       u32 txrcb, limit;
 
        /* Disable all transmit rings but the first. */
        if (!tg3_flag(tp, 5705_PLUS))
@@ -9187,7 +9257,33 @@ static void tg3_rings_reset(struct tg3 *tp)
             txrcb < limit; txrcb += TG3_BDINFO_SIZE)
                tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS,
                              BDINFO_FLAGS_DISABLED);
+}
+
+/* tp->lock is held. */
+static void tg3_tx_rcbs_init(struct tg3 *tp)
+{
+       int i = 0;
+       u32 txrcb = NIC_SRAM_SEND_RCB;
+
+       if (tg3_flag(tp, ENABLE_TSS))
+               i++;
+
+       for (; i < tp->irq_max; i++, txrcb += TG3_BDINFO_SIZE) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+
+               if (!tnapi->tx_ring)
+                       continue;
+
+               tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
+                              (TG3_TX_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT),
+                              NIC_SRAM_TX_BUFFER_DESC);
+       }
+}
 
+/* tp->lock is held. */
+static void tg3_rx_ret_rcbs_disable(struct tg3 *tp)
+{
+       u32 rxrcb, limit;
 
        /* Disable all receive return rings but the first. */
        if (tg3_flag(tp, 5717_PLUS))
@@ -9205,6 +9301,39 @@ static void tg3_rings_reset(struct tg3 *tp)
             rxrcb < limit; rxrcb += TG3_BDINFO_SIZE)
                tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS,
                              BDINFO_FLAGS_DISABLED);
+}
+
+/* tp->lock is held. */
+static void tg3_rx_ret_rcbs_init(struct tg3 *tp)
+{
+       int i = 0;
+       u32 rxrcb = NIC_SRAM_RCV_RET_RCB;
+
+       if (tg3_flag(tp, ENABLE_RSS))
+               i++;
+
+       for (; i < tp->irq_max; i++, rxrcb += TG3_BDINFO_SIZE) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+
+               if (!tnapi->rx_rcb)
+                       continue;
+
+               tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
+                              (tp->rx_ret_ring_mask + 1) <<
+                               BDINFO_FLAGS_MAXLEN_SHIFT, 0);
+       }
+}
+
+/* tp->lock is held. */
+static void tg3_rings_reset(struct tg3 *tp)
+{
+       int i;
+       u32 stblk;
+       struct tg3_napi *tnapi = &tp->napi[0];
+
+       tg3_tx_rcbs_disable(tp);
+
+       tg3_rx_ret_rcbs_disable(tp);
 
        /* Disable interrupts */
        tw32_mailbox_f(tp->napi[0].int_mbox, 1);
@@ -9241,9 +9370,6 @@ static void tg3_rings_reset(struct tg3 *tp)
                        tw32_tx_mbox(mbox + i * 8, 0);
        }
 
-       txrcb = NIC_SRAM_SEND_RCB;
-       rxrcb = NIC_SRAM_RCV_RET_RCB;
-
        /* Clear status block in ram. */
        memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
 
@@ -9253,46 +9379,20 @@ static void tg3_rings_reset(struct tg3 *tp)
        tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
             ((u64) tnapi->status_mapping & 0xffffffff));
 
-       if (tnapi->tx_ring) {
-               tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
-                              (TG3_TX_RING_SIZE <<
-                               BDINFO_FLAGS_MAXLEN_SHIFT),
-                              NIC_SRAM_TX_BUFFER_DESC);
-               txrcb += TG3_BDINFO_SIZE;
-       }
-
-       if (tnapi->rx_rcb) {
-               tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
-                              (tp->rx_ret_ring_mask + 1) <<
-                               BDINFO_FLAGS_MAXLEN_SHIFT, 0);
-               rxrcb += TG3_BDINFO_SIZE;
-       }
-
        stblk = HOSTCC_STATBLCK_RING1;
 
        for (i = 1, tnapi++; i < tp->irq_cnt; i++, tnapi++) {
                u64 mapping = (u64)tnapi->status_mapping;
                tw32(stblk + TG3_64BIT_REG_HIGH, mapping >> 32);
                tw32(stblk + TG3_64BIT_REG_LOW, mapping & 0xffffffff);
+               stblk += 8;
 
                /* Clear status block in ram. */
                memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
-
-               if (tnapi->tx_ring) {
-                       tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
-                                      (TG3_TX_RING_SIZE <<
-                                       BDINFO_FLAGS_MAXLEN_SHIFT),
-                                      NIC_SRAM_TX_BUFFER_DESC);
-                       txrcb += TG3_BDINFO_SIZE;
-               }
-
-               tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
-                              ((tp->rx_ret_ring_mask + 1) <<
-                               BDINFO_FLAGS_MAXLEN_SHIFT), 0);
-
-               stblk += 8;
-               rxrcb += TG3_BDINFO_SIZE;
        }
+
+       tg3_tx_rcbs_init(tp);
+       tg3_rx_ret_rcbs_init(tp);
 }
 
 static void tg3_setup_rxbd_thresholds(struct tg3 *tp)
@@ -9492,46 +9592,17 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy)
        if (tg3_flag(tp, INIT_COMPLETE))
                tg3_abort_hw(tp, 1);
 
-       /* Enable MAC control of LPI */
-       if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
-               val = TG3_CPMU_EEE_LNKIDL_PCIE_NL0 |
-                     TG3_CPMU_EEE_LNKIDL_UART_IDL;
-               if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0)
-                       val |= TG3_CPMU_EEE_LNKIDL_APE_TX_MT;
-
-               tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, val);
-
-               tw32_f(TG3_CPMU_EEE_CTRL,
-                      TG3_CPMU_EEE_CTRL_EXIT_20_1_US);
-
-               val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET |
-                     TG3_CPMU_EEEMD_LPI_IN_TX |
-                     TG3_CPMU_EEEMD_LPI_IN_RX |
-                     TG3_CPMU_EEEMD_EEE_ENABLE;
-
-               if (tg3_asic_rev(tp) != ASIC_REV_5717)
-                       val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN;
-
-               if (tg3_flag(tp, ENABLE_APE))
-                       val |= TG3_CPMU_EEEMD_APE_TX_DET_EN;
-
-               tw32_f(TG3_CPMU_EEE_MODE, val);
-
-               tw32_f(TG3_CPMU_EEE_DBTMR1,
-                      TG3_CPMU_DBTMR1_PCIEXIT_2047US |
-                      TG3_CPMU_DBTMR1_LNKIDLE_2047US);
-
-               tw32_f(TG3_CPMU_EEE_DBTMR2,
-                      TG3_CPMU_DBTMR2_APE_TX_2047US |
-                      TG3_CPMU_DBTMR2_TXIDXEQ_2047US);
-       }
-
        if ((tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) &&
            !(tp->phy_flags & TG3_PHYFLG_USER_CONFIGURED)) {
                tg3_phy_pull_config(tp);
+               tg3_eee_pull_config(tp, NULL);
                tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED;
        }
 
+       /* Enable MAC control of LPI */
+       if (tp->phy_flags & TG3_PHYFLG_EEE_CAP)
+               tg3_setup_eee(tp);
+
        if (reset_phy)
                tg3_phy_reset(tp);
 
@@ -11180,7 +11251,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
         */
        err = tg3_alloc_consistent(tp);
        if (err)
-               goto err_out1;
+               goto out_ints_fini;
 
        tg3_napi_init(tp);
 
@@ -11194,12 +11265,15 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
                                tnapi = &tp->napi[i];
                                free_irq(tnapi->irq_vec, tnapi);
                        }
-                       goto err_out2;
+                       goto out_napi_fini;
                }
        }
 
        tg3_full_lock(tp, 0);
 
+       if (init)
+               tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
+
        err = tg3_init_hw(tp, reset_phy);
        if (err) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
@@ -11209,7 +11283,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
        tg3_full_unlock(tp);
 
        if (err)
-               goto err_out3;
+               goto out_free_irq;
 
        if (test_irq && tg3_flag(tp, USING_MSI)) {
                err = tg3_test_msi(tp);
@@ -11220,7 +11294,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
                        tg3_free_rings(tp);
                        tg3_full_unlock(tp);
 
-                       goto err_out2;
+                       goto out_napi_fini;
                }
 
                if (!tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) {
@@ -11260,18 +11334,18 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
 
        return 0;
 
-err_out3:
+out_free_irq:
        for (i = tp->irq_cnt - 1; i >= 0; i--) {
                struct tg3_napi *tnapi = &tp->napi[i];
                free_irq(tnapi->irq_vec, tnapi);
        }
 
-err_out2:
+out_napi_fini:
        tg3_napi_disable(tp);
        tg3_napi_fini(tp);
        tg3_free_consistent(tp);
 
-err_out1:
+out_ints_fini:
        tg3_ints_fini(tp);
 
        return err;
@@ -13316,11 +13390,13 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
        struct tg3 *tp = netdev_priv(dev);
        bool doextlpbk = etest->flags & ETH_TEST_FL_EXTERNAL_LB;
 
-       if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) &&
-           tg3_power_up(tp)) {
-               etest->flags |= ETH_TEST_FL_FAILED;
-               memset(data, 1, sizeof(u64) * TG3_NUM_TEST);
-               return;
+       if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
+               if (tg3_power_up(tp)) {
+                       etest->flags |= ETH_TEST_FL_FAILED;
+                       memset(data, 1, sizeof(u64) * TG3_NUM_TEST);
+                       return;
+               }
+               tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
        }
 
        memset(data, 0, sizeof(u64) * TG3_NUM_TEST);
@@ -13611,6 +13687,57 @@ static int tg3_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
        return 0;
 }
 
+static int tg3_set_eee(struct net_device *dev, struct ethtool_eee *edata)
+{
+       struct tg3 *tp = netdev_priv(dev);
+
+       if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) {
+               netdev_warn(tp->dev, "Board does not support EEE!\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (edata->advertised != tp->eee.advertised) {
+               netdev_warn(tp->dev,
+                           "Direct manipulation of EEE advertisement is not supported\n");
+               return -EINVAL;
+       }
+
+       if (edata->tx_lpi_timer > TG3_CPMU_DBTMR1_LNKIDLE_MAX) {
+               netdev_warn(tp->dev,
+                           "Maximal Tx Lpi timer supported is %#x(u)\n",
+                           TG3_CPMU_DBTMR1_LNKIDLE_MAX);
+               return -EINVAL;
+       }
+
+       tp->eee = *edata;
+
+       tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED;
+       tg3_warn_mgmt_link_flap(tp);
+
+       if (netif_running(tp->dev)) {
+               tg3_full_lock(tp, 0);
+               tg3_setup_eee(tp);
+               tg3_phy_reset(tp);
+               tg3_full_unlock(tp);
+       }
+
+       return 0;
+}
+
+static int tg3_get_eee(struct net_device *dev, struct ethtool_eee *edata)
+{
+       struct tg3 *tp = netdev_priv(dev);
+
+       if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) {
+               netdev_warn(tp->dev,
+                           "Board does not support EEE!\n");
+               return -EOPNOTSUPP;
+       }
+
+       *edata = tp->eee;
+       return 0;
+}
+
 static const struct ethtool_ops tg3_ethtool_ops = {
        .get_settings           = tg3_get_settings,
        .set_settings           = tg3_set_settings,
@@ -13644,6 +13771,8 @@ static const struct ethtool_ops tg3_ethtool_ops = {
        .get_channels           = tg3_get_channels,
        .set_channels           = tg3_set_channels,
        .get_ts_info            = tg3_get_ts_info,
+       .get_eee                = tg3_get_eee,
+       .set_eee                = tg3_set_eee,
 };
 
 static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
@@ -14992,9 +15121,18 @@ static int tg3_phy_probe(struct tg3 *tp)
             (tg3_asic_rev(tp) == ASIC_REV_5717 &&
              tg3_chip_rev_id(tp) != CHIPREV_ID_5717_A0) ||
             (tg3_asic_rev(tp) == ASIC_REV_57765 &&
-             tg3_chip_rev_id(tp) != CHIPREV_ID_57765_A0)))
+             tg3_chip_rev_id(tp) != CHIPREV_ID_57765_A0))) {
                tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
 
+               tp->eee.supported = SUPPORTED_100baseT_Full |
+                                   SUPPORTED_1000baseT_Full;
+               tp->eee.advertised = ADVERTISED_100baseT_Full |
+                                    ADVERTISED_1000baseT_Full;
+               tp->eee.eee_enabled = 1;
+               tp->eee.tx_lpi_enabled = 1;
+               tp->eee.tx_lpi_timer = TG3_CPMU_DBTMR1_LNKIDLE_2047US;
+       }
+
        tg3_phy_init_link_config(tp);
 
        if (!(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) &&
@@ -17066,7 +17204,7 @@ static int tg3_init_one(struct pci_dev *pdev,
 {
        struct net_device *dev;
        struct tg3 *tp;
-       int i, err, pm_cap;
+       int i, err;
        u32 sndmbx, rcvmbx, intmbx;
        char str[40];
        u64 dma_mask, persist_dma_mask;
@@ -17088,25 +17226,10 @@ static int tg3_init_one(struct pci_dev *pdev,
 
        pci_set_master(pdev);
 
-       /* Find power-management capability. */
-       pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
-       if (pm_cap == 0) {
-               dev_err(&pdev->dev,
-                       "Cannot find Power Management capability, aborting\n");
-               err = -EIO;
-               goto err_out_free_res;
-       }
-
-       err = pci_set_power_state(pdev, PCI_D0);
-       if (err) {
-               dev_err(&pdev->dev, "Transition to D0 failed, aborting\n");
-               goto err_out_free_res;
-       }
-
        dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS);
        if (!dev) {
                err = -ENOMEM;
-               goto err_out_power_down;
+               goto err_out_free_res;
        }
 
        SET_NETDEV_DEV(dev, &pdev->dev);
@@ -17114,7 +17237,7 @@ static int tg3_init_one(struct pci_dev *pdev,
        tp = netdev_priv(dev);
        tp->pdev = pdev;
        tp->dev = dev;
-       tp->pm_cap = pm_cap;
+       tp->pm_cap = pdev->pm_cap;
        tp->rx_mode = TG3_DEF_RX_MODE;
        tp->tx_mode = TG3_DEF_TX_MODE;
        tp->irq_sync = 1;
@@ -17452,9 +17575,6 @@ err_out_iounmap:
 err_out_free_dev:
        free_netdev(dev);
 
-err_out_power_down:
-       pci_set_power_state(pdev, PCI_D3hot);
-
 err_out_free_res:
        pci_release_regions(pdev);
 
@@ -17564,6 +17684,8 @@ static int tg3_resume(struct device *device)
 
        tg3_full_lock(tp, 0);
 
+       tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
+
        tg3_flag_set(tp, INIT_COMPLETE);
        err = tg3_restart_hw(tp,
                             !(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN));
@@ -17698,6 +17820,7 @@ static void tg3_io_resume(struct pci_dev *pdev)
                goto done;
 
        tg3_full_lock(tp, 0);
+       tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
        tg3_flag_set(tp, INIT_COMPLETE);
        err = tg3_restart_hw(tp, true);
        if (err) {
@@ -17735,15 +17858,4 @@ static struct pci_driver tg3_driver = {
        .driver.pm      = &tg3_pm_ops,
 };
 
-static int __init tg3_init(void)
-{
-       return pci_register_driver(&tg3_driver);
-}
-
-static void __exit tg3_cleanup(void)
-{
-       pci_unregister_driver(&tg3_driver);
-}
-
-module_init(tg3_init);
-module_exit(tg3_cleanup);
+module_pci_driver(tg3_driver);
index ff6e30eeae354e11895ae3e77bef4644050dd730..cd63d1189aae9fdfbcceb5615d76b8d6d74704d2 100644 (file)
 #define TG3_CPMU_EEE_DBTMR1            0x000036b4
 #define  TG3_CPMU_DBTMR1_PCIEXIT_2047US         0x07ff0000
 #define  TG3_CPMU_DBTMR1_LNKIDLE_2047US         0x000007ff
+#define  TG3_CPMU_DBTMR1_LNKIDLE_MAX    0x0000ffff
 #define TG3_CPMU_EEE_DBTMR2            0x000036b8
 #define  TG3_CPMU_DBTMR2_APE_TX_2047US  0x07ff0000
 #define  TG3_CPMU_DBTMR2_TXIDXEQ_2047US         0x000007ff
@@ -3372,6 +3373,7 @@ struct tg3 {
        unsigned int                    irq_cnt;
 
        struct ethtool_coalesce         coal;
+       struct ethtool_eee              eee;
 
        /* firmware info */
        const char                      *fw_needed;
index e423f82da4906b2f1a8a3a4680c52e05fc9a9678..b7d8127c198f7ef92f6e9f74201041464da3f64b 100644 (file)
@@ -164,7 +164,8 @@ struct bfa_ioc_attr {
        u8                              port_mode;      /*!< enum bfa_mode */
        u8                              cap_bm;         /*!< capability */
        u8                              port_mode_cfg;  /*!< enum bfa_mode */
-       u8                              rsvd[4];        /*!< 64bit align */
+       u8                              def_fn;         /*!< 1 if default fn */
+       u8                              rsvd[3];        /*!< 64bit align */
 };
 
 /* Adapter capability mask definition */
index f2b73ffa91224b732459f2c3dd777449846c1331..6f3cac060f29fb2eed554c0b42cfec9325c7ba39 100644 (file)
@@ -2371,7 +2371,7 @@ bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
        memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr));
 
        ioc_attr->state = bfa_ioc_get_state(ioc);
-       ioc_attr->port_id = ioc->port_id;
+       ioc_attr->port_id = bfa_ioc_portid(ioc);
        ioc_attr->port_mode = ioc->port_mode;
 
        ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
@@ -2381,8 +2381,9 @@ bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
 
        bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
 
-       ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
-       ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
+       ioc_attr->pci_attr.device_id = bfa_ioc_devid(ioc);
+       ioc_attr->pci_attr.pcifn = bfa_ioc_pcifn(ioc);
+       ioc_attr->def_fn = bfa_ioc_is_default(ioc);
        bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
 }
 
index 63a85e555df8b3815c9ee8181428fffe627c0706..f04e0aab25b43a763019c1e8f8e61fa591ad1ca9 100644 (file)
@@ -222,6 +222,8 @@ struct bfa_ioc_hwif {
 #define bfa_ioc_bar0(__ioc)            ((__ioc)->pcidev.pci_bar_kva)
 #define bfa_ioc_portid(__ioc)          ((__ioc)->port_id)
 #define bfa_ioc_asic_gen(__ioc)                ((__ioc)->asic_gen)
+#define bfa_ioc_is_default(__ioc)      \
+       (bfa_ioc_pcifn(__ioc) == bfa_ioc_portid(__ioc))
 #define bfa_ioc_fetch_stats(__ioc, __stats) \
                (((__stats)->drv_stats) = (__ioc)->stats)
 #define bfa_ioc_clr_stats(__ioc)       \
index 25dae757e9c42661b094270786d5f141ab72c3b4..f1eafc409bbd131894146d775b5b586d5318de86 100644 (file)
@@ -455,6 +455,8 @@ void bna_bfi_rx_enet_stop_rsp(struct bna_rx *rx,
 void bna_bfi_rxf_cfg_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr);
 void bna_bfi_rxf_mcast_add_rsp(struct bna_rxf *rxf,
                               struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_rxf_ucast_set_rsp(struct bna_rxf *rxf,
+                              struct bfi_msgq_mhdr *msghdr);
 
 /* APIs for BNA */
 void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
index db14f69d63bcd4b5268b0c9d76bff81739de41ed..3ca77fad4851ca077e1f598e28d46155887f22c2 100644 (file)
@@ -298,7 +298,6 @@ bna_msgq_rsp_handler(void *arg, struct bfi_msgq_mhdr *msghdr)
        case BFI_ENET_I2H_RSS_ENABLE_RSP:
        case BFI_ENET_I2H_RX_PROMISCUOUS_RSP:
        case BFI_ENET_I2H_RX_DEFAULT_RSP:
-       case BFI_ENET_I2H_MAC_UCAST_SET_RSP:
        case BFI_ENET_I2H_MAC_UCAST_CLR_RSP:
        case BFI_ENET_I2H_MAC_UCAST_ADD_RSP:
        case BFI_ENET_I2H_MAC_UCAST_DEL_RSP:
@@ -311,6 +310,12 @@ bna_msgq_rsp_handler(void *arg, struct bfi_msgq_mhdr *msghdr)
                        bna_bfi_rxf_cfg_rsp(&rx->rxf, msghdr);
                break;
 
+       case BFI_ENET_I2H_MAC_UCAST_SET_RSP:
+               bna_rx_from_rid(bna, msghdr->enet_id, rx);
+               if (rx)
+                       bna_bfi_rxf_ucast_set_rsp(&rx->rxf, msghdr);
+               break;
+
        case BFI_ENET_I2H_MAC_MCAST_ADD_RSP:
                bna_rx_from_rid(bna, msghdr->enet_id, rx);
                if (rx)
index ea6f4a036401aae98d9e02126119d343f05ede71..57cd1bff59f1cd056f5d7b68755612ef7e985426 100644 (file)
@@ -710,6 +710,21 @@ bna_bfi_rxf_cfg_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr)
        bfa_fsm_send_event(rxf, RXF_E_FW_RESP);
 }
 
+void
+bna_bfi_rxf_ucast_set_rsp(struct bna_rxf *rxf,
+                       struct bfi_msgq_mhdr *msghdr)
+{
+       struct bfi_enet_rsp *rsp =
+               (struct bfi_enet_rsp *)msghdr;
+
+       if (rsp->error) {
+               /* Clear ucast from cache */
+               rxf->ucast_active_set = 0;
+       }
+
+       bfa_fsm_send_event(rxf, RXF_E_FW_RESP);
+}
+
 void
 bna_bfi_rxf_mcast_add_rsp(struct bna_rxf *rxf,
                        struct bfi_msgq_mhdr *msghdr)
index 07f7ef05c3f20b00b3b3f287b412deb1ff747b35..b78e69e0e52a291047e72c222530a1500e4ac003 100644 (file)
@@ -2624,6 +2624,9 @@ bnad_stop(struct net_device *netdev)
        bnad_destroy_tx(bnad, 0);
        bnad_destroy_rx(bnad, 0);
 
+       /* These config flags are cleared in the hardware */
+       bnad->cfg_flags &= ~(BNAD_CF_ALLMULTI | BNAD_CF_PROMISC);
+
        /* Synchronize mailbox IRQ */
        bnad_mbox_irq_sync(bnad);
 
index c1d0bc059bfd57b1d6ac744a7ba5c6ccdf1945ae..aefee77523f2fbc52c621883ebe8fd56a5ffbfce 100644 (file)
@@ -71,7 +71,7 @@ struct bnad_rx_ctrl {
 #define BNAD_NAME                      "bna"
 #define BNAD_NAME_LEN                  64
 
-#define BNAD_VERSION                   "3.1.2.1"
+#define BNAD_VERSION                   "3.2.21.1"
 
 #define BNAD_MAILBOX_MSIX_INDEX                0
 #define BNAD_MAILBOX_MSIX_VECTORS      1
index 14ca9317c9150139f3047ab29fb7fba7835bdb61..c37f706d9992fadcfbd90016d8d23c7472452672 100644 (file)
@@ -37,8 +37,8 @@
 
 extern char bfa_version[];
 
-#define CNA_FW_FILE_CT "ctfw-3.1.0.0.bin"
-#define CNA_FW_FILE_CT2        "ct2fw-3.1.0.0.bin"
+#define CNA_FW_FILE_CT "ctfw-3.2.1.0.bin"
+#define CNA_FW_FILE_CT2        "ct2fw-3.2.1.0.bin"
 #define FC_SYMNAME_MAX 256     /*!< max name server symbolic name size */
 
 #pragma pack(1)
index cc9a185f0abbc03dfb9265a86a2d9fa13b07ba10..3f1957158a3bc876839d0613f1cbb0e7079687a5 100644 (file)
@@ -435,7 +435,6 @@ static int at91ether_remove(struct platform_device *pdev)
        unregister_netdev(dev);
        clk_disable(lp->pclk);
        free_netdev(dev);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index c89aa41dd44873f02fbea97c6af3f3cd6132dcbd..4465e27ba9d1303e82bb431a34f68d078b0e051f 100644 (file)
@@ -1649,7 +1649,6 @@ err_out_put_pclk:
 err_out_free_dev:
        free_netdev(dev);
 err_out:
-       platform_set_drvdata(pdev, NULL);
        return err;
 }
 
@@ -1675,7 +1674,6 @@ static int __exit macb_remove(struct platform_device *pdev)
                clk_disable_unprepare(bp->pclk);
                clk_put(bp->pclk);
                free_netdev(dev);
-               platform_set_drvdata(pdev, NULL);
        }
 
        return 0;
index 4a1f2fa812abea3e32ce97880b0c1ea5f41287b8..7cb148c495c900ad4385ed3c59db7f63f389821b 100644 (file)
@@ -1790,7 +1790,6 @@ err_io:
        free_netdev(ndev);
 err_alloc:
        release_mem_region(res->start, resource_size(res));
-       platform_set_drvdata(pdev, NULL);
        return ret;
 }
 
@@ -1813,7 +1812,6 @@ static int xgmac_remove(struct platform_device *pdev)
        free_irq(ndev->irq, ndev);
        free_irq(priv->pmt_irq, ndev);
 
-       platform_set_drvdata(pdev, NULL);
        unregister_netdev(ndev);
        netif_napi_del(&priv->napi);
 
index 9624cfe7df57154a7377f34253e3d42801762d23..d7048db9863d905a57b23b9bc985a4c3d27f9bc9 100644 (file)
@@ -1351,22 +1351,11 @@ static void remove_one(struct pci_dev *pdev)
        t1_sw_reset(pdev);
 }
 
-static struct pci_driver driver = {
+static struct pci_driver cxgb_pci_driver = {
        .name     = DRV_NAME,
        .id_table = t1_pci_tbl,
        .probe    = init_one,
        .remove   = remove_one,
 };
 
-static int __init t1_init_module(void)
-{
-       return pci_register_driver(&driver);
-}
-
-static void __exit t1_cleanup_module(void)
-{
-       pci_unregister_driver(&driver);
-}
-
-module_init(t1_init_module);
-module_exit(t1_cleanup_module);
+module_pci_driver(cxgb_pci_driver);
index 0c96e5fe99cc263461d210745c78cafc1123d4a7..4058b856eb710779bf7f164ed1547749f6a26b94 100644 (file)
@@ -1246,6 +1246,7 @@ int cxgb3_offload_activate(struct adapter *adapter)
        struct tid_range stid_range, tid_range;
        struct mtutab mtutab;
        unsigned int l2t_capacity;
+       struct l2t_data *l2td;
 
        t = kzalloc(sizeof(*t), GFP_KERNEL);
        if (!t)
@@ -1261,8 +1262,8 @@ int cxgb3_offload_activate(struct adapter *adapter)
                goto out_free;
 
        err = -ENOMEM;
-       RCU_INIT_POINTER(dev->l2opt, t3_init_l2t(l2t_capacity));
-       if (!L2DATA(dev))
+       l2td = t3_init_l2t(l2t_capacity);
+       if (!l2td)
                goto out_free;
 
        natids = min(tid_range.num / 2, MAX_ATIDS);
@@ -1279,6 +1280,7 @@ int cxgb3_offload_activate(struct adapter *adapter)
        INIT_LIST_HEAD(&t->list_node);
        t->dev = dev;
 
+       RCU_INIT_POINTER(dev->l2opt, l2td);
        T3C_DATA(dev) = t;
        dev->recv = process_rx;
        dev->neigh_update = t3_l2t_update;
@@ -1294,8 +1296,7 @@ int cxgb3_offload_activate(struct adapter *adapter)
        return 0;
 
 out_free_l2t:
-       t3_free_l2t(L2DATA(dev));
-       RCU_INIT_POINTER(dev->l2opt, NULL);
+       t3_free_l2t(l2td);
 out_free:
        kfree(t);
        return err;
index f12e6b85a653c3d345c775281a3b7b9ccacdf90f..687ec4a8bb48de001cfa9d39ef233ee7c69a5d96 100644 (file)
@@ -455,6 +455,11 @@ static int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q,
                q->pg_chunk.offset = 0;
                mapping = pci_map_page(adapter->pdev, q->pg_chunk.page,
                                       0, q->alloc_size, PCI_DMA_FROMDEVICE);
+               if (unlikely(pci_dma_mapping_error(adapter->pdev, mapping))) {
+                       __free_pages(q->pg_chunk.page, order);
+                       q->pg_chunk.page = NULL;
+                       return -EIO;
+               }
                q->pg_chunk.mapping = mapping;
        }
        sd->pg_chunk = q->pg_chunk;
@@ -949,40 +954,75 @@ static inline unsigned int calc_tx_descs(const struct sk_buff *skb)
        return flits_to_desc(flits);
 }
 
+
+/*     map_skb - map a packet main body and its page fragments
+ *     @pdev: the PCI device
+ *     @skb: the packet
+ *     @addr: placeholder to save the mapped addresses
+ *
+ *     map the main body of an sk_buff and its page fragments, if any.
+ */
+static int map_skb(struct pci_dev *pdev, const struct sk_buff *skb,
+                  dma_addr_t *addr)
+{
+       const skb_frag_t *fp, *end;
+       const struct skb_shared_info *si;
+
+       *addr = pci_map_single(pdev, skb->data, skb_headlen(skb),
+                              PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(pdev, *addr))
+               goto out_err;
+
+       si = skb_shinfo(skb);
+       end = &si->frags[si->nr_frags];
+
+       for (fp = si->frags; fp < end; fp++) {
+               *++addr = skb_frag_dma_map(&pdev->dev, fp, 0, skb_frag_size(fp),
+                                          DMA_TO_DEVICE);
+               if (pci_dma_mapping_error(pdev, *addr))
+                       goto unwind;
+       }
+       return 0;
+
+unwind:
+       while (fp-- > si->frags)
+               dma_unmap_page(&pdev->dev, *--addr, skb_frag_size(fp),
+                              DMA_TO_DEVICE);
+
+       pci_unmap_single(pdev, addr[-1], skb_headlen(skb), PCI_DMA_TODEVICE);
+out_err:
+       return -ENOMEM;
+}
+
 /**
- *     make_sgl - populate a scatter/gather list for a packet
+ *     write_sgl - populate a scatter/gather list for a packet
  *     @skb: the packet
  *     @sgp: the SGL to populate
  *     @start: start address of skb main body data to include in the SGL
  *     @len: length of skb main body data to include in the SGL
- *     @pdev: the PCI device
+ *     @addr: the list of the mapped addresses
  *
- *     Generates a scatter/gather list for the buffers that make up a packet
+ *     Copies the scatter/gather list for the buffers that make up a packet
  *     and returns the SGL size in 8-byte words.  The caller must size the SGL
  *     appropriately.
  */
-static inline unsigned int make_sgl(const struct sk_buff *skb,
+static inline unsigned int write_sgl(const struct sk_buff *skb,
                                    struct sg_ent *sgp, unsigned char *start,
-                                   unsigned int len, struct pci_dev *pdev)
+                                   unsigned int len, const dma_addr_t *addr)
 {
-       dma_addr_t mapping;
-       unsigned int i, j = 0, nfrags;
+       unsigned int i, j = 0, k = 0, nfrags;
 
        if (len) {
-               mapping = pci_map_single(pdev, start, len, PCI_DMA_TODEVICE);
                sgp->len[0] = cpu_to_be32(len);
-               sgp->addr[0] = cpu_to_be64(mapping);
-               j = 1;
+               sgp->addr[j++] = cpu_to_be64(addr[k++]);
        }
 
        nfrags = skb_shinfo(skb)->nr_frags;
        for (i = 0; i < nfrags; i++) {
                const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
-               mapping = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
-                                          DMA_TO_DEVICE);
                sgp->len[j] = cpu_to_be32(skb_frag_size(frag));
-               sgp->addr[j] = cpu_to_be64(mapping);
+               sgp->addr[j] = cpu_to_be64(addr[k++]);
                j ^= 1;
                if (j == 0)
                        ++sgp;
@@ -1138,7 +1178,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
                            const struct port_info *pi,
                            unsigned int pidx, unsigned int gen,
                            struct sge_txq *q, unsigned int ndesc,
-                           unsigned int compl)
+                           unsigned int compl, const dma_addr_t *addr)
 {
        unsigned int flits, sgl_flits, cntrl, tso_info;
        struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1];
@@ -1196,7 +1236,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
        }
 
        sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
-       sgl_flits = make_sgl(skb, sgp, skb->data, skb_headlen(skb), adap->pdev);
+       sgl_flits = write_sgl(skb, sgp, skb->data, skb_headlen(skb), addr);
 
        write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen,
                         htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl),
@@ -1227,6 +1267,7 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
        struct netdev_queue *txq;
        struct sge_qset *qs;
        struct sge_txq *q;
+       dma_addr_t addr[MAX_SKB_FRAGS + 1];
 
        /*
         * The chip min packet length is 9 octets but play safe and reject
@@ -1255,6 +1296,11 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
+       if (unlikely(map_skb(adap->pdev, skb, addr) < 0)) {
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+
        q->in_use += ndesc;
        if (unlikely(credits - ndesc < q->stop_thres)) {
                t3_stop_tx_queue(txq, qs, q);
@@ -1312,7 +1358,7 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
        if (likely(!skb_shared(skb)))
                skb_orphan(skb);
 
-       write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl);
+       write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl, addr);
        check_ring_tx_db(adap, q);
        return NETDEV_TX_OK;
 }
@@ -1537,10 +1583,9 @@ static void deferred_unmap_destructor(struct sk_buff *skb)
        dui = (struct deferred_unmap_info *)skb->head;
        p = dui->addr;
 
-       if (skb->tail - skb->transport_header)
-               pci_unmap_single(dui->pdev, *p++,
-                                skb->tail - skb->transport_header,
-                                PCI_DMA_TODEVICE);
+       if (skb_tail_pointer(skb) - skb_transport_header(skb))
+               pci_unmap_single(dui->pdev, *p++, skb_tail_pointer(skb) -
+                                skb_transport_header(skb), PCI_DMA_TODEVICE);
 
        si = skb_shinfo(skb);
        for (i = 0; i < si->nr_frags; i++)
@@ -1578,7 +1623,8 @@ static void setup_deferred_unmapping(struct sk_buff *skb, struct pci_dev *pdev,
  */
 static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
                          struct sge_txq *q, unsigned int pidx,
-                         unsigned int gen, unsigned int ndesc)
+                         unsigned int gen, unsigned int ndesc,
+                         const dma_addr_t *addr)
 {
        unsigned int sgl_flits, flits;
        struct work_request_hdr *from;
@@ -1599,9 +1645,9 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
 
        flits = skb_transport_offset(skb) / 8;
        sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
-       sgl_flits = make_sgl(skb, sgp, skb_transport_header(skb),
-                            skb->tail - skb->transport_header,
-                            adap->pdev);
+       sgl_flits = write_sgl(skb, sgp, skb_transport_header(skb),
+                            skb_tail_pointer(skb) -
+                            skb_transport_header(skb), addr);
        if (need_skb_unmap()) {
                setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits);
                skb->destructor = deferred_unmap_destructor;
@@ -1627,7 +1673,7 @@ static inline unsigned int calc_tx_descs_ofld(const struct sk_buff *skb)
 
        flits = skb_transport_offset(skb) / 8;  /* headers */
        cnt = skb_shinfo(skb)->nr_frags;
-       if (skb->tail != skb->transport_header)
+       if (skb_tail_pointer(skb) != skb_transport_header(skb))
                cnt++;
        return flits_to_desc(flits + sgl_len(cnt));
 }
@@ -1659,6 +1705,11 @@ again:   reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
                goto again;
        }
 
+       if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head)) {
+               spin_unlock(&q->lock);
+               return NET_XMIT_SUCCESS;
+       }
+
        gen = q->gen;
        q->in_use += ndesc;
        pidx = q->pidx;
@@ -1669,7 +1720,7 @@ again:    reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
        }
        spin_unlock(&q->lock);
 
-       write_ofld_wr(adap, skb, q, pidx, gen, ndesc);
+       write_ofld_wr(adap, skb, q, pidx, gen, ndesc, (dma_addr_t *)skb->head);
        check_ring_tx_db(adap, q);
        return NET_XMIT_SUCCESS;
 }
@@ -1687,6 +1738,7 @@ static void restart_offloadq(unsigned long data)
        struct sge_txq *q = &qs->txq[TXQ_OFLD];
        const struct port_info *pi = netdev_priv(qs->netdev);
        struct adapter *adap = pi->adapter;
+       unsigned int written = 0;
 
        spin_lock(&q->lock);
 again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
@@ -1706,10 +1758,14 @@ again:  reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
                        break;
                }
 
+               if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head))
+                       break;
+
                gen = q->gen;
                q->in_use += ndesc;
                pidx = q->pidx;
                q->pidx += ndesc;
+               written += ndesc;
                if (q->pidx >= q->size) {
                        q->pidx -= q->size;
                        q->gen ^= 1;
@@ -1717,7 +1773,8 @@ again:    reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
                __skb_unlink(skb, &q->sendq);
                spin_unlock(&q->lock);
 
-               write_ofld_wr(adap, skb, q, pidx, gen, ndesc);
+               write_ofld_wr(adap, skb, q, pidx, gen, ndesc,
+                            (dma_addr_t *)skb->head);
                spin_lock(&q->lock);
        }
        spin_unlock(&q->lock);
@@ -1727,8 +1784,9 @@ again:    reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
        set_bit(TXQ_LAST_PKT_DB, &q->flags);
 #endif
        wmb();
-       t3_write_reg(adap, A_SG_KDOORBELL,
-                    F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
+       if (likely(written))
+               t3_write_reg(adap, A_SG_KDOORBELL,
+                            F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
 }
 
 /**
index 681804b30a3fef09678b76b40b3cae54ebaa80d1..2aafb809e067b7a204a3fb1a92412756d9ceb78f 100644 (file)
@@ -51,7 +51,7 @@
 #include "t4_hw.h"
 
 #define FW_VERSION_MAJOR 1
-#define FW_VERSION_MINOR 1
+#define FW_VERSION_MINOR 4
 #define FW_VERSION_MICRO 0
 
 #define FW_VERSION_MAJOR_T5 0
index 3cd397d60434fe93b3005d2c329621a171bea24f..5a3256b083f23f7e69d8013c4ca1ac0585ec33c4 100644 (file)
@@ -4842,8 +4842,17 @@ static int adap_init0(struct adapter *adap)
         * is excessively mismatched relative to the driver.)
         */
        ret = t4_check_fw_version(adap);
+
+       /* The error code -EFAULT is returned by t4_check_fw_version() if
+        * firmware on adapter < supported firmware. If firmware on adapter
+        * is too old (not supported by driver) and we're the MASTER_PF set
+        * adapter state to DEV_STATE_UNINIT to force firmware upgrade
+        * and reinitialization.
+        */
+       if ((adap->flags & MASTER_PF) && ret == -EFAULT)
+               state = DEV_STATE_UNINIT;
        if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
-               if (ret == -EINVAL || ret > 0) {
+               if (ret == -EINVAL || ret == -EFAULT || ret > 0) {
                        if (upgrade_fw(adap) >= 0) {
                                /*
                                 * Note that the chip was reset as part of the
@@ -4852,7 +4861,21 @@ static int adap_init0(struct adapter *adap)
                                 */
                                reset = 0;
                                ret = t4_check_fw_version(adap);
-                       }
+                       } else
+                               if (ret == -EFAULT) {
+                                       /*
+                                        * Firmware is old but still might
+                                        * work if we force reinitialization
+                                        * of the adapter. Ignoring FW upgrade
+                                        * failure.
+                                        */
+                                       dev_warn(adap->pdev_dev,
+                                                "Ignoring firmware upgrade "
+                                                "failure, and forcing driver "
+                                                "to reinitialize the "
+                                                "adapter.\n");
+                                       ret = 0;
+                               }
                }
                if (ret < 0)
                        return ret;
index 2bfbb206b35af7c943f489ab5cbae9ebb44b8d7e..ac311f5f3eb9590d1d9b5fb3bb0a9c3f0fac5ce7 100644 (file)
@@ -1294,7 +1294,7 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
 
        flits = skb_transport_offset(skb) / 8U;   /* headers */
        cnt = skb_shinfo(skb)->nr_frags;
-       if (skb->tail != skb->transport_header)
+       if (skb_tail_pointer(skb) != skb_transport_header(skb))
                cnt++;
        return flits + sgl_len(cnt);
 }
index d02d4e8c4417cf7d78a70586f6c532ef8355a76a..bff89a437b760c9d8f2630531e67bbd577629a79 100644 (file)
@@ -938,6 +938,15 @@ int t4_check_fw_version(struct adapter *adapter)
        memcpy(adapter->params.api_vers, api_vers,
               sizeof(adapter->params.api_vers));
 
+       if (major < exp_major || (major == exp_major && minor < exp_minor) ||
+           (major == exp_major && minor == exp_minor && micro < exp_micro)) {
+               dev_err(adapter->pdev_dev,
+                       "Card has firmware version %u.%u.%u, minimum "
+                       "supported firmware is %u.%u.%u.\n", major, minor,
+                       micro, exp_major, exp_minor, exp_micro);
+               return -EFAULT;
+       }
+
        if (major != exp_major) {            /* major mismatch - fail */
                dev_err(adapter->pdev_dev,
                        "card FW has major version %u, driver wants %u\n",
index 67b0388b6e68223d2281bacb8f69aa330f2193fa..e3d4ec836f8bee3f31b41a7502966470edd90655 100644 (file)
@@ -783,7 +783,6 @@ static int ep93xx_eth_remove(struct platform_device *pdev)
        dev = platform_get_drvdata(pdev);
        if (dev == NULL)
                return 0;
-       platform_set_drvdata(pdev, NULL);
 
        ep = netdev_priv(dev);
 
index 9105465b2a1a92c5561c99bbda0df7902182ccbb..a13b312b50f20dfd544d88a338bd4263a4a716af 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/spinlock.h>
 #include <linux/crc32.h>
 #include <linux/mii.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
 #include <linux/ethtool.h>
 #include <linux/dm9000.h>
 #include <linux/delay.h>
@@ -827,7 +829,7 @@ dm9000_hash_table_unlocked(struct net_device *dev)
        struct netdev_hw_addr *ha;
        int i, oft;
        u32 hash_val;
-       u16 hash_table[4];
+       u16 hash_table[4] = { 0, 0, 0, 0x8000 }; /* broadcast address */
        u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
 
        dm9000_dbg(db, 1, "entering %s\n", __func__);
@@ -835,13 +837,6 @@ dm9000_hash_table_unlocked(struct net_device *dev)
        for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
                iow(db, oft, dev->dev_addr[i]);
 
-       /* Clear Hash Table */
-       for (i = 0; i < 4; i++)
-               hash_table[i] = 0x0;
-
-       /* broadcast address */
-       hash_table[3] = 0x8000;
-
        if (dev->flags & IFF_PROMISC)
                rcr |= RCR_PRMSC;
 
@@ -1358,6 +1353,31 @@ static const struct net_device_ops dm9000_netdev_ops = {
 #endif
 };
 
+static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev)
+{
+       struct dm9000_plat_data *pdata;
+       struct device_node *np = dev->of_node;
+       const void *mac_addr;
+
+       if (!IS_ENABLED(CONFIG_OF) || !np)
+               return NULL;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return ERR_PTR(-ENOMEM);
+
+       if (of_find_property(np, "davicom,ext-phy", NULL))
+               pdata->flags |= DM9000_PLATF_EXT_PHY;
+       if (of_find_property(np, "davicom,no-eeprom", NULL))
+               pdata->flags |= DM9000_PLATF_NO_EEPROM;
+
+       mac_addr = of_get_mac_address(np);
+       if (mac_addr)
+               memcpy(pdata->dev_addr, mac_addr, sizeof(pdata->dev_addr));
+
+       return pdata;
+}
+
 /*
  * Search DM9000 board, allocate space and register it
  */
@@ -1373,6 +1393,12 @@ dm9000_probe(struct platform_device *pdev)
        int i;
        u32 id_val;
 
+       if (!pdata) {
+               pdata = dm9000_parse_dt(&pdev->dev);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+       }
+
        /* Init network device */
        ndev = alloc_etherdev(sizeof(struct board_info));
        if (!ndev)
@@ -1673,8 +1699,6 @@ dm9000_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
 
-       platform_set_drvdata(pdev, NULL);
-
        unregister_netdev(ndev);
        dm9000_release_board(pdev, netdev_priv(ndev));
        free_netdev(ndev);              /* free device structure */
@@ -1683,11 +1707,20 @@ dm9000_drv_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id dm9000_of_matches[] = {
+       { .compatible = "davicom,dm9000", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dm9000_of_matches);
+#endif
+
 static struct platform_driver dm9000_driver = {
        .driver = {
                .name    = "dm9000",
                .owner   = THIS_MODULE,
                .pm      = &dm9000_drv_pm_ops,
+               .of_match_table = of_match_ptr(dm9000_of_matches),
        },
        .probe   = dm9000_probe,
        .remove  = dm9000_drv_remove,
index 1e9443d9fb5732fffa352683de3a019679c7f6b8..c94152f1c6be5396b511902a28478bae1c00e442 100644 (file)
@@ -1410,12 +1410,6 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                return i;
        }
 
-       /* The chip will fail to enter a low-power state later unless
-        * first explicitly commanded into D0 */
-       if (pci_set_power_state(pdev, PCI_D0)) {
-               pr_notice("Failed to set power state to D0\n");
-       }
-
        irq = pdev->irq;
 
        /* alloc_etherdev ensures aligned and zeroed private structures */
index cdbcd16431411bf48ad3cf459c8cb12f3adbf537..9b84cb04fe5fccded9f26fe010cf16ea6bb36c8a 100644 (file)
@@ -1171,16 +1171,4 @@ investigate_write_descriptor(struct net_device *dev,
        }
 }
 
-static int __init xircom_init(void)
-{
-       return pci_register_driver(&xircom_ops);
-}
-
-static void __exit xircom_exit(void)
-{
-       pci_unregister_driver(&xircom_ops);
-}
-
-module_init(xircom_init)
-module_exit(xircom_exit)
-
+module_pci_driver(xircom_ops);
index 0a510684e46857a66b8c969b63ea728b8ec446b9..c827b1b6b1ceb81c5d10bdc2db6fcea3192701a3 100644 (file)
@@ -333,6 +333,9 @@ enum vf_state {
 #define BE_VF_UC_PMAC_COUNT            2
 #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD            (1 << 11)
 
+/* Ethtool set_dump flags */
+#define LANCER_INITIATE_FW_DUMP                        0x1
+
 struct phy_info {
        u8 transceiver;
        u8 autoneg;
@@ -398,6 +401,7 @@ struct be_adapter {
        u32 cmd_privileges;
        /* Ethtool knobs and info */
        char fw_ver[FW_VER_LEN];
+       char fw_on_flash[FW_VER_LEN];
        int if_handle;          /* Used to configure filtering */
        u32 *pmac_id;           /* MAC addr handle used by BE card */
        u32 beacon_state;       /* for set_phys_id */
index 1db2df61b8af65d5b0ca32534b8b6a96e9a2c794..6e6e0a117ee2fe16061ae8e0b77a51aaacd3336b 100644 (file)
@@ -3255,6 +3255,72 @@ err:
        return status;
 }
 
+static int lancer_wait_idle(struct be_adapter *adapter)
+{
+#define SLIPORT_IDLE_TIMEOUT 30
+       u32 reg_val;
+       int status = 0, i;
+
+       for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
+               reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
+               if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
+                       break;
+
+               ssleep(1);
+       }
+
+       if (i == SLIPORT_IDLE_TIMEOUT)
+               status = -1;
+
+       return status;
+}
+
+int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
+{
+       int status = 0;
+
+       status = lancer_wait_idle(adapter);
+       if (status)
+               return status;
+
+       iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
+
+       return status;
+}
+
+/* Routine to check whether dump image is present or not */
+bool dump_present(struct be_adapter *adapter)
+{
+       u32 sliport_status = 0;
+
+       sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+       return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
+}
+
+int lancer_initiate_dump(struct be_adapter *adapter)
+{
+       int status;
+
+       /* give firmware reset and diagnostic dump */
+       status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
+                                    PHYSDEV_CONTROL_DD_MASK);
+       if (status < 0) {
+               dev_err(&adapter->pdev->dev, "Firmware reset failed\n");
+               return status;
+       }
+
+       status = lancer_wait_idle(adapter);
+       if (status)
+               return status;
+
+       if (!dump_present(adapter)) {
+               dev_err(&adapter->pdev->dev, "Dump image not present\n");
+               return -1;
+       }
+
+       return 0;
+}
+
 /* Uses sync mcc */
 int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
 {
index 025bdb0d1764e29ed92948a920a4273cf1172a35..5228d88c5a024e8e20be18e4f9fec69de7865e42 100644 (file)
@@ -1937,6 +1937,9 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
                                          struct be_dma_mem *cmd,
                                          struct be_fat_conf_params *cfgs);
 extern int lancer_wait_ready(struct be_adapter *adapter);
+extern int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask);
+extern int lancer_initiate_dump(struct be_adapter *adapter);
+extern bool dump_present(struct be_adapter *adapter);
 extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
 extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
 extern int be_cmd_get_func_config(struct be_adapter *adapter);
index 3d4461adb3b4194eef3fe2dca339650665dac97b..4f8c941217cc017495736129373fe5d2ba40db60 100644 (file)
@@ -177,19 +177,15 @@ static void be_get_drvinfo(struct net_device *netdev,
                                struct ethtool_drvinfo *drvinfo)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
-       char fw_on_flash[FW_VER_LEN];
-
-       memset(fw_on_flash, 0 , sizeof(fw_on_flash));
-       be_cmd_get_fw_ver(adapter, adapter->fw_ver, fw_on_flash);
 
        strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
        strlcpy(drvinfo->version, DRV_VER, sizeof(drvinfo->version));
-       if (!memcmp(adapter->fw_ver, fw_on_flash, FW_VER_LEN))
+       if (!memcmp(adapter->fw_ver, adapter->fw_on_flash, FW_VER_LEN))
                strlcpy(drvinfo->fw_version, adapter->fw_ver,
                        sizeof(drvinfo->fw_version));
        else
                snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
-                        "%s [%s]", adapter->fw_ver, fw_on_flash);
+                        "%s [%s]", adapter->fw_ver, adapter->fw_on_flash);
 
        strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
@@ -673,6 +669,34 @@ be_set_phys_id(struct net_device *netdev,
        return 0;
 }
 
+static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump)
+{
+       struct be_adapter *adapter = netdev_priv(netdev);
+       struct device *dev = &adapter->pdev->dev;
+       int status;
+
+       if (!lancer_chip(adapter)) {
+               dev_err(dev, "FW dump not supported\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (dump_present(adapter)) {
+               dev_err(dev, "Previous dump not cleared, not forcing dump\n");
+               return 0;
+       }
+
+       switch (dump->flag) {
+       case LANCER_INITIATE_FW_DUMP:
+               status = lancer_initiate_dump(adapter);
+               if (!status)
+                       dev_info(dev, "F/w dump initiated successfully\n");
+               break;
+       default:
+               dev_err(dev, "Invalid dump level: 0x%x\n", dump->flag);
+               return -EINVAL;
+       }
+       return status;
+}
 
 static void
 be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
@@ -1110,6 +1134,7 @@ const struct ethtool_ops be_ethtool_ops = {
        .set_pauseparam = be_set_pauseparam,
        .get_strings = be_get_stat_strings,
        .set_phys_id = be_set_phys_id,
+       .set_dump = be_set_dump,
        .get_msglevel = be_get_msg_level,
        .set_msglevel = be_set_msg_level,
        .get_sset_count = be_get_sset_count,
index 8780183c6d1c3aa3168e55d59c51c3f63e545267..3e2162121601e79481428c4d7ca02c3523dc0e33 100644 (file)
 #define PHYSDEV_CONTROL_OFFSET         0x414
 
 #define SLIPORT_STATUS_ERR_MASK                0x80000000
+#define SLIPORT_STATUS_DIP_MASK                0x02000000
 #define SLIPORT_STATUS_RN_MASK         0x01000000
 #define SLIPORT_STATUS_RDY_MASK                0x00800000
 #define SLI_PORT_CONTROL_IP_MASK       0x08000000
 #define PHYSDEV_CONTROL_FW_RESET_MASK  0x00000002
+#define PHYSDEV_CONTROL_DD_MASK                0x00000004
 #define PHYSDEV_CONTROL_INP_MASK       0x40000000
 
 #define SLIPORT_ERROR_NO_RESOURCE1     0x2
index 8bc1b21b1c790b44cffc347d7fe365f22f3a7ee2..9aef457dacbb9d99a38d514530528cc4bf71bd95 100644 (file)
@@ -834,32 +834,39 @@ static int be_vlan_tag_tx_chk(struct be_adapter *adapter, struct sk_buff *skb)
        return vlan_tx_tag_present(skb) || adapter->pvid || adapter->qnq_vid;
 }
 
-static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, struct sk_buff *skb)
+static int be_ipv6_tx_stall_chk(struct be_adapter *adapter,
+                               struct sk_buff *skb)
 {
-       return BE3_chip(adapter) &&
-               be_ipv6_exthdr_check(skb);
+       return BE3_chip(adapter) && be_ipv6_exthdr_check(skb);
 }
 
-static netdev_tx_t be_xmit(struct sk_buff *skb,
-                       struct net_device *netdev)
+static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
+                                          struct sk_buff *skb,
+                                          bool *skip_hw_vlan)
 {
-       struct be_adapter *adapter = netdev_priv(netdev);
-       struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)];
-       struct be_queue_info *txq = &txo->q;
-       struct iphdr *ip = NULL;
-       u32 wrb_cnt = 0, copied = 0;
-       u32 start = txq->head, eth_hdr_len;
-       bool dummy_wrb, stopped = false;
-       bool skip_hw_vlan = false;
        struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
+       unsigned int eth_hdr_len;
+       struct iphdr *ip;
 
-       eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
-               VLAN_ETH_HLEN : ETH_HLEN;
+       /* Lancer ASIC has a bug wherein packets that are 32 bytes or less
+        * may cause a transmit stall on that port. So the work-around is to
+        * pad such packets to a 36-byte length.
+        */
+       if (unlikely(lancer_chip(adapter) && skb->len <= 32)) {
+               if (skb_padto(skb, 36))
+                       goto tx_drop;
+               skb->len = 36;
+       }
 
        /* For padded packets, BE HW modifies tot_len field in IP header
         * incorrecly when VLAN tag is inserted by HW.
+        * For padded packets, Lancer computes incorrect checksum.
         */
-       if (skb->len <= 60 && vlan_tx_tag_present(skb) && is_ipv4_pkt(skb)) {
+       eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
+                                               VLAN_ETH_HLEN : ETH_HLEN;
+       if (skb->len <= 60 &&
+           (lancer_chip(adapter) || vlan_tx_tag_present(skb)) &&
+           is_ipv4_pkt(skb)) {
                ip = (struct iphdr *)ip_hdr(skb);
                pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
        }
@@ -869,15 +876,15 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
         */
        if ((adapter->function_mode & UMC_ENABLED) &&
            veh->h_vlan_proto == htons(ETH_P_8021Q))
-                       skip_hw_vlan = true;
+                       *skip_hw_vlan = true;
 
        /* HW has a bug wherein it will calculate CSUM for VLAN
         * pkts even though it is disabled.
         * Manually insert VLAN in pkt.
         */
        if (skb->ip_summed != CHECKSUM_PARTIAL &&
-                       vlan_tx_tag_present(skb)) {
-               skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan);
+           vlan_tx_tag_present(skb)) {
+               skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan);
                if (unlikely(!skb))
                        goto tx_drop;
        }
@@ -887,8 +894,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
         * skip HW tagging is not enabled by FW.
         */
        if (unlikely(be_ipv6_tx_stall_chk(adapter, skb) &&
-                    (adapter->pvid || adapter->qnq_vid) &&
-                    !qnq_async_evt_rcvd(adapter)))
+           (adapter->pvid || adapter->qnq_vid) &&
+           !qnq_async_evt_rcvd(adapter)))
                goto tx_drop;
 
        /* Manual VLAN tag insertion to prevent:
@@ -899,11 +906,31 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
         */
        if (be_ipv6_tx_stall_chk(adapter, skb) &&
            be_vlan_tag_tx_chk(adapter, skb)) {
-               skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan);
+               skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan);
                if (unlikely(!skb))
                        goto tx_drop;
        }
 
+       return skb;
+tx_drop:
+       dev_kfree_skb_any(skb);
+       return NULL;
+}
+
+static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct be_adapter *adapter = netdev_priv(netdev);
+       struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)];
+       struct be_queue_info *txq = &txo->q;
+       bool dummy_wrb, stopped = false;
+       u32 wrb_cnt = 0, copied = 0;
+       bool skip_hw_vlan = false;
+       u32 start = txq->head;
+
+       skb = be_xmit_workarounds(adapter, skb, &skip_hw_vlan);
+       if (!skb)
+               return NETDEV_TX_OK;
+
        wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);
 
        copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb,
@@ -933,7 +960,6 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
                txq->head = start;
                dev_kfree_skb_any(skb);
        }
-tx_drop:
        return NETDEV_TX_OK;
 }
 
@@ -3184,7 +3210,7 @@ static int be_setup(struct be_adapter *adapter)
        if (status)
                goto err;
 
-       be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL);
+       be_cmd_get_fw_ver(adapter, adapter->fw_ver, adapter->fw_on_flash);
 
        if (adapter->vlans_added)
                be_vid_config(adapter);
@@ -3530,40 +3556,6 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
        return 0;
 }
 
-static int lancer_wait_idle(struct be_adapter *adapter)
-{
-#define SLIPORT_IDLE_TIMEOUT 30
-       u32 reg_val;
-       int status = 0, i;
-
-       for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
-               reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
-               if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
-                       break;
-
-               ssleep(1);
-       }
-
-       if (i == SLIPORT_IDLE_TIMEOUT)
-               status = -1;
-
-       return status;
-}
-
-static int lancer_fw_reset(struct be_adapter *adapter)
-{
-       int status = 0;
-
-       status = lancer_wait_idle(adapter);
-       if (status)
-               return status;
-
-       iowrite32(PHYSDEV_CONTROL_FW_RESET_MASK, adapter->db +
-                 PHYSDEV_CONTROL_OFFSET);
-
-       return status;
-}
-
 static int lancer_fw_download(struct be_adapter *adapter,
                                const struct firmware *fw)
 {
@@ -3641,7 +3633,8 @@ static int lancer_fw_download(struct be_adapter *adapter,
        }
 
        if (change_status == LANCER_FW_RESET_NEEDED) {
-               status = lancer_fw_reset(adapter);
+               status = lancer_physdev_ctrl(adapter,
+                                            PHYSDEV_CONTROL_FW_RESET_MASK);
                if (status) {
                        dev_err(&adapter->pdev->dev,
                                "Adapter busy for FW reset.\n"
@@ -3776,6 +3769,10 @@ int be_load_fw(struct be_adapter *adapter, u8 *fw_file)
        else
                status = be_fw_download(adapter, fw);
 
+       if (!status)
+               be_cmd_get_fw_ver(adapter, adapter->fw_ver,
+                                 adapter->fw_on_flash);
+
 fw_exit:
        release_firmware(fw);
        return status;
index 5722bc61fa582d0796a4ce37b2e8912c4840cc59..cf579fb39bc5cf575f217902b725052d34456d0e 100644 (file)
@@ -1147,8 +1147,6 @@ static int ethoc_remove(struct platform_device *pdev)
        struct net_device *netdev = platform_get_drvdata(pdev);
        struct ethoc *priv = netdev_priv(netdev);
 
-       platform_set_drvdata(pdev, NULL);
-
        if (netdev) {
                netif_napi_del(&priv->napi);
                phy_disconnect(priv->phy);
index 21b85fb7d05f68da25f7980b937e61b1c4d9de56..934e1ae279f01ac85ce0ddb221470a9aeebab7d5 100644 (file)
@@ -1311,7 +1311,6 @@ err_ioremap:
        release_resource(priv->res);
 err_req_mem:
        netif_napi_del(&priv->napi);
-       platform_set_drvdata(pdev, NULL);
        free_netdev(netdev);
 err_alloc_etherdev:
        return err;
@@ -1335,7 +1334,6 @@ static int __exit ftgmac100_remove(struct platform_device *pdev)
        release_resource(priv->res);
 
        netif_napi_del(&priv->napi);
-       platform_set_drvdata(pdev, NULL);
        free_netdev(netdev);
        return 0;
 }
index a6eda8d83138bd791769ba9e45bccf5c1f88c00e..4658f4cc196933226f0488ab15d0a956e40354e4 100644 (file)
@@ -1149,7 +1149,6 @@ err_ioremap:
        release_resource(priv->res);
 err_req_mem:
        netif_napi_del(&priv->napi);
-       platform_set_drvdata(pdev, NULL);
        free_netdev(netdev);
 err_alloc_etherdev:
        return err;
@@ -1169,7 +1168,6 @@ static int __exit ftmac100_remove(struct platform_device *pdev)
        release_resource(priv->res);
 
        netif_napi_del(&priv->napi);
-       platform_set_drvdata(pdev, NULL);
        free_netdev(netdev);
        return 0;
 }
index 9ce5b7185fda196f521d439a143b3021b56ff5c3..b11cdbcc04ff5d6d518b9b5dc735d99626022554 100644 (file)
@@ -272,6 +272,7 @@ struct fec_enet_private {
        int hwts_tx_en;
        struct timer_list time_keep;
        struct fec_enet_delayed_work delay_work;
+       struct regulator *reg_phy;
 };
 
 void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev);
index a667015be22ada3a3bb85628620584e4fb1982e3..c42c42a0cc573745da7843557b32680476a4ae34 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/of_net.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/regulator/consumer.h>
 
 #include <asm/cacheflush.h>
@@ -243,7 +242,7 @@ static void *swap_buffer(void *bufaddr, int len)
        int i;
        unsigned int *buf = bufaddr;
 
-       for (i = 0; i < (len + 3) / 4; i++, buf++)
+       for (i = 0; i < DIV_ROUND_UP(len, 4); i++, buf++)
                *buf = cpu_to_be32(*buf);
 
        return bufaddr;
@@ -1853,8 +1852,6 @@ fec_probe(struct platform_device *pdev)
        struct resource *r;
        const struct of_device_id *of_id;
        static int dev_id;
-       struct pinctrl *pinctrl;
-       struct regulator *reg_phy;
 
        of_id = of_match_device(fec_dt_ids, &pdev->dev);
        if (of_id)
@@ -1903,12 +1900,6 @@ fec_probe(struct platform_device *pdev)
                fep->phy_interface = ret;
        }
 
-       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-       if (IS_ERR(pinctrl)) {
-               ret = PTR_ERR(pinctrl);
-               goto failed_pin;
-       }
-
        fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
        if (IS_ERR(fep->clk_ipg)) {
                ret = PTR_ERR(fep->clk_ipg);
@@ -1939,14 +1930,16 @@ fec_probe(struct platform_device *pdev)
        clk_prepare_enable(fep->clk_enet_out);
        clk_prepare_enable(fep->clk_ptp);
 
-       reg_phy = devm_regulator_get(&pdev->dev, "phy");
-       if (!IS_ERR(reg_phy)) {
-               ret = regulator_enable(reg_phy);
+       fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
+       if (!IS_ERR(fep->reg_phy)) {
+               ret = regulator_enable(fep->reg_phy);
                if (ret) {
                        dev_err(&pdev->dev,
                                "Failed to enable phy regulator: %d\n", ret);
                        goto failed_regulator;
                }
+       } else {
+               fep->reg_phy = NULL;
        }
 
        fec_reset_phy(pdev);
@@ -1996,19 +1989,20 @@ fec_probe(struct platform_device *pdev)
 failed_register:
        fec_enet_mii_remove(fep);
 failed_mii_init:
-failed_init:
+failed_irq:
        for (i = 0; i < FEC_IRQ_NUM; i++) {
                irq = platform_get_irq(pdev, i);
                if (irq > 0)
                        free_irq(irq, ndev);
        }
-failed_irq:
+failed_init:
+       if (fep->reg_phy)
+               regulator_disable(fep->reg_phy);
 failed_regulator:
        clk_disable_unprepare(fep->clk_ahb);
        clk_disable_unprepare(fep->clk_ipg);
        clk_disable_unprepare(fep->clk_enet_out);
        clk_disable_unprepare(fep->clk_ptp);
-failed_pin:
 failed_clk:
 failed_ioremap:
        free_netdev(ndev);
@@ -2027,21 +2021,21 @@ fec_drv_remove(struct platform_device *pdev)
        unregister_netdev(ndev);
        fec_enet_mii_remove(fep);
        del_timer_sync(&fep->time_keep);
+       for (i = 0; i < FEC_IRQ_NUM; i++) {
+               int irq = platform_get_irq(pdev, i);
+               if (irq > 0)
+                       free_irq(irq, ndev);
+       }
+       if (fep->reg_phy)
+               regulator_disable(fep->reg_phy);
        clk_disable_unprepare(fep->clk_ptp);
        if (fep->ptp_clock)
                ptp_clock_unregister(fep->ptp_clock);
        clk_disable_unprepare(fep->clk_enet_out);
        clk_disable_unprepare(fep->clk_ahb);
        clk_disable_unprepare(fep->clk_ipg);
-       for (i = 0; i < FEC_IRQ_NUM; i++) {
-               int irq = platform_get_irq(pdev, i);
-               if (irq > 0)
-                       free_irq(irq, ndev);
-       }
        free_netdev(ndev);
 
-       platform_set_drvdata(pdev, NULL);
-
        return 0;
 }
 
@@ -2060,6 +2054,9 @@ fec_suspend(struct device *dev)
        clk_disable_unprepare(fep->clk_ahb);
        clk_disable_unprepare(fep->clk_ipg);
 
+       if (fep->reg_phy)
+               regulator_disable(fep->reg_phy);
+
        return 0;
 }
 
@@ -2068,6 +2065,13 @@ fec_resume(struct device *dev)
 {
        struct net_device *ndev = dev_get_drvdata(dev);
        struct fec_enet_private *fep = netdev_priv(ndev);
+       int ret;
+
+       if (fep->reg_phy) {
+               ret = regulator_enable(fep->reg_phy);
+               if (ret)
+                       return ret;
+       }
 
        clk_prepare_enable(fep->clk_enet_out);
        clk_prepare_enable(fep->clk_ahb);
index 9bc15e2365bbc924631da31872b10ae94e0062c7..9947765e90c547e97eee26edbc55aa06fd436329 100644 (file)
@@ -981,7 +981,7 @@ static int mpc52xx_fec_probe(struct platform_device *op)
                goto err_node;
 
        /* We're done ! */
-       dev_set_drvdata(&op->dev, ndev);
+       platform_set_drvdata(op, ndev);
        netdev_info(ndev, "%s MAC %pM\n",
                    op->dev.of_node->full_name, ndev->dev_addr);
 
@@ -1010,7 +1010,7 @@ mpc52xx_fec_remove(struct platform_device *op)
        struct net_device *ndev;
        struct mpc52xx_fec_priv *priv;
 
-       ndev = dev_get_drvdata(&op->dev);
+       ndev = platform_get_drvdata(op);
        priv = netdev_priv(ndev);
 
        unregister_netdev(ndev);
@@ -1030,14 +1030,13 @@ mpc52xx_fec_remove(struct platform_device *op)
 
        free_netdev(ndev);
 
-       dev_set_drvdata(&op->dev, NULL);
        return 0;
 }
 
 #ifdef CONFIG_PM
 static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state)
 {
-       struct net_device *dev = dev_get_drvdata(&op->dev);
+       struct net_device *dev = platform_get_drvdata(op);
 
        if (netif_running(dev))
                mpc52xx_fec_close(dev);
@@ -1047,7 +1046,7 @@ static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state
 
 static int mpc52xx_fec_of_resume(struct platform_device *op)
 {
-       struct net_device *dev = dev_get_drvdata(&op->dev);
+       struct net_device *dev = platform_get_drvdata(op);
 
        mpc52xx_fec_hw_init(dev);
        mpc52xx_fec_reset_stats(dev);
index edc120094c340bbe61dbd33f4a3cbbf9b9a3e8d8..8de53a14a6f48895bc107c6f8ec40910d35ced7b 100644 (file)
@@ -1048,7 +1048,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
        }
 
        SET_NETDEV_DEV(ndev, &ofdev->dev);
-       dev_set_drvdata(&ofdev->dev, ndev);
+       platform_set_drvdata(ofdev, ndev);
 
        fep = netdev_priv(ndev);
        fep->dev = &ofdev->dev;
@@ -1106,7 +1106,6 @@ out_cleanup_data:
        fep->ops->cleanup_data(ndev);
 out_free_dev:
        free_netdev(ndev);
-       dev_set_drvdata(&ofdev->dev, NULL);
 out_put:
        of_node_put(fpi->phy_node);
 out_free_fpi:
@@ -1116,7 +1115,7 @@ out_free_fpi:
 
 static int fs_enet_remove(struct platform_device *ofdev)
 {
-       struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+       struct net_device *ndev = platform_get_drvdata(ofdev);
        struct fs_enet_private *fep = netdev_priv(ndev);
 
        unregister_netdev(ndev);
index 2bafbd37c247ab52802e64b531ac2e7ccc5e148a..844ecfa84d175f9b2dbcec1e5c724ac22b4ac395 100644 (file)
@@ -179,7 +179,7 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev)
        }
 
        new_bus->parent = &ofdev->dev;
-       dev_set_drvdata(&ofdev->dev, new_bus);
+       platform_set_drvdata(ofdev, new_bus);
 
        ret = of_mdiobus_register(new_bus, ofdev->dev.of_node);
        if (ret)
@@ -188,7 +188,6 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev)
        return 0;
 
 out_free_irqs:
-       dev_set_drvdata(&ofdev->dev, NULL);
        kfree(new_bus->irq);
 out_unmap_regs:
        iounmap(bitbang->dir);
@@ -202,11 +201,10 @@ out:
 
 static int fs_enet_mdio_remove(struct platform_device *ofdev)
 {
-       struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
+       struct mii_bus *bus = platform_get_drvdata(ofdev);
        struct bb_info *bitbang = bus->priv;
 
        mdiobus_unregister(bus);
-       dev_set_drvdata(&ofdev->dev, NULL);
        kfree(bus->irq);
        free_mdio_bitbang(bus);
        iounmap(bitbang->dir);
index 18e8ef203736bf2154967599a102fd454e7cc05a..2f1c46a12f0516bbcd122d1ca70a7830ea2223dd 100644 (file)
@@ -180,7 +180,7 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev)
        }
 
        new_bus->parent = &ofdev->dev;
-       dev_set_drvdata(&ofdev->dev, new_bus);
+       platform_set_drvdata(ofdev, new_bus);
 
        ret = of_mdiobus_register(new_bus, ofdev->dev.of_node);
        if (ret)
@@ -189,7 +189,6 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev)
        return 0;
 
 out_free_irqs:
-       dev_set_drvdata(&ofdev->dev, NULL);
        kfree(new_bus->irq);
 out_unmap_regs:
        iounmap(fec->fecp);
@@ -204,11 +203,10 @@ out:
 
 static int fs_enet_mdio_remove(struct platform_device *ofdev)
 {
-       struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
+       struct mii_bus *bus = platform_get_drvdata(ofdev);
        struct fec_info *fec = bus->priv;
 
        mdiobus_unregister(bus);
-       dev_set_drvdata(&ofdev->dev, NULL);
        kfree(bus->irq);
        iounmap(fec->fecp);
        kfree(fec);
index 2375a01715a0e93fa8f78c89dfcc90a88325585e..14f06947e70d2ea45a5b8c0361ff9c9b92923834 100644 (file)
@@ -1000,7 +1000,7 @@ static int gfar_probe(struct platform_device *ofdev)
        spin_lock_init(&priv->bflock);
        INIT_WORK(&priv->reset_task, gfar_reset_task);
 
-       dev_set_drvdata(&ofdev->dev, priv);
+       platform_set_drvdata(ofdev, priv);
        regs = priv->gfargrp[0].regs;
 
        gfar_detect_errata(priv);
@@ -1240,15 +1240,13 @@ register_fail:
 
 static int gfar_remove(struct platform_device *ofdev)
 {
-       struct gfar_private *priv = dev_get_drvdata(&ofdev->dev);
+       struct gfar_private *priv = platform_get_drvdata(ofdev);
 
        if (priv->phy_node)
                of_node_put(priv->phy_node);
        if (priv->tbi_node)
                of_node_put(priv->tbi_node);
 
-       dev_set_drvdata(&ofdev->dev, NULL);
-
        unregister_netdev(priv->ndev);
        unmap_group_regs(priv);
        free_gfar_dev(priv);
index 083ea2b4d20a4106e5ae3c993da3855504493f0f..098f133908ae016058f326225e2ed58b9709d592 100644 (file)
@@ -519,7 +519,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
        }
        gfar_phc_index = ptp_clock_index(etsects->clock);
 
-       dev_set_drvdata(&dev->dev, etsects);
+       platform_set_drvdata(dev, etsects);
 
        return 0;
 
@@ -537,7 +537,7 @@ no_memory:
 
 static int gianfar_ptp_remove(struct platform_device *dev)
 {
-       struct etsects *etsects = dev_get_drvdata(&dev->dev);
+       struct etsects *etsects = platform_get_drvdata(dev);
 
        gfar_write(&etsects->regs->tmr_temask, 0);
        gfar_write(&etsects->regs->tmr_ctrl,   0);
index e04c59818f60ff2f9616599d34e301e97a2f65f5..3c43dac894ecddde910e2ce8e784c455944af915 100644 (file)
@@ -3564,7 +3564,7 @@ static void ucc_geth_timeout(struct net_device *dev)
 
 static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state)
 {
-       struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+       struct net_device *ndev = platform_get_drvdata(ofdev);
        struct ucc_geth_private *ugeth = netdev_priv(ndev);
 
        if (!netif_running(ndev))
@@ -3592,7 +3592,7 @@ static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state)
 
 static int ucc_geth_resume(struct platform_device *ofdev)
 {
-       struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+       struct net_device *ndev = platform_get_drvdata(ofdev);
        struct ucc_geth_private *ugeth = netdev_priv(ndev);
        int err;
 
index 418068b941b1cadea61271ba5cc52aff01aefc10..c1b6e7e31aac4f258dd21049c4e29b7f006e933a 100644 (file)
@@ -227,7 +227,7 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
                goto err_registration;
        }
 
-       dev_set_drvdata(&pdev->dev, bus);
+       platform_set_drvdata(pdev, bus);
 
        return 0;
 
@@ -242,7 +242,7 @@ err_ioremap:
 
 static int xgmac_mdio_remove(struct platform_device *pdev)
 {
-       struct mii_bus *bus = dev_get_drvdata(&pdev->dev);
+       struct mii_bus *bus = platform_get_drvdata(pdev);
 
        mdiobus_unregister(bus);
        iounmap(bus->priv);
index 6529d31595a7e595f4ebd9e55929d017253c2c17..563a1ac71dbc8aa332657a9625120e90253b9aa5 100644 (file)
@@ -5,8 +5,7 @@
 config NET_VENDOR_IBM
        bool "IBM devices"
        default y
-       depends on MCA || PPC_PSERIES || PPC_PSERIES || PPC_DCR || \
-                  (IBMEBUS && SPARSEMEM)
+       depends on PPC_PSERIES || PPC_DCR || (IBMEBUS && SPARSEMEM)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 90ea0b1673ca45300f902f0f038f0a4a7061b745..0605e76c7eddfbd00b218faa08ed6aeb9e79ac51 100644 (file)
@@ -3289,7 +3289,7 @@ static int ehea_probe_adapter(struct platform_device *dev,
 
        adapter->pd = EHEA_PD_ID;
 
-       dev_set_drvdata(&dev->dev, adapter);
+       platform_set_drvdata(dev, adapter);
 
 
        /* initialize adapter and ports */
@@ -3360,7 +3360,7 @@ out:
 
 static int ehea_remove(struct platform_device *dev)
 {
-       struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev);
+       struct ehea_adapter *adapter = platform_get_drvdata(dev);
        int i;
 
        for (i = 0; i < EHEA_MAX_PORTS; i++)
index 610ed223d1dbd0e8c8136cdb5bb7bd46a433c8c2..856ea66c9223536bfd33cd46813d49b260bb49b0 100644 (file)
@@ -696,7 +696,7 @@ static int mal_probe(struct platform_device *ofdev)
 
        /* Advertise this instance to the rest of the world */
        wmb();
-       dev_set_drvdata(&ofdev->dev, mal);
+       platform_set_drvdata(ofdev, mal);
 
        mal_dbg_register(mal);
 
@@ -722,7 +722,7 @@ static int mal_probe(struct platform_device *ofdev)
 
 static int mal_remove(struct platform_device *ofdev)
 {
-       struct mal_instance *mal = dev_get_drvdata(&ofdev->dev);
+       struct mal_instance *mal = platform_get_drvdata(ofdev);
 
        MAL_DBG(mal, "remove" NL);
 
@@ -735,8 +735,6 @@ static int mal_remove(struct platform_device *ofdev)
                       "mal%d: commac list is not empty on remove!\n",
                       mal->index);
 
-       dev_set_drvdata(&ofdev->dev, NULL);
-
        free_irq(mal->serr_irq, mal);
        free_irq(mal->txde_irq, mal);
        free_irq(mal->txeob_irq, mal);
index 39251765b55d444c8dbc0ab0e380e89546d4a964..c47e23d6eeaa0b57752d4ca047567178e1d37026 100644 (file)
@@ -95,7 +95,7 @@ static inline u32 rgmii_mode_mask(int mode, int input)
 
 int rgmii_attach(struct platform_device *ofdev, int input, int mode)
 {
-       struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct rgmii_instance *dev = platform_get_drvdata(ofdev);
        struct rgmii_regs __iomem *p = dev->base;
 
        RGMII_DBG(dev, "attach(%d)" NL, input);
@@ -124,7 +124,7 @@ int rgmii_attach(struct platform_device *ofdev, int input, int mode)
 
 void rgmii_set_speed(struct platform_device *ofdev, int input, int speed)
 {
-       struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct rgmii_instance *dev = platform_get_drvdata(ofdev);
        struct rgmii_regs __iomem *p = dev->base;
        u32 ssr;
 
@@ -146,7 +146,7 @@ void rgmii_set_speed(struct platform_device *ofdev, int input, int speed)
 
 void rgmii_get_mdio(struct platform_device *ofdev, int input)
 {
-       struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct rgmii_instance *dev = platform_get_drvdata(ofdev);
        struct rgmii_regs __iomem *p = dev->base;
        u32 fer;
 
@@ -167,7 +167,7 @@ void rgmii_get_mdio(struct platform_device *ofdev, int input)
 
 void rgmii_put_mdio(struct platform_device *ofdev, int input)
 {
-       struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct rgmii_instance *dev = platform_get_drvdata(ofdev);
        struct rgmii_regs __iomem *p = dev->base;
        u32 fer;
 
@@ -188,7 +188,7 @@ void rgmii_put_mdio(struct platform_device *ofdev, int input)
 
 void rgmii_detach(struct platform_device *ofdev, int input)
 {
-       struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct rgmii_instance *dev = platform_get_drvdata(ofdev);
        struct rgmii_regs __iomem *p;
 
        BUG_ON(!dev || dev->users == 0);
@@ -214,7 +214,7 @@ int rgmii_get_regs_len(struct platform_device *ofdev)
 
 void *rgmii_dump_regs(struct platform_device *ofdev, void *buf)
 {
-       struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct rgmii_instance *dev = platform_get_drvdata(ofdev);
        struct emac_ethtool_regs_subhdr *hdr = buf;
        struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1);
 
@@ -279,7 +279,7 @@ static int rgmii_probe(struct platform_device *ofdev)
               (dev->flags & EMAC_RGMII_FLAG_HAS_MDIO) ? "" : "out");
 
        wmb();
-       dev_set_drvdata(&ofdev->dev, dev);
+       platform_set_drvdata(ofdev, dev);
 
        return 0;
 
@@ -291,9 +291,7 @@ static int rgmii_probe(struct platform_device *ofdev)
 
 static int rgmii_remove(struct platform_device *ofdev)
 {
-       struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
-
-       dev_set_drvdata(&ofdev->dev, NULL);
+       struct rgmii_instance *dev = platform_get_drvdata(ofdev);
 
        WARN_ON(dev->users != 0);
 
index 795f1393e2b6d006fd568e91d22bfd58dc7d08d4..c231a4a32c4dc90d341b10c67c194c1025e4c686 100644 (file)
@@ -25,7 +25,7 @@
 
 int tah_attach(struct platform_device *ofdev, int channel)
 {
-       struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct tah_instance *dev = platform_get_drvdata(ofdev);
 
        mutex_lock(&dev->lock);
        /* Reset has been done at probe() time... nothing else to do for now */
@@ -37,7 +37,7 @@ int tah_attach(struct platform_device *ofdev, int channel)
 
 void tah_detach(struct platform_device *ofdev, int channel)
 {
-       struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct tah_instance *dev = platform_get_drvdata(ofdev);
 
        mutex_lock(&dev->lock);
        --dev->users;
@@ -46,7 +46,7 @@ void tah_detach(struct platform_device *ofdev, int channel)
 
 void tah_reset(struct platform_device *ofdev)
 {
-       struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct tah_instance *dev = platform_get_drvdata(ofdev);
        struct tah_regs __iomem *p = dev->base;
        int n;
 
@@ -74,7 +74,7 @@ int tah_get_regs_len(struct platform_device *ofdev)
 
 void *tah_dump_regs(struct platform_device *ofdev, void *buf)
 {
-       struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct tah_instance *dev = platform_get_drvdata(ofdev);
        struct emac_ethtool_regs_subhdr *hdr = buf;
        struct tah_regs *regs = (struct tah_regs *)(hdr + 1);
 
@@ -118,7 +118,7 @@ static int tah_probe(struct platform_device *ofdev)
                goto err_free;
        }
 
-       dev_set_drvdata(&ofdev->dev, dev);
+       platform_set_drvdata(ofdev, dev);
 
        /* Initialize TAH and enable IPv4 checksum verification, no TSO yet */
        tah_reset(ofdev);
@@ -137,9 +137,7 @@ static int tah_probe(struct platform_device *ofdev)
 
 static int tah_remove(struct platform_device *ofdev)
 {
-       struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
-
-       dev_set_drvdata(&ofdev->dev, NULL);
+       struct tah_instance *dev = platform_get_drvdata(ofdev);
 
        WARN_ON(dev->users != 0);
 
index f91202f42125d3088c6fbb69ac9c87b3417dfb07..4cdf286f7ee314dc55acb2494a74ede4468170e8 100644 (file)
@@ -84,7 +84,7 @@ static inline u32 zmii_mode_mask(int mode, int input)
 
 int zmii_attach(struct platform_device *ofdev, int input, int *mode)
 {
-       struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct zmii_instance *dev = platform_get_drvdata(ofdev);
        struct zmii_regs __iomem *p = dev->base;
 
        ZMII_DBG(dev, "init(%d, %d)" NL, input, *mode);
@@ -150,7 +150,7 @@ int zmii_attach(struct platform_device *ofdev, int input, int *mode)
 
 void zmii_get_mdio(struct platform_device *ofdev, int input)
 {
-       struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct zmii_instance *dev = platform_get_drvdata(ofdev);
        u32 fer;
 
        ZMII_DBG2(dev, "get_mdio(%d)" NL, input);
@@ -163,7 +163,7 @@ void zmii_get_mdio(struct platform_device *ofdev, int input)
 
 void zmii_put_mdio(struct platform_device *ofdev, int input)
 {
-       struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct zmii_instance *dev = platform_get_drvdata(ofdev);
 
        ZMII_DBG2(dev, "put_mdio(%d)" NL, input);
        mutex_unlock(&dev->lock);
@@ -172,7 +172,7 @@ void zmii_put_mdio(struct platform_device *ofdev, int input)
 
 void zmii_set_speed(struct platform_device *ofdev, int input, int speed)
 {
-       struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct zmii_instance *dev = platform_get_drvdata(ofdev);
        u32 ssr;
 
        mutex_lock(&dev->lock);
@@ -193,7 +193,7 @@ void zmii_set_speed(struct platform_device *ofdev, int input, int speed)
 
 void zmii_detach(struct platform_device *ofdev, int input)
 {
-       struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct zmii_instance *dev = platform_get_drvdata(ofdev);
 
        BUG_ON(!dev || dev->users == 0);
 
@@ -218,7 +218,7 @@ int zmii_get_regs_len(struct platform_device *ofdev)
 
 void *zmii_dump_regs(struct platform_device *ofdev, void *buf)
 {
-       struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+       struct zmii_instance *dev = platform_get_drvdata(ofdev);
        struct emac_ethtool_regs_subhdr *hdr = buf;
        struct zmii_regs *regs = (struct zmii_regs *)(hdr + 1);
 
@@ -272,7 +272,7 @@ static int zmii_probe(struct platform_device *ofdev)
        printk(KERN_INFO
               "ZMII %s initialized\n", ofdev->dev.of_node->full_name);
        wmb();
-       dev_set_drvdata(&ofdev->dev, dev);
+       platform_set_drvdata(ofdev, dev);
 
        return 0;
 
@@ -284,9 +284,7 @@ static int zmii_probe(struct platform_device *ofdev)
 
 static int zmii_remove(struct platform_device *ofdev)
 {
-       struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
-
-       dev_set_drvdata(&ofdev->dev, NULL);
+       struct zmii_instance *dev = platform_get_drvdata(ofdev);
 
        WARN_ON(dev->users != 0);
 
index 068d78151658819ba5a88895df55942d59134e83..1fde90b96685e878b12ffeee0abc8487845cb4da 100644 (file)
@@ -2298,15 +2298,4 @@ static struct pci_driver ipg_pci_driver = {
        .remove         = ipg_remove,
 };
 
-static int __init ipg_init_module(void)
-{
-       return pci_register_driver(&ipg_pci_driver);
-}
-
-static void __exit ipg_exit_module(void)
-{
-       pci_unregister_driver(&ipg_pci_driver);
-}
-
-module_init(ipg_init_module);
-module_exit(ipg_exit_module);
+module_pci_driver(ipg_pci_driver);
index b71c8502a2b347d8c770ac723d659a6115127e35..895450e9bb3cfe81d22f19148b4a52d9fc14352a 100644 (file)
@@ -66,17 +66,17 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
        s32 ret_val;
 
        if (hw->phy.media_type != e1000_media_type_copper) {
-               phy->type       = e1000_phy_none;
+               phy->type = e1000_phy_none;
                return 0;
        } else {
                phy->ops.power_up = e1000_power_up_phy_copper;
                phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
        }
 
-       phy->addr               = 1;
-       phy->autoneg_mask       = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-       phy->reset_delay_us      = 100;
-       phy->type               = e1000_phy_gg82563;
+       phy->addr = 1;
+       phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us = 100;
+       phy->type = e1000_phy_gg82563;
 
        /* This can only be done after all function pointers are setup. */
        ret_val = e1000e_get_phy_id(hw);
@@ -98,19 +98,19 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
        u32 eecd = er32(EECD);
        u16 size;
 
-       nvm->opcode_bits        = 8;
-       nvm->delay_usec  = 1;
+       nvm->opcode_bits = 8;
+       nvm->delay_usec = 1;
        switch (nvm->override) {
        case e1000_nvm_override_spi_large:
-               nvm->page_size    = 32;
+               nvm->page_size = 32;
                nvm->address_bits = 16;
                break;
        case e1000_nvm_override_spi_small:
-               nvm->page_size    = 8;
+               nvm->page_size = 8;
                nvm->address_bits = 8;
                break;
        default:
-               nvm->page_size    = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
+               nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
                nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
                break;
        }
@@ -128,7 +128,7 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
        /* EEPROM access above 16k is unsupported */
        if (size > 14)
                size = 14;
-       nvm->word_size  = 1 << size;
+       nvm->word_size = 1 << size;
 
        return 0;
 }
@@ -859,7 +859,7 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
 
        /* Transmit Arbitration Control 0 */
        reg = er32(TARC(0));
-       reg &= ~(0xF << 27); /* 30:27 */
+       reg &= ~(0xF << 27);    /* 30:27 */
        if (hw->phy.media_type != e1000_media_type_copper)
                reg &= ~(1 << 20);
        ew32(TARC(0), reg);
index 7380442a38299b5480c7858ee344a48bc87905b5..4c303e2a7cb3f3aae1ed974d6a066168c7e82c4a 100644 (file)
@@ -77,24 +77,24 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
                return 0;
        }
 
-       phy->addr                        = 1;
-       phy->autoneg_mask                = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-       phy->reset_delay_us              = 100;
+       phy->addr = 1;
+       phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us = 100;
 
-       phy->ops.power_up                = e1000_power_up_phy_copper;
-       phy->ops.power_down              = e1000_power_down_phy_copper_82571;
+       phy->ops.power_up = e1000_power_up_phy_copper;
+       phy->ops.power_down = e1000_power_down_phy_copper_82571;
 
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
-               phy->type                = e1000_phy_igp_2;
+               phy->type = e1000_phy_igp_2;
                break;
        case e1000_82573:
-               phy->type                = e1000_phy_m88;
+               phy->type = e1000_phy_m88;
                break;
        case e1000_82574:
        case e1000_82583:
-               phy->type                = e1000_phy_bm;
+               phy->type = e1000_phy_bm;
                phy->ops.acquire = e1000_get_hw_semaphore_82574;
                phy->ops.release = e1000_put_hw_semaphore_82574;
                phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574;
@@ -193,7 +193,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
                /* EEPROM access above 16k is unsupported */
                if (size > 14)
                        size = 14;
-               nvm->word_size  = 1 << size;
+               nvm->word_size = 1 << size;
                break;
        }
 
@@ -339,7 +339,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
 static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
-       static int global_quad_port_a; /* global port a indication */
+       static int global_quad_port_a;  /* global port a indication */
        struct pci_dev *pdev = adapter->pdev;
        int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1;
        s32 rc;
@@ -1003,8 +1003,6 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
        default:
                break;
        }
-       if (ret_val)
-               e_dbg("Cannot acquire MDIO ownership\n");
 
        ctrl = er32(CTRL);
 
@@ -1015,7 +1013,9 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
        switch (hw->mac.type) {
        case e1000_82574:
        case e1000_82583:
-               e1000_put_hw_semaphore_82574(hw);
+               /* Release mutex only if the hw semaphore is acquired */
+               if (!ret_val)
+                       e1000_put_hw_semaphore_82574(hw);
                break;
        default:
                break;
@@ -1178,7 +1178,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
 
        /* Transmit Arbitration Control 0 */
        reg = er32(TARC(0));
-       reg &= ~(0xF << 27); /* 30:27 */
+       reg &= ~(0xF << 27);    /* 30:27 */
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
@@ -1390,7 +1390,7 @@ bool e1000_check_phy_82574(struct e1000_hw *hw)
        ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors);
        if (ret_val)
                return false;
-       if (receive_errors == E1000_RECEIVE_ERROR_MAX)  {
+       if (receive_errors == E1000_RECEIVE_ERROR_MAX) {
                ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt);
                if (ret_val)
                        return false;
index 7c8ca658d553d489f37234fe177d25ed870975d0..59c22bf18701bf6505b13c0f16228a43694e2bb7 100644 (file)
@@ -244,7 +244,7 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
                mac->autoneg = 1;
                adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL;
                break;
-       case SPEED_1000 + DUPLEX_HALF: /* not supported */
+       case SPEED_1000 + DUPLEX_HALF:  /* not supported */
        default:
                goto err_inval;
        }
@@ -416,7 +416,7 @@ static void e1000_set_msglevel(struct net_device *netdev, u32 data)
 
 static int e1000_get_regs_len(struct net_device __always_unused *netdev)
 {
-#define E1000_REGS_LEN 32 /* overestimate */
+#define E1000_REGS_LEN 32      /* overestimate */
        return E1000_REGS_LEN * sizeof(u32);
 }
 
@@ -433,22 +433,22 @@ static void e1000_get_regs(struct net_device *netdev,
        regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
            adapter->pdev->device;
 
-       regs_buff[0]  = er32(CTRL);
-       regs_buff[1]  = er32(STATUS);
+       regs_buff[0] = er32(CTRL);
+       regs_buff[1] = er32(STATUS);
 
-       regs_buff[2]  = er32(RCTL);
-       regs_buff[3]  = er32(RDLEN(0));
-       regs_buff[4]  = er32(RDH(0));
-       regs_buff[5]  = er32(RDT(0));
-       regs_buff[6]  = er32(RDTR);
+       regs_buff[2] = er32(RCTL);
+       regs_buff[3] = er32(RDLEN(0));
+       regs_buff[4] = er32(RDH(0));
+       regs_buff[5] = er32(RDT(0));
+       regs_buff[6] = er32(RDTR);
 
-       regs_buff[7]  = er32(TCTL);
-       regs_buff[8]  = er32(TDLEN(0));
-       regs_buff[9]  = er32(TDH(0));
+       regs_buff[7] = er32(TCTL);
+       regs_buff[8] = er32(TDLEN(0));
+       regs_buff[9] = er32(TDH(0));
        regs_buff[10] = er32(TDT(0));
        regs_buff[11] = er32(TIDV);
 
-       regs_buff[12] = adapter->hw.phy.type;  /* PHY type (IGP=1, M88=0) */
+       regs_buff[12] = adapter->hw.phy.type;   /* PHY type (IGP=1, M88=0) */
 
        /* ethtool doesn't use anything past this point, so all this
         * code is likely legacy junk for apps that may or may not exist
@@ -1379,7 +1379,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 
        if (hw->phy.media_type == e1000_media_type_copper &&
            hw->phy.type == e1000_phy_m88) {
-               ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
+               ctrl_reg |= E1000_CTRL_ILOS;    /* Invert Loss of Signal */
        } else {
                /* Set the ILOS bit on the fiber Nic if half duplex link is
                 * detected.
@@ -1613,7 +1613,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
                ew32(TDT(0), k);
                e1e_flush();
                msleep(200);
-               time = jiffies; /* set the start time for the receive */
+               time = jiffies; /* set the start time for the receive */
                good_cnt = 0;
                /* receive the sent packets */
                do {
@@ -1636,11 +1636,11 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
                         */
                } while ((good_cnt < 64) && !time_after(jiffies, time + 20));
                if (good_cnt != 64) {
-                       ret_val = 13; /* ret_val is the same as mis-compare */
+                       ret_val = 13;   /* ret_val is the same as mis-compare */
                        break;
                }
                if (jiffies >= (time + 20)) {
-                       ret_val = 14; /* error code for time out error */
+                       ret_val = 14;   /* error code for time out error */
                        break;
                }
        }
index 84850f7a23e4205650b9cef83f12be762a4feea9..a6f903a9b7731cd3460d5337b98d3ae79a4d3661 100644 (file)
@@ -402,13 +402,13 @@ struct e1000_phy_stats {
 
 struct e1000_host_mng_dhcp_cookie {
        u32 signature;
-       u8  status;
-       u8  reserved0;
+       u8 status;
+       u8 reserved0;
        u16 vlan_id;
        u32 reserved1;
        u16 reserved2;
-       u8  reserved3;
-       u8  checksum;
+       u8 reserved3;
+       u8 checksum;
 };
 
 /* Host Interface "Rev 1" */
@@ -427,8 +427,8 @@ struct e1000_host_command_info {
 
 /* Host Interface "Rev 2" */
 struct e1000_host_mng_command_header {
-       u8  command_id;
-       u8  checksum;
+       u8 command_id;
+       u8 checksum;
        u16 reserved1;
        u16 reserved2;
        u16 command_length;
@@ -549,7 +549,7 @@ struct e1000_mac_info {
        u32 mta_shadow[MAX_MTA_REG];
        u16 rar_entry_count;
 
-       u8  forced_speed_duplex;
+       u8 forced_speed_duplex;
 
        bool adaptive_ifs;
        bool has_fwsm;
@@ -577,7 +577,7 @@ struct e1000_phy_info {
 
        u32 addr;
        u32 id;
-       u32 reset_delay_us; /* in usec */
+       u32 reset_delay_us;     /* in usec */
        u32 revision;
 
        enum e1000_media_type media_type;
@@ -636,11 +636,11 @@ struct e1000_dev_spec_82571 {
 };
 
 struct e1000_dev_spec_80003es2lan {
-       bool  mdic_wa_enable;
+       bool mdic_wa_enable;
 };
 
 struct e1000_shadow_ram {
-       u16  value;
+       u16 value;
        bool modified;
 };
 
@@ -660,17 +660,17 @@ struct e1000_hw {
        void __iomem *hw_addr;
        void __iomem *flash_address;
 
-       struct e1000_mac_info  mac;
-       struct e1000_fc_info   fc;
-       struct e1000_phy_info  phy;
-       struct e1000_nvm_info  nvm;
-       struct e1000_bus_info  bus;
+       struct e1000_mac_info mac;
+       struct e1000_fc_info fc;
+       struct e1000_phy_info phy;
+       struct e1000_nvm_info nvm;
+       struct e1000_bus_info bus;
        struct e1000_host_mng_dhcp_cookie mng_cookie;
 
        union {
-               struct e1000_dev_spec_82571     e82571;
+               struct e1000_dev_spec_82571 e82571;
                struct e1000_dev_spec_80003es2lan e80003es2lan;
-               struct e1000_dev_spec_ich8lan   ich8lan;
+               struct e1000_dev_spec_ich8lan ich8lan;
        } dev_spec;
 };
 
index ad9d8f2dd868778d1b4f8a1c2e3b767add06acd8..9dde390f7e71c34f327f1e1bc213dce5338b917c 100644 (file)
@@ -101,12 +101,12 @@ union ich8_hws_flash_regacc {
 /* ICH Flash Protected Region */
 union ich8_flash_protected_range {
        struct ich8_pr {
-               u32 base:13;     /* 0:12 Protected Range Base */
-               u32 reserved1:2; /* 13:14 Reserved */
-               u32 rpe:1;       /* 15 Read Protection Enable */
-               u32 limit:13;    /* 16:28 Protected Range Limit */
-               u32 reserved2:2; /* 29:30 Reserved */
-               u32 wpe:1;       /* 31 Write Protection Enable */
+               u32 base:13;    /* 0:12 Protected Range Base */
+               u32 reserved1:2;        /* 13:14 Reserved */
+               u32 rpe:1;      /* 15 Read Protection Enable */
+               u32 limit:13;   /* 16:28 Protected Range Limit */
+               u32 reserved2:2;        /* 29:30 Reserved */
+               u32 wpe:1;      /* 31 Write Protection Enable */
        } range;
        u32 regval;
 };
@@ -362,21 +362,21 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
 
-       phy->addr                     = 1;
-       phy->reset_delay_us           = 100;
-
-       phy->ops.set_page             = e1000_set_page_igp;
-       phy->ops.read_reg             = e1000_read_phy_reg_hv;
-       phy->ops.read_reg_locked      = e1000_read_phy_reg_hv_locked;
-       phy->ops.read_reg_page        = e1000_read_phy_reg_page_hv;
-       phy->ops.set_d0_lplu_state    = e1000_set_lplu_state_pchlan;
-       phy->ops.set_d3_lplu_state    = e1000_set_lplu_state_pchlan;
-       phy->ops.write_reg            = e1000_write_phy_reg_hv;
-       phy->ops.write_reg_locked     = e1000_write_phy_reg_hv_locked;
-       phy->ops.write_reg_page       = e1000_write_phy_reg_page_hv;
-       phy->ops.power_up             = e1000_power_up_phy_copper;
-       phy->ops.power_down           = e1000_power_down_phy_copper_ich8lan;
-       phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->addr = 1;
+       phy->reset_delay_us = 100;
+
+       phy->ops.set_page = e1000_set_page_igp;
+       phy->ops.read_reg = e1000_read_phy_reg_hv;
+       phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked;
+       phy->ops.read_reg_page = e1000_read_phy_reg_page_hv;
+       phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan;
+       phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
+       phy->ops.write_reg = e1000_write_phy_reg_hv;
+       phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked;
+       phy->ops.write_reg_page = e1000_write_phy_reg_page_hv;
+       phy->ops.power_up = e1000_power_up_phy_copper;
+       phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
+       phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
 
        phy->id = e1000_phy_unknown;
 
@@ -445,11 +445,11 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
        s32 ret_val;
        u16 i = 0;
 
-       phy->addr                       = 1;
-       phy->reset_delay_us             = 100;
+       phy->addr = 1;
+       phy->reset_delay_us = 100;
 
-       phy->ops.power_up               = e1000_power_up_phy_copper;
-       phy->ops.power_down             = e1000_power_down_phy_copper_ich8lan;
+       phy->ops.power_up = e1000_power_up_phy_copper;
+       phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
 
        /* We may need to do this twice - once for IGP and if that fails,
         * we'll set BM func pointers and try again
@@ -457,7 +457,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
        ret_val = e1000e_determine_phy_address(hw);
        if (ret_val) {
                phy->ops.write_reg = e1000e_write_phy_reg_bm;
-               phy->ops.read_reg  = e1000e_read_phy_reg_bm;
+               phy->ops.read_reg = e1000e_read_phy_reg_bm;
                ret_val = e1000e_determine_phy_address(hw);
                if (ret_val) {
                        e_dbg("Cannot determine PHY addr. Erroring out\n");
@@ -560,7 +560,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
        /* Clear shadow ram */
        for (i = 0; i < nvm->word_size; i++) {
                dev_spec->shadow_ram[i].modified = false;
-               dev_spec->shadow_ram[i].value    = 0xFFFF;
+               dev_spec->shadow_ram[i].value = 0xFFFF;
        }
 
        return 0;
@@ -1012,7 +1012,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
        hw->dev_spec.ich8lan.eee_lp_ability = 0;
 
        if (!link)
-               return 0; /* No link detected */
+               return 0;       /* No link detected */
 
        mac->get_link_status = false;
 
@@ -2816,7 +2816,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
        s32 ret_val = -E1000_ERR_NVM;
        u8 count = 0;
 
-       if (size < 1  || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
+       if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
                return -E1000_ERR_NVM;
 
        flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
@@ -2939,7 +2939,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
         * write to bank 0 etc.  We also need to erase the segment that
         * is going to be written
         */
-       ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+       ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
        if (ret_val) {
                e_dbg("Could not detect valid bank, assuming bank 0\n");
                bank = 0;
@@ -4073,7 +4073,7 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
 {
        u32 reg;
        u16 data;
-       u8  retry = 0;
+       u8 retry = 0;
 
        if (hw->phy.type != e1000_phy_igp_3)
                return;
index a27e3bcc3249f129c71930d5f1966b4ccf732796..77f81cbb601a4b248f4018f76a3d6efbb94726bc 100644 (file)
@@ -1196,7 +1196,7 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
        while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
               (count < tx_ring->count)) {
                bool cleaned = false;
-               rmb(); /* read buffer_info after eop_desc */
+               rmb();          /* read buffer_info after eop_desc */
                for (; !cleaned; count++) {
                        tx_desc = E1000_TX_DESC(*tx_ring, i);
                        buffer_info = &tx_ring->buffer_info[i];
@@ -1385,7 +1385,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
 
                                skb_put(skb, l1);
                                goto copydone;
-                       } /* if */
+                       }       /* if */
                }
 
                for (j = 0; j < PS_PAGE_BUFFERS; j++) {
@@ -1800,7 +1800,7 @@ static irqreturn_t e1000_intr(int __always_unused irq, void *data)
        u32 rctl, icr = er32(ICR);
 
        if (!icr || test_bit(__E1000_DOWN, &adapter->state))
-               return IRQ_NONE;  /* Not our interrupt */
+               return IRQ_NONE;        /* Not our interrupt */
 
        /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
         * not set, then the adapter didn't send an interrupt
@@ -2487,7 +2487,7 @@ static unsigned int e1000_update_itr(u16 itr_setting, int packets, int bytes)
                else if ((packets < 5) && (bytes > 512))
                        retval = low_latency;
                break;
-       case low_latency:  /* 50 usec aka 20000 ints/s */
+       case low_latency:       /* 50 usec aka 20000 ints/s */
                if (bytes > 10000) {
                        /* this if handles the TSO accounting */
                        if (bytes / packets > 8000)
@@ -2502,7 +2502,7 @@ static unsigned int e1000_update_itr(u16 itr_setting, int packets, int bytes)
                        retval = lowest_latency;
                }
                break;
-       case bulk_latency: /* 250 usec aka 4000 ints/s */
+       case bulk_latency:      /* 250 usec aka 4000 ints/s */
                if (bytes > 25000) {
                        if (packets > 35)
                                retval = low_latency;
@@ -2554,7 +2554,7 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
                new_itr = 70000;
                break;
        case low_latency:
-               new_itr = 20000; /* aka hwitr = ~200 */
+               new_itr = 20000;        /* aka hwitr = ~200 */
                break;
        case bulk_latency:
                new_itr = 4000;
@@ -2673,7 +2673,7 @@ static int e1000e_poll(struct napi_struct *napi, int weight)
 }
 
 static int e1000_vlan_rx_add_vid(struct net_device *netdev,
-                                __be16 proto, u16 vid)
+                                __always_unused __be16 proto, u16 vid)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
@@ -2699,7 +2699,7 @@ static int e1000_vlan_rx_add_vid(struct net_device *netdev,
 }
 
 static int e1000_vlan_rx_kill_vid(struct net_device *netdev,
-                                 __be16 proto, u16 vid)
+                                 __always_unused __be16 proto, u16 vid)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
@@ -3104,13 +3104,13 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
                /* UPE and MPE will be handled by normal PROMISC logic
                 * in e1000e_set_rx_mode
                 */
-               rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
-                        E1000_RCTL_BAM | /* RX All Bcast Pkts */
-                        E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
+               rctl |= (E1000_RCTL_SBP |       /* Receive bad packets */
+                        E1000_RCTL_BAM |       /* RX All Bcast Pkts */
+                        E1000_RCTL_PMCF);      /* RX All MAC Ctrl Pkts */
 
-               rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */
-                         E1000_RCTL_DPF | /* Allow filtered pause */
-                         E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */
+               rctl &= ~(E1000_RCTL_VFE |      /* Disable VLAN filter */
+                         E1000_RCTL_DPF |      /* Allow filtered pause */
+                         E1000_RCTL_CFIEN);    /* Dis VLAN CFIEN Filter */
                /* Do not mess with E1000_CTRL_VME, it affects transmit as well,
                 * and that breaks VLANs.
                 */
@@ -3799,7 +3799,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
                hwm = min(((pba << 10) * 9 / 10),
                          ((pba << 10) - adapter->max_frame_size));
 
-               fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */
+               fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */
                fc->low_water = fc->high_water - 8;
                break;
        case e1000_pchlan:
@@ -3808,10 +3808,10 @@ void e1000e_reset(struct e1000_adapter *adapter)
                 */
                if (adapter->netdev->mtu > ETH_DATA_LEN) {
                        fc->high_water = 0x3500;
-                       fc->low_water  = 0x1500;
+                       fc->low_water = 0x1500;
                } else {
                        fc->high_water = 0x5000;
-                       fc->low_water  = 0x3000;
+                       fc->low_water = 0x3000;
                }
                fc->refresh_time = 0x1000;
                break;
@@ -4581,7 +4581,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
        adapter->stats.crcerrs += er32(CRCERRS);
        adapter->stats.gprc += er32(GPRC);
        adapter->stats.gorc += er32(GORCL);
-       er32(GORCH); /* Clear gorc */
+       er32(GORCH);            /* Clear gorc */
        adapter->stats.bprc += er32(BPRC);
        adapter->stats.mprc += er32(MPRC);
        adapter->stats.roc += er32(ROC);
@@ -4614,7 +4614,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
        adapter->stats.xofftxc += er32(XOFFTXC);
        adapter->stats.gptc += er32(GPTC);
        adapter->stats.gotc += er32(GOTCL);
-       er32(GOTCH); /* Clear gotc */
+       er32(GOTCH);            /* Clear gotc */
        adapter->stats.rnbc += er32(RNBC);
        adapter->stats.ruc += er32(RUC);
 
@@ -5106,13 +5106,13 @@ static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb)
        context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
        buffer_info = &tx_ring->buffer_info[i];
 
-       context_desc->lower_setup.ip_fields.ipcss  = ipcss;
-       context_desc->lower_setup.ip_fields.ipcso  = ipcso;
-       context_desc->lower_setup.ip_fields.ipcse  = cpu_to_le16(ipcse);
+       context_desc->lower_setup.ip_fields.ipcss = ipcss;
+       context_desc->lower_setup.ip_fields.ipcso = ipcso;
+       context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse);
        context_desc->upper_setup.tcp_fields.tucss = tucss;
        context_desc->upper_setup.tcp_fields.tucso = tucso;
        context_desc->upper_setup.tcp_fields.tucse = 0;
-       context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
+       context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss);
        context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
        context_desc->cmd_and_length = cpu_to_le32(cmd_length);
 
@@ -5363,7 +5363,7 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count)
 static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,
                                    struct sk_buff *skb)
 {
-       struct e1000_hw *hw =  &adapter->hw;
+       struct e1000_hw *hw = &adapter->hw;
        u16 length, offset;
 
        if (vlan_tx_tag_present(skb) &&
@@ -6259,7 +6259,7 @@ static void e1000_netpoll(struct net_device *netdev)
                e1000_intr_msi(adapter->pdev->irq, netdev);
                enable_irq(adapter->pdev->irq);
                break;
-       default: /* E1000E_INT_MODE_LEGACY */
+       default:                /* E1000E_INT_MODE_LEGACY */
                disable_irq(adapter->pdev->irq);
                e1000_intr(adapter->pdev->irq, netdev);
                enable_irq(adapter->pdev->irq);
@@ -6589,9 +6589,9 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T;
 
        /* construct the net_device struct */
-       netdev->netdev_ops              = &e1000e_netdev_ops;
+       netdev->netdev_ops = &e1000e_netdev_ops;
        e1000e_set_ethtool_ops(netdev);
-       netdev->watchdog_timeo          = 5 * HZ;
+       netdev->watchdog_timeo = 5 * HZ;
        netif_napi_add(netdev, &adapter->napi, e1000e_poll, 64);
        strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
 
@@ -7034,7 +7034,6 @@ static void __exit e1000_exit_module(void)
 }
 module_exit(e1000_exit_module);
 
-
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
 MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
 MODULE_LICENSE("GPL");
index 44ddc0a0ee0e4287ee17b6a389904aaedb9b226a..d70a03906ac0a0cecfb3f078fa584e376eae061a 100644 (file)
@@ -117,7 +117,6 @@ static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
        u16 data;
 
        eecd = er32(EECD);
-
        eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
        data = 0;
 
index 59c76a6815a0854edd9b38067b82dfcede1c9d10..da2be59505c06226b4cd79f9e8cc120945ca1d17 100644 (file)
@@ -1583,13 +1583,13 @@ s32 e1000e_check_downshift(struct e1000_hw *hw)
        case e1000_phy_gg82563:
        case e1000_phy_bm:
        case e1000_phy_82578:
-               offset  = M88E1000_PHY_SPEC_STATUS;
-               mask    = M88E1000_PSSR_DOWNSHIFT;
+               offset = M88E1000_PHY_SPEC_STATUS;
+               mask = M88E1000_PSSR_DOWNSHIFT;
                break;
        case e1000_phy_igp_2:
        case e1000_phy_igp_3:
-               offset  = IGP01E1000_PHY_LINK_HEALTH;
-               mask    = IGP01E1000_PLHR_SS_DOWNGRADE;
+               offset = IGP01E1000_PHY_LINK_HEALTH;
+               mask = IGP01E1000_PLHR_SS_DOWNGRADE;
                break;
        default:
                /* speed downshift not supported */
@@ -1653,14 +1653,14 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
 
        if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
            IGP01E1000_PSSR_SPEED_1000MBPS) {
-               offset  = IGP01E1000_PHY_PCS_INIT_REG;
-               mask    = IGP01E1000_PHY_POLARITY_MASK;
+               offset = IGP01E1000_PHY_PCS_INIT_REG;
+               mask = IGP01E1000_PHY_POLARITY_MASK;
        } else {
                /* This really only applies to 10Mbps since
                 * there is no polarity for 100Mbps (always 0).
                 */
-               offset  = IGP01E1000_PHY_PORT_STATUS;
-               mask    = IGP01E1000_PSSR_POLARITY_REVERSED;
+               offset = IGP01E1000_PHY_PORT_STATUS;
+               mask = IGP01E1000_PSSR_POLARITY_REVERSED;
        }
 
        ret_val = e1e_rphy(hw, offset, &data);
@@ -1900,7 +1900,7 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
 s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       s32  ret_val;
+       s32 ret_val;
        u16 phy_data;
        bool link;
 
@@ -2253,7 +2253,7 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
        case M88E1011_I_PHY_ID:
                phy_type = e1000_phy_m88;
                break;
-       case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */
+       case IGP01E1000_I_PHY_ID:       /* IGP 1 & 2 share this */
                phy_type = e1000_phy_igp_2;
                break;
        case GG82563_E_PHY_ID:
@@ -2317,7 +2317,7 @@ s32 e1000e_determine_phy_address(struct e1000_hw *hw)
                        /* If phy_type is valid, break - we found our
                         * PHY address
                         */
-                       if (phy_type  != e1000_phy_unknown)
+                       if (phy_type != e1000_phy_unknown)
                                return 0;
 
                        usleep_range(1000, 2000);
index ff6a17cb136280ec5547b128c74126e757f6bd52..f21a91a299a2200995be96c6a92dd05d80060c9b 100644 (file)
@@ -401,12 +401,82 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw)
        return 0;
 }
 
+/**
+ *  igb_set_sfp_media_type_82575 - derives SFP module media type.
+ *  @hw: pointer to the HW structure
+ *
+ *  The media type is chosen based on SFP module.
+ *  compatibility flags retrieved from SFP ID EEPROM.
+ **/
+static s32 igb_set_sfp_media_type_82575(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_ERR_CONFIG;
+       u32 ctrl_ext = 0;
+       struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+       struct e1000_sfp_flags *eth_flags = &dev_spec->eth_flags;
+       u8 tranceiver_type = 0;
+       s32 timeout = 3;
+
+       /* Turn I2C interface ON and power on sfp cage */
+       ctrl_ext = rd32(E1000_CTRL_EXT);
+       ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
+       wr32(E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA);
+
+       wrfl();
+
+       /* Read SFP module data */
+       while (timeout) {
+               ret_val = igb_read_sfp_data_byte(hw,
+                       E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET),
+                       &tranceiver_type);
+               if (ret_val == 0)
+                       break;
+               msleep(100);
+               timeout--;
+       }
+       if (ret_val != 0)
+               goto out;
+
+       ret_val = igb_read_sfp_data_byte(hw,
+                       E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET),
+                       (u8 *)eth_flags);
+       if (ret_val != 0)
+               goto out;
+
+       /* Check if there is some SFP module plugged and powered */
+       if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) ||
+           (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) {
+               dev_spec->module_plugged = true;
+               if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) {
+                       hw->phy.media_type = e1000_media_type_internal_serdes;
+               } else if (eth_flags->e100_base_fx) {
+                       dev_spec->sgmii_active = true;
+                       hw->phy.media_type = e1000_media_type_internal_serdes;
+               } else if (eth_flags->e1000_base_t) {
+                       dev_spec->sgmii_active = true;
+                       hw->phy.media_type = e1000_media_type_copper;
+               } else {
+                       hw->phy.media_type = e1000_media_type_unknown;
+                       hw_dbg("PHY module has not been recognized\n");
+                       goto out;
+               }
+       } else {
+               hw->phy.media_type = e1000_media_type_unknown;
+       }
+       ret_val = 0;
+out:
+       /* Restore I2C interface setting */
+       wr32(E1000_CTRL_EXT, ctrl_ext);
+       return ret_val;
+}
+
 static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        struct e1000_dev_spec_82575 * dev_spec = &hw->dev_spec._82575;
        s32 ret_val;
        u32 ctrl_ext = 0;
+       u32 link_mode = 0;
 
        switch (hw->device_id) {
        case E1000_DEV_ID_82575EB_COPPER:
@@ -470,15 +540,55 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
         */
        hw->phy.media_type = e1000_media_type_copper;
        dev_spec->sgmii_active = false;
+       dev_spec->module_plugged = false;
 
        ctrl_ext = rd32(E1000_CTRL_EXT);
-       switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
-       case E1000_CTRL_EXT_LINK_MODE_SGMII:
-               dev_spec->sgmii_active = true;
-               break;
+
+       link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK;
+       switch (link_mode) {
        case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
-       case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
                hw->phy.media_type = e1000_media_type_internal_serdes;
+               break;
+       case E1000_CTRL_EXT_LINK_MODE_SGMII:
+               /* Get phy control interface type set (MDIO vs. I2C)*/
+               if (igb_sgmii_uses_mdio_82575(hw)) {
+                       hw->phy.media_type = e1000_media_type_copper;
+                       dev_spec->sgmii_active = true;
+                       break;
+               }
+               /* fall through for I2C based SGMII */
+       case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
+               /* read media type from SFP EEPROM */
+               ret_val = igb_set_sfp_media_type_82575(hw);
+               if ((ret_val != 0) ||
+                   (hw->phy.media_type == e1000_media_type_unknown)) {
+                       /* If media type was not identified then return media
+                        * type defined by the CTRL_EXT settings.
+                        */
+                       hw->phy.media_type = e1000_media_type_internal_serdes;
+
+                       if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) {
+                               hw->phy.media_type = e1000_media_type_copper;
+                               dev_spec->sgmii_active = true;
+                       }
+
+                       break;
+               }
+
+               /* do not change link mode for 100BaseFX */
+               if (dev_spec->eth_flags.e100_base_fx)
+                       break;
+
+               /* change current link mode setting */
+               ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
+
+               if (hw->phy.media_type == e1000_media_type_copper)
+                       ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII;
+               else
+                       ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
+
+               wr32(E1000_CTRL_EXT, ctrl_ext);
+
                break;
        default:
                break;
index 31a0f82cc650b9ae1eca5940d2f939632c337dcc..aa201abb8ad2809aeadbfbea73f00bc4f913e132 100644 (file)
 /* Clear Interrupt timers after IMS clear */
 /* packet buffer parity error detection enabled */
 /* descriptor FIFO parity error detection enable */
-#define E1000_CTRL_EXT_PBA_CLR        0x80000000 /* PBA Clear */
-#define E1000_I2CCMD_REG_ADDR_SHIFT   16
-#define E1000_I2CCMD_PHY_ADDR_SHIFT   24
-#define E1000_I2CCMD_OPCODE_READ      0x08000000
-#define E1000_I2CCMD_OPCODE_WRITE     0x00000000
-#define E1000_I2CCMD_READY            0x20000000
-#define E1000_I2CCMD_ERROR            0x80000000
-#define E1000_MAX_SGMII_PHY_REG_ADDR  255
-#define E1000_I2CCMD_PHY_TIMEOUT      200
-#define E1000_IVAR_VALID              0x80
-#define E1000_GPIE_NSICR              0x00000001
-#define E1000_GPIE_MSIX_MODE          0x00000010
-#define E1000_GPIE_EIAME              0x40000000
-#define E1000_GPIE_PBA                0x80000000
+#define E1000_CTRL_EXT_PBA_CLR         0x80000000 /* PBA Clear */
+#define E1000_I2CCMD_REG_ADDR_SHIFT    16
+#define E1000_I2CCMD_PHY_ADDR_SHIFT    24
+#define E1000_I2CCMD_OPCODE_READ       0x08000000
+#define E1000_I2CCMD_OPCODE_WRITE      0x00000000
+#define E1000_I2CCMD_READY             0x20000000
+#define E1000_I2CCMD_ERROR             0x80000000
+#define E1000_I2CCMD_SFP_DATA_ADDR(a)  (0x0000 + (a))
+#define E1000_I2CCMD_SFP_DIAG_ADDR(a)  (0x0100 + (a))
+#define E1000_MAX_SGMII_PHY_REG_ADDR   255
+#define E1000_I2CCMD_PHY_TIMEOUT       200
+#define E1000_IVAR_VALID               0x80
+#define E1000_GPIE_NSICR               0x00000001
+#define E1000_GPIE_MSIX_MODE           0x00000010
+#define E1000_GPIE_EIAME               0x40000000
+#define E1000_GPIE_PBA                 0x80000000
 
 /* Receive Descriptor bit definitions */
 #define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
 #define AUTONEG_ADVERTISE_SPEED_DEFAULT   E1000_ALL_SPEED_DUPLEX
 
 /* LED Control */
-#define E1000_LEDCTL_LED0_MODE_SHIFT      0
-#define E1000_LEDCTL_LED0_BLINK           0x00000080
+#define E1000_LEDCTL_LED0_MODE_SHIFT   0
+#define E1000_LEDCTL_LED0_BLINK                0x00000080
+#define E1000_LEDCTL_LED0_MODE_MASK    0x0000000F
+#define E1000_LEDCTL_LED0_IVRT         0x00000040
 
 #define E1000_LEDCTL_MODE_LED_ON        0xE
 #define E1000_LEDCTL_MODE_LED_OFF       0xF
index 488abb24a54f9f5d3cdb91e2df45f464a03ecdea..94d7866b9c2086b4d0919711a7b6eec2f889bf20 100644 (file)
@@ -528,6 +528,8 @@ struct e1000_dev_spec_82575 {
        bool global_device_reset;
        bool eee_disable;
        bool clear_semaphore_once;
+       struct e1000_sfp_flags eth_flags;
+       bool module_plugged;
 };
 
 struct e1000_hw {
index bfc08e05c90741849d3445cbca337f98d466db2d..5caa332e7556628806491b186ada8e43ec88abf0 100644 (file)
@@ -82,11 +82,11 @@ enum E1000_INVM_STRUCTURE_TYPE {
 #define E1000_INVM_MAJOR_SHIFT         4
 
 #define ID_LED_DEFAULT_I210            ((ID_LED_OFF1_ON2  << 8) | \
-                                        (ID_LED_OFF1_OFF2 <<  4) | \
-                                        (ID_LED_DEF1_DEF2))
+                                        (ID_LED_DEF1_DEF2 <<  4) | \
+                                        (ID_LED_OFF1_OFF2))
 #define ID_LED_DEFAULT_I210_SERDES     ((ID_LED_DEF1_DEF2 << 8) | \
                                         (ID_LED_DEF1_DEF2 <<  4) | \
-                                        (ID_LED_DEF1_DEF2))
+                                        (ID_LED_OFF1_ON2))
 
 /* NVM offset defaults for i211 device */
 #define NVM_INIT_CTRL_2_DEFAULT_I211   0X7243
index 2559d70a2321b717b05b167a2c1c3a5b4f9f44a6..bab556a47fcc48cdb7d90a044f582ef18c335be0 100644 (file)
@@ -1332,7 +1332,13 @@ s32 igb_id_led_init(struct e1000_hw *hw)
        u16 data, i, temp;
        const u16 led_mask = 0x0F;
 
-       ret_val = igb_valid_led_default(hw, &data);
+       /* i210 and i211 devices have different LED mechanism */
+       if ((hw->mac.type == e1000_i210) ||
+           (hw->mac.type == e1000_i211))
+               ret_val = igb_valid_led_default_i210(hw, &data);
+       else
+               ret_val = igb_valid_led_default(hw, &data);
+
        if (ret_val)
                goto out;
 
@@ -1406,15 +1412,34 @@ s32 igb_blink_led(struct e1000_hw *hw)
        u32 ledctl_blink = 0;
        u32 i;
 
-       /* set the blink bit for each LED that's "on" (0x0E)
-        * in ledctl_mode2
-        */
-       ledctl_blink = hw->mac.ledctl_mode2;
-       for (i = 0; i < 4; i++)
-               if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
-                   E1000_LEDCTL_MODE_LED_ON)
-                       ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<
-                                        (i * 8));
+       if (hw->phy.media_type == e1000_media_type_fiber) {
+               /* always blink LED0 for PCI-E fiber */
+               ledctl_blink = E1000_LEDCTL_LED0_BLINK |
+                    (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
+       } else {
+               /* Set the blink bit for each LED that's "on" (0x0E)
+                * (or "off" if inverted) in ledctl_mode2.  The blink
+                * logic in hardware only works when mode is set to "on"
+                * so it must be changed accordingly when the mode is
+                * "off" and inverted.
+                */
+               ledctl_blink = hw->mac.ledctl_mode2;
+               for (i = 0; i < 32; i += 8) {
+                       u32 mode = (hw->mac.ledctl_mode2 >> i) &
+                           E1000_LEDCTL_LED0_MODE_MASK;
+                       u32 led_default = hw->mac.ledctl_default >> i;
+
+                       if ((!(led_default & E1000_LEDCTL_LED0_IVRT) &&
+                            (mode == E1000_LEDCTL_MODE_LED_ON)) ||
+                           ((led_default & E1000_LEDCTL_LED0_IVRT) &&
+                            (mode == E1000_LEDCTL_MODE_LED_OFF))) {
+                               ledctl_blink &=
+                                   ~(E1000_LEDCTL_LED0_MODE_MASK << i);
+                               ledctl_blink |= (E1000_LEDCTL_LED0_BLINK |
+                                                E1000_LEDCTL_MODE_LED_ON) << i;
+                       }
+               }
+       }
 
        wr32(E1000_LEDCTL, ledctl_blink);
 
index 115b0da6e01337d528f8b59dd9a02a097b15d2b1..1d6a401cc5d4ba254cd1ca8cc133450bbf8a625c 100644 (file)
@@ -340,6 +340,130 @@ s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
        return 0;
 }
 
+/**
+ *  igb_read_sfp_data_byte - Reads SFP module data.
+ *  @hw: pointer to the HW structure
+ *  @offset: byte location offset to be read
+ *  @data: read data buffer pointer
+ *
+ *  Reads one byte from SFP module data stored
+ *  in SFP resided EEPROM memory or SFP diagnostic area.
+ *  Function should be called with
+ *  E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
+ *  E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
+ *  access
+ **/
+s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data)
+{
+       u32 i = 0;
+       u32 i2ccmd = 0;
+       u32 data_local = 0;
+
+       if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
+               hw_dbg("I2CCMD command address exceeds upper limit\n");
+               return -E1000_ERR_PHY;
+       }
+
+       /* Set up Op-code, EEPROM Address,in the I2CCMD
+        * register. The MAC will take care of interfacing with the
+        * EEPROM to retrieve the desired data.
+        */
+       i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+                 E1000_I2CCMD_OPCODE_READ);
+
+       wr32(E1000_I2CCMD, i2ccmd);
+
+       /* Poll the ready bit to see if the I2C read completed */
+       for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
+               udelay(50);
+               data_local = rd32(E1000_I2CCMD);
+               if (data_local & E1000_I2CCMD_READY)
+                       break;
+       }
+       if (!(data_local & E1000_I2CCMD_READY)) {
+               hw_dbg("I2CCMD Read did not complete\n");
+               return -E1000_ERR_PHY;
+       }
+       if (data_local & E1000_I2CCMD_ERROR) {
+               hw_dbg("I2CCMD Error bit set\n");
+               return -E1000_ERR_PHY;
+       }
+       *data = (u8) data_local & 0xFF;
+
+       return 0;
+}
+
+/**
+ *  e1000_write_sfp_data_byte - Writes SFP module data.
+ *  @hw: pointer to the HW structure
+ *  @offset: byte location offset to write to
+ *  @data: data to write
+ *
+ *  Writes one byte to SFP module data stored
+ *  in SFP resided EEPROM memory or SFP diagnostic area.
+ *  Function should be called with
+ *  E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
+ *  E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
+ *  access
+ **/
+s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
+{
+       u32 i = 0;
+       u32 i2ccmd = 0;
+       u32 data_local = 0;
+
+       if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
+               hw_dbg("I2CCMD command address exceeds upper limit\n");
+               return -E1000_ERR_PHY;
+       }
+       /* The programming interface is 16 bits wide
+        * so we need to read the whole word first
+        * then update appropriate byte lane and write
+        * the updated word back.
+        */
+       /* Set up Op-code, EEPROM Address,in the I2CCMD
+        * register. The MAC will take care of interfacing
+        * with an EEPROM to write the data given.
+        */
+       i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+                 E1000_I2CCMD_OPCODE_READ);
+       /* Set a command to read single word */
+       wr32(E1000_I2CCMD, i2ccmd);
+       for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
+               udelay(50);
+               /* Poll the ready bit to see if lastly
+                * launched I2C operation completed
+                */
+               i2ccmd = rd32(E1000_I2CCMD);
+               if (i2ccmd & E1000_I2CCMD_READY) {
+                       /* Check if this is READ or WRITE phase */
+                       if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) ==
+                           E1000_I2CCMD_OPCODE_READ) {
+                               /* Write the selected byte
+                                * lane and update whole word
+                                */
+                               data_local = i2ccmd & 0xFF00;
+                               data_local |= data;
+                               i2ccmd = ((offset <<
+                                       E1000_I2CCMD_REG_ADDR_SHIFT) |
+                                       E1000_I2CCMD_OPCODE_WRITE | data_local);
+                               wr32(E1000_I2CCMD, i2ccmd);
+                       } else {
+                               break;
+                       }
+               }
+       }
+       if (!(i2ccmd & E1000_I2CCMD_READY)) {
+               hw_dbg("I2CCMD Write did not complete\n");
+               return -E1000_ERR_PHY;
+       }
+       if (i2ccmd & E1000_I2CCMD_ERROR) {
+               hw_dbg("I2CCMD Error bit set\n");
+               return -E1000_ERR_PHY;
+       }
+       return 0;
+}
+
 /**
  *  igb_read_phy_reg_igp - Read igp PHY register
  *  @hw: pointer to the HW structure
index 784fd1c40989fc86bbdb5d750bc61f5cd40da187..6a0873f2095a49affef31c68ced1dd0d785aa265 100644 (file)
@@ -69,6 +69,8 @@ s32  igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
 s32  igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
+s32  igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data);
+s32  e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data);
 s32  igb_copper_link_setup_82580(struct e1000_hw *hw);
 s32  igb_get_phy_info_82580(struct e1000_hw *hw);
 s32  igb_phy_force_speed_duplex_82580(struct e1000_hw *hw);
@@ -157,4 +159,22 @@ s32  igb_check_polarity_m88(struct e1000_hw *hw);
 #define GS40G_CS_POWER_DOWN            0x0002
 #define GS40G_LINE_LB                  0x4000
 
+/* SFP modules ID memory locations */
+#define E1000_SFF_IDENTIFIER_OFFSET    0x00
+#define E1000_SFF_IDENTIFIER_SFF       0x02
+#define E1000_SFF_IDENTIFIER_SFP       0x03
+
+#define E1000_SFF_ETH_FLAGS_OFFSET     0x06
+/* Flags for SFP modules compatible with ETH up to 1Gb */
+struct e1000_sfp_flags {
+       u8 e1000_base_sx:1;
+       u8 e1000_base_lx:1;
+       u8 e1000_base_cx:1;
+       u8 e1000_base_t:1;
+       u8 e100_base_lx:1;
+       u8 e100_base_fx:1;
+       u8 e10_base_bx10:1;
+       u8 e10_base_px:1;
+};
+
 #endif
index 9d6c075e232d9c5c2885cebcfa58c297e03b049e..15ea8dc9dad3dc1c5c86e6682882802da574d9d3 100644 (file)
@@ -322,11 +322,6 @@ static inline int igb_desc_unused(struct igb_ring *ring)
        return ring->count + ring->next_to_clean - ring->next_to_use - 1;
 }
 
-struct igb_i2c_client_list {
-       struct i2c_client *client;
-       struct igb_i2c_client_list *next;
-};
-
 #ifdef CONFIG_IGB_HWMON
 
 #define IGB_HWMON_TYPE_LOC     0
@@ -514,13 +509,18 @@ extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
 extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
                                unsigned char *va,
                                struct sk_buff *skb);
-static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
+static inline void igb_ptp_rx_hwtstamp(struct igb_ring *rx_ring,
                                       union e1000_adv_rx_desc *rx_desc,
                                       struct sk_buff *skb)
 {
        if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) &&
            !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))
-               igb_ptp_rx_rgtstamp(q_vector, skb);
+               igb_ptp_rx_rgtstamp(rx_ring->q_vector, skb);
+
+       /* Update the last_rx_timestamp timer in order to enable watchdog check
+        * for error case of latched timestamp on a dropped packet.
+        */
+       rx_ring->last_rx_timestamp = jiffies;
 }
 
 extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
index 7876240fa74e27c16e759168ed662750aae4c66a..85fe7b52f435cf9444cab5d1c466e9e604e3f40b 100644 (file)
@@ -142,6 +142,8 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
+       struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+       struct e1000_sfp_flags *eth_flags = &dev_spec->eth_flags;
        u32 status;
 
        if (hw->phy.media_type == e1000_media_type_copper) {
@@ -162,49 +164,26 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                        ecmd->advertising |= hw->phy.autoneg_advertised;
                }
 
-               if (hw->mac.autoneg != 1)
-                       ecmd->advertising &= ~(ADVERTISED_Pause |
-                                              ADVERTISED_Asym_Pause);
-
-               if (hw->fc.requested_mode == e1000_fc_full)
-                       ecmd->advertising |= ADVERTISED_Pause;
-               else if (hw->fc.requested_mode == e1000_fc_rx_pause)
-                       ecmd->advertising |= (ADVERTISED_Pause |
-                                             ADVERTISED_Asym_Pause);
-               else if (hw->fc.requested_mode == e1000_fc_tx_pause)
-                       ecmd->advertising |=  ADVERTISED_Asym_Pause;
-               else
-                       ecmd->advertising &= ~(ADVERTISED_Pause |
-                                              ADVERTISED_Asym_Pause);
-
                ecmd->port = PORT_TP;
                ecmd->phy_address = hw->phy.addr;
                ecmd->transceiver = XCVR_INTERNAL;
        } else {
-               ecmd->supported = (SUPPORTED_1000baseT_Full |
-                                  SUPPORTED_100baseT_Full |
-                                  SUPPORTED_FIBRE |
+               ecmd->supported = (SUPPORTED_FIBRE |
                                   SUPPORTED_Autoneg |
                                   SUPPORTED_Pause);
-               if (hw->mac.type == e1000_i354)
-                               ecmd->supported |= SUPPORTED_2500baseX_Full;
-
                ecmd->advertising = ADVERTISED_FIBRE;
-
-               switch (adapter->link_speed) {
-               case SPEED_2500:
-                       ecmd->advertising = ADVERTISED_2500baseX_Full;
-                       break;
-               case SPEED_1000:
-                       ecmd->advertising = ADVERTISED_1000baseT_Full;
-                       break;
-               case SPEED_100:
-                       ecmd->advertising = ADVERTISED_100baseT_Full;
-                       break;
-               default:
-                       break;
+               if (hw->mac.type == e1000_i354) {
+                       ecmd->supported |= SUPPORTED_2500baseX_Full;
+                       ecmd->advertising |= ADVERTISED_2500baseX_Full;
+               }
+               if ((eth_flags->e1000_base_lx) || (eth_flags->e1000_base_sx)) {
+                       ecmd->supported |= SUPPORTED_1000baseT_Full;
+                       ecmd->advertising |= ADVERTISED_1000baseT_Full;
+               }
+               if (eth_flags->e100_base_fx) {
+                       ecmd->supported |= SUPPORTED_100baseT_Full;
+                       ecmd->advertising |= ADVERTISED_100baseT_Full;
                }
-
                if (hw->mac.autoneg == 1)
                        ecmd->advertising |= ADVERTISED_Autoneg;
 
@@ -212,6 +191,21 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                ecmd->transceiver = XCVR_EXTERNAL;
        }
 
+       if (hw->mac.autoneg != 1)
+               ecmd->advertising &= ~(ADVERTISED_Pause |
+                                      ADVERTISED_Asym_Pause);
+
+       if (hw->fc.requested_mode == e1000_fc_full)
+               ecmd->advertising |= ADVERTISED_Pause;
+       else if (hw->fc.requested_mode == e1000_fc_rx_pause)
+               ecmd->advertising |= (ADVERTISED_Pause |
+                                     ADVERTISED_Asym_Pause);
+       else if (hw->fc.requested_mode == e1000_fc_tx_pause)
+               ecmd->advertising |=  ADVERTISED_Asym_Pause;
+       else
+               ecmd->advertising &= ~(ADVERTISED_Pause |
+                                      ADVERTISED_Asym_Pause);
+
        status = rd32(E1000_STATUS);
 
        if (status & E1000_STATUS_LU) {
@@ -392,6 +386,10 @@ static int igb_set_pauseparam(struct net_device *netdev,
        struct e1000_hw *hw = &adapter->hw;
        int retval = 0;
 
+       /* 100basefx does not support setting link flow control */
+       if (hw->dev_spec._82575.eth_flags.e100_base_fx)
+               return -EINVAL;
+
        adapter->fc_autoneg = pause->autoneg;
 
        while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
@@ -813,10 +811,8 @@ static int igb_set_eeprom(struct net_device *netdev,
        ret_val = hw->nvm.ops.write(hw, first_word,
                                    last_word - first_word + 1, eeprom_buff);
 
-       /* Update the checksum over the first part of the EEPROM if needed
-        * and flush shadow RAM for 82573 controllers
-        */
-       if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG)))
+       /* Update the checksum if nvm write succeeded */
+       if (ret_val == 0)
                hw->nvm.ops.update(hw);
 
        igb_set_fw_version(adapter);
index 64cbe0dfe04347aff1af3fd15f5eb130caefaff6..6a0c1b66ce54116b88a8aaf33bcf0518a7ef7ca3 100644 (file)
@@ -1667,10 +1667,13 @@ void igb_down(struct igb_adapter *adapter)
        wrfl();
        msleep(10);
 
-       for (i = 0; i < adapter->num_q_vectors; i++)
+       igb_irq_disable(adapter);
+
+       for (i = 0; i < adapter->num_q_vectors; i++) {
+               napi_synchronize(&(adapter->q_vector[i]->napi));
                napi_disable(&(adapter->q_vector[i]->napi));
+       }
 
-       igb_irq_disable(adapter);
 
        del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
@@ -6622,7 +6625,7 @@ static void igb_process_skb_fields(struct igb_ring *rx_ring,
 
        igb_rx_checksum(rx_ring, rx_desc, skb);
 
-       igb_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb);
+       igb_ptp_rx_hwtstamp(rx_ring, rx_desc, skb);
 
        if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
            igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
index 1f2c805684dd3ee46027d49ca8289b8d4d63b4e9..e055e000131bdcf0c32280270361c957d0a4d8a0 100644 (file)
@@ -380,3 +380,26 @@ s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw,
        }
        return 0;
 }
+
+static void ixgbe_dcb_read_rtrup2tc_82599(struct ixgbe_hw *hw, u8 *map)
+{
+       u32 reg, i;
+
+       reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC);
+       for (i = 0; i < MAX_USER_PRIORITY; i++)
+               map[i] = IXGBE_RTRUP2TC_UP_MASK &
+                       (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT));
+       return;
+}
+
+void ixgbe_dcb_read_rtrup2tc(struct ixgbe_hw *hw, u8 *map)
+{
+       switch (hw->mac.type) {
+       case ixgbe_mac_82599EB:
+       case ixgbe_mac_X540:
+               ixgbe_dcb_read_rtrup2tc_82599(hw, map);
+               break;
+       default:
+               break;
+       }
+}
index 1634de8b627f179a99b3836b37bd69af54fbbfaf..fc0a2dd5249956bf19ba836bad5c2d92d61b1b60 100644 (file)
@@ -159,6 +159,8 @@ s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw, u16 *refill, u16 *max,
 s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *tc_prio);
 s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *);
 
+void ixgbe_dcb_read_rtrup2tc(struct ixgbe_hw *hw, u8 *map);
+
 /* DCB definitions for credit calculation */
 #define DCB_CREDIT_QUANTUM     64   /* DCB Quantum */
 #define MAX_CREDIT_REFILL       511  /* 0x1FF * 64B = 32704B */
index a4ef07631d1e349aafd5d8f0a110acdafdccd279..d71d9ce3e394b4199f297ebbcb493fa268092dd2 100644 (file)
@@ -45,6 +45,7 @@
 
 /* Receive UP2TC mapping */
 #define IXGBE_RTRUP2TC_UP_SHIFT 3
+#define IXGBE_RTRUP2TC_UP_MASK 7
 /* Transmit UP2TC mapping */
 #define IXGBE_RTTUP2TC_UP_SHIFT 3
 
index f3d68f9696ba0b9b6e430ec38574bd3472b75bce..edd89a1ef27f67f0f40d0cefba9ebed3e39f3185 100644 (file)
@@ -554,6 +554,9 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
                for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
                        adapter->ixgbe_ieee_ets->prio_tc[i] =
                                IEEE_8021QAZ_MAX_TCS;
+               /* if possible update UP2TC mappings from HW */
+               ixgbe_dcb_read_rtrup2tc(&adapter->hw,
+                                       adapter->ixgbe_ieee_ets->prio_tc);
        }
 
        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
index 070a6f1a057745a803d3a6ccd6d8201644e95703..7fbe6abf60542fe483170eb807f6f16f2e563cad 100644 (file)
@@ -3148,7 +3148,6 @@ jme_init_one(struct pci_dev *pdev,
        jme->mii_if.mdio_write = jme_mdio_write;
 
        jme_clear_pm(jme);
-       pci_set_power_state(jme->pdev, PCI_D0);
        device_set_wakeup_enable(&pdev->dev, true);
 
        jme_set_phyfifo_5level(jme);
index 5409fe876a441607488d43ac39829f7e5fc9e891..64646eb39e8bc23f31454041e68959bf0b4e6f32 100644 (file)
@@ -495,12 +495,9 @@ static void korina_multicast_list(struct net_device *dev)
 
        /* Build the hash table */
        if (netdev_mc_count(dev) > 4) {
-               u16 hash_table[4];
+               u16 hash_table[4] = { 0 };
                u32 crc;
 
-               for (i = 0; i < 4; i++)
-                       hash_table[i] = 0;
-
                netdev_for_each_mc_addr(ha, dev) {
                        crc = ether_crc_le(6, ha->addr);
                        crc >>= 26;
@@ -1214,7 +1211,6 @@ static int korina_remove(struct platform_device *pdev)
        iounmap(lp->rx_dma_regs);
        iounmap(lp->tx_dma_regs);
 
-       platform_set_drvdata(pdev, NULL);
        unregister_netdev(bif->dev);
        free_netdev(bif->dev);
 
index 2ad1494efbb3021e796481da6c4f48f21e63ca30..c7f9fb33ce9525f939d637425c075bece69a6da3 100644 (file)
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_net.h>
+#include <linux/of_mdio.h>
 
 static char mv643xx_eth_driver_name[] = "mv643xx_eth";
 static char mv643xx_eth_driver_version[] = "1.4";
@@ -115,6 +119,8 @@ static char mv643xx_eth_driver_version[] = "1.4";
 #define  LINK_UP                       0x00000002
 #define TXQ_COMMAND                    0x0048
 #define TXQ_FIX_PRIO_CONF              0x004c
+#define PORT_SERIAL_CONTROL1           0x004c
+#define  CLK125_BYPASS_EN              0x00000010
 #define TX_BW_RATE                     0x0050
 #define TX_BW_MTU                      0x0058
 #define TX_BW_BURST                    0x005c
@@ -2450,13 +2456,150 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
        }
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id mv643xx_eth_shared_ids[] = {
+       { .compatible = "marvell,orion-eth", },
+       { .compatible = "marvell,kirkwood-eth", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mv643xx_eth_shared_ids);
+#endif
+
+#if defined(CONFIG_OF) && !defined(CONFIG_MV64X60)
+#define mv643xx_eth_property(_np, _name, _v)                           \
+       do {                                                            \
+               u32 tmp;                                                \
+               if (!of_property_read_u32(_np, "marvell," _name, &tmp)) \
+                       _v = tmp;                                       \
+       } while (0)
+
+static struct platform_device *port_platdev[3];
+
+static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
+                                         struct device_node *pnp)
+{
+       struct platform_device *ppdev;
+       struct mv643xx_eth_platform_data ppd;
+       struct resource res;
+       const char *mac_addr;
+       int ret;
+
+       memset(&ppd, 0, sizeof(ppd));
+       ppd.shared = pdev;
+
+       memset(&res, 0, sizeof(res));
+       if (!of_irq_to_resource(pnp, 0, &res)) {
+               dev_err(&pdev->dev, "missing interrupt on %s\n", pnp->name);
+               return -EINVAL;
+       }
+
+       if (of_property_read_u32(pnp, "reg", &ppd.port_number)) {
+               dev_err(&pdev->dev, "missing reg property on %s\n", pnp->name);
+               return -EINVAL;
+       }
+
+       if (ppd.port_number >= 3) {
+               dev_err(&pdev->dev, "invalid reg property on %s\n", pnp->name);
+               return -EINVAL;
+       }
+
+       mac_addr = of_get_mac_address(pnp);
+       if (mac_addr)
+               memcpy(ppd.mac_addr, mac_addr, 6);
+
+       mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size);
+       mv643xx_eth_property(pnp, "tx-sram-addr", ppd.tx_sram_addr);
+       mv643xx_eth_property(pnp, "tx-sram-size", ppd.tx_sram_size);
+       mv643xx_eth_property(pnp, "rx-queue-size", ppd.rx_queue_size);
+       mv643xx_eth_property(pnp, "rx-sram-addr", ppd.rx_sram_addr);
+       mv643xx_eth_property(pnp, "rx-sram-size", ppd.rx_sram_size);
+
+       ppd.phy_node = of_parse_phandle(pnp, "phy-handle", 0);
+       if (!ppd.phy_node) {
+               ppd.phy_addr = MV643XX_ETH_PHY_NONE;
+               of_property_read_u32(pnp, "speed", &ppd.speed);
+               of_property_read_u32(pnp, "duplex", &ppd.duplex);
+       }
+
+       ppdev = platform_device_alloc(MV643XX_ETH_NAME, ppd.port_number);
+       if (!ppdev)
+               return -ENOMEM;
+       ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+       ret = platform_device_add_resources(ppdev, &res, 1);
+       if (ret)
+               goto port_err;
+
+       ret = platform_device_add_data(ppdev, &ppd, sizeof(ppd));
+       if (ret)
+               goto port_err;
+
+       ret = platform_device_add(ppdev);
+       if (ret)
+               goto port_err;
+
+       port_platdev[ppd.port_number] = ppdev;
+
+       return 0;
+
+port_err:
+       platform_device_put(ppdev);
+       return ret;
+}
+
+static int mv643xx_eth_shared_of_probe(struct platform_device *pdev)
+{
+       struct mv643xx_eth_shared_platform_data *pd;
+       struct device_node *pnp, *np = pdev->dev.of_node;
+       int ret;
+
+       /* bail out if not registered from DT */
+       if (!np)
+               return 0;
+
+       pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd)
+               return -ENOMEM;
+       pdev->dev.platform_data = pd;
+
+       mv643xx_eth_property(np, "tx-checksum-limit", pd->tx_csum_limit);
+
+       for_each_available_child_of_node(np, pnp) {
+               ret = mv643xx_eth_shared_of_add_port(pdev, pnp);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static void mv643xx_eth_shared_of_remove(void)
+{
+       int n;
+
+       for (n = 0; n < 3; n++) {
+               platform_device_del(port_platdev[n]);
+               port_platdev[n] = NULL;
+       }
+}
+#else
+static inline int mv643xx_eth_shared_of_probe(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static inline void mv643xx_eth_shared_of_remove(void)
+{
+}
+#endif
+
 static int mv643xx_eth_shared_probe(struct platform_device *pdev)
 {
        static int mv643xx_eth_version_printed;
-       struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
+       struct mv643xx_eth_shared_platform_data *pd;
        struct mv643xx_eth_shared_private *msp;
        const struct mbus_dram_target_info *dram;
        struct resource *res;
+       int ret;
 
        if (!mv643xx_eth_version_printed++)
                pr_notice("MV-643xx 10/100/1000 ethernet driver version %s\n",
@@ -2469,8 +2612,9 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
        msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL);
        if (msp == NULL)
                return -ENOMEM;
+       platform_set_drvdata(pdev, msp);
 
-       msp->base = ioremap(res->start, resource_size(res));
+       msp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (msp->base == NULL)
                return -ENOMEM;
 
@@ -2485,12 +2629,15 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
        if (dram)
                mv643xx_eth_conf_mbus_windows(msp, dram);
 
+       ret = mv643xx_eth_shared_of_probe(pdev);
+       if (ret)
+               return ret;
+       pd = pdev->dev.platform_data;
+
        msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ?
                                        pd->tx_csum_limit : 9 * 1024;
        infer_hw_params(msp);
 
-       platform_set_drvdata(pdev, msp);
-
        return 0;
 }
 
@@ -2498,10 +2645,9 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev)
 {
        struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
 
-       iounmap(msp->base);
+       mv643xx_eth_shared_of_remove();
        if (!IS_ERR(msp->clk))
                clk_disable_unprepare(msp->clk);
-
        return 0;
 }
 
@@ -2511,6 +2657,7 @@ static struct platform_driver mv643xx_eth_shared_driver = {
        .driver = {
                .name   = MV643XX_ETH_SHARED_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(mv643xx_eth_shared_ids),
        },
 };
 
@@ -2701,6 +2848,15 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 
        mp->dev = dev;
 
+       /* Kirkwood resets some registers on gated clocks. Especially
+        * CLK125_BYPASS_EN must be cleared but is not available on
+        * all other SoCs/System Controllers using this driver.
+        */
+       if (of_device_is_compatible(pdev->dev.of_node,
+                                   "marvell,kirkwood-eth-port"))
+               wrlp(mp, PORT_SERIAL_CONTROL1,
+                    rdlp(mp, PORT_SERIAL_CONTROL1) & ~CLK125_BYPASS_EN);
+
        /*
         * Start with a default rate, and if there is a clock, allow
         * it to override the default.
@@ -2710,23 +2866,35 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        if (!IS_ERR(mp->clk)) {
                clk_prepare_enable(mp->clk);
                mp->t_clk = clk_get_rate(mp->clk);
+       } else if (!IS_ERR(mp->shared->clk)) {
+               mp->t_clk = clk_get_rate(mp->shared->clk);
        }
 
        set_params(mp, pd);
        netif_set_real_num_tx_queues(dev, mp->txq_count);
        netif_set_real_num_rx_queues(dev, mp->rxq_count);
 
-       if (pd->phy_addr != MV643XX_ETH_PHY_NONE) {
+       err = 0;
+       if (pd->phy_node) {
+               mp->phy = of_phy_connect(mp->dev, pd->phy_node,
+                                        mv643xx_eth_adjust_link, 0,
+                                        PHY_INTERFACE_MODE_GMII);
+               if (!mp->phy)
+                       err = -ENODEV;
+       } else if (pd->phy_addr != MV643XX_ETH_PHY_NONE) {
                mp->phy = phy_scan(mp, pd->phy_addr);
 
-               if (IS_ERR(mp->phy)) {
+               if (IS_ERR(mp->phy))
                        err = PTR_ERR(mp->phy);
-                       if (err == -ENODEV)
-                               err = -EPROBE_DEFER;
-                       goto out;
-               }
-               phy_init(mp, pd->speed, pd->duplex);
+               else
+                       phy_init(mp, pd->speed, pd->duplex);
        }
+       if (err == -ENODEV) {
+               err = -EPROBE_DEFER;
+               goto out;
+       }
+       if (err)
+               goto out;
 
        SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops);
 
@@ -2805,7 +2973,7 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
 
        unregister_netdev(mp->dev);
        if (mp->phy != NULL)
-               phy_detach(mp->phy);
+               phy_disconnect(mp->phy);
        cancel_work_sync(&mp->tx_timeout_task);
 
        if (!IS_ERR(mp->clk))
@@ -2813,8 +2981,6 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
 
        free_netdev(mp->dev);
 
-       platform_set_drvdata(pdev, NULL);
-
        return 0;
 }
 
index c96678555233c4afc1336c012c17c3b0da943060..712779fb12b7d80416db0a4349257f046ae0d11d 100644 (file)
@@ -2251,6 +2251,21 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu)
        return 0;
 }
 
+/* Get mac address */
+static void mvneta_get_mac_addr(struct mvneta_port *pp, unsigned char *addr)
+{
+       u32 mac_addr_l, mac_addr_h;
+
+       mac_addr_l = mvreg_read(pp, MVNETA_MAC_ADDR_LOW);
+       mac_addr_h = mvreg_read(pp, MVNETA_MAC_ADDR_HIGH);
+       addr[0] = (mac_addr_h >> 24) & 0xFF;
+       addr[1] = (mac_addr_h >> 16) & 0xFF;
+       addr[2] = (mac_addr_h >> 8) & 0xFF;
+       addr[3] = mac_addr_h & 0xFF;
+       addr[4] = (mac_addr_l >> 8) & 0xFF;
+       addr[5] = mac_addr_l & 0xFF;
+}
+
 /* Handle setting mac address */
 static int mvneta_set_mac_addr(struct net_device *dev, void *addr)
 {
@@ -2667,7 +2682,9 @@ static int mvneta_probe(struct platform_device *pdev)
        u32 phy_addr;
        struct mvneta_port *pp;
        struct net_device *dev;
-       const char *mac_addr;
+       const char *dt_mac_addr;
+       char hw_mac_addr[ETH_ALEN];
+       const char *mac_from;
        int phy_mode;
        int err;
 
@@ -2703,13 +2720,6 @@ static int mvneta_probe(struct platform_device *pdev)
                goto err_free_irq;
        }
 
-       mac_addr = of_get_mac_address(dn);
-
-       if (!mac_addr || !is_valid_ether_addr(mac_addr))
-               eth_hw_addr_random(dev);
-       else
-               memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
-
        dev->tx_queue_len = MVNETA_MAX_TXD;
        dev->watchdog_timeo = 5 * HZ;
        dev->netdev_ops = &mvneta_netdev_ops;
@@ -2740,6 +2750,21 @@ static int mvneta_probe(struct platform_device *pdev)
 
        clk_prepare_enable(pp->clk);
 
+       dt_mac_addr = of_get_mac_address(dn);
+       if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
+               mac_from = "device tree";
+               memcpy(dev->dev_addr, dt_mac_addr, ETH_ALEN);
+       } else {
+               mvneta_get_mac_addr(pp, hw_mac_addr);
+               if (is_valid_ether_addr(hw_mac_addr)) {
+                       mac_from = "hardware";
+                       memcpy(dev->dev_addr, hw_mac_addr, ETH_ALEN);
+               } else {
+                       mac_from = "random";
+                       eth_hw_addr_random(dev);
+               }
+       }
+
        pp->tx_done_timer.data = (unsigned long)dev;
 
        pp->tx_ring_size = MVNETA_MAX_TXD;
@@ -2772,7 +2797,8 @@ static int mvneta_probe(struct platform_device *pdev)
                goto err_deinit;
        }
 
-       netdev_info(dev, "mac: %pM\n", dev->dev_addr);
+       netdev_info(dev, "Using %s mac address %pM\n", mac_from,
+                   dev->dev_addr);
 
        platform_set_drvdata(pdev, pp->dev);
 
@@ -2804,8 +2830,6 @@ static int mvneta_remove(struct platform_device *pdev)
        irq_dispose_mapping(dev->irq);
        free_netdev(dev);
 
-       platform_set_drvdata(pdev, NULL);
-
        return 0;
 }
 
index 339bb323cb0c99c91bf2741cbfea918e7ae4499d..2602cf7ba64214d5cd64760dc7df9e4012fc9c83 100644 (file)
@@ -1602,7 +1602,6 @@ static int pxa168_eth_remove(struct platform_device *pdev)
        unregister_netdev(dev);
        cancel_work_sync(&pep->tx_timeout_task);
        free_netdev(dev);
-       platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
index 171f4b3dda07ae5fc4f9986c36102beeab8de49e..c896079728e1312893fdf03f0b0e111f2a6676cc 100644 (file)
@@ -3706,7 +3706,7 @@ static const struct file_operations skge_debug_fops = {
 static int skge_device_event(struct notifier_block *unused,
                             unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct skge_port *skge;
        struct dentry *d;
 
index d175bbd3ffd37952f5dc2e66348049693ac7d2d7..e09a8c6f85366c4c1251f5365549e154f743f08c 100644 (file)
@@ -4642,7 +4642,7 @@ static const struct file_operations sky2_debug_fops = {
 static int sky2_device_event(struct notifier_block *unused,
                             unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct sky2_port *sky2 = netdev_priv(dev);
 
        if (dev->netdev_ops->ndo_open != sky2_open || !sky2_debug)
index 4e6877a032a8414bd059e2dcf658616dc2cab0fe..7c492382da09937764e8c6bb9a835d1c05771021 100644 (file)
@@ -544,7 +544,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
        if (vlan_tx_tag_present(skb))
                up = vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT;
 
-       return __skb_tx_hash(dev, skb, rings_p_up) + up * rings_p_up;
+       return __netdev_pick_tx(dev, skb) % rings_p_up + up * rings_p_up;
 }
 
 static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt)
index b1d7657b2bf559573015cea69a7e1b573453eb1e..b1f51c1f635c0edb4c03b4453b77f1189d0ce5c2 100644 (file)
 #define MLX4_EN_ALLOC_SIZE     PAGE_ALIGN(16384)
 #define MLX4_EN_ALLOC_ORDER    get_order(MLX4_EN_ALLOC_SIZE)
 
-/* Receive fragment sizes; we use at most 4 fragments (for 9600 byte MTU
+/* Receive fragment sizes; we use at most 3 fragments (for 9600 byte MTU
  * and 4K allocations) */
 enum {
-       FRAG_SZ0 = 512 - NET_IP_ALIGN,
-       FRAG_SZ1 = 1024,
+       FRAG_SZ0 = 1536 - NET_IP_ALIGN,
+       FRAG_SZ1 = 4096,
        FRAG_SZ2 = 4096,
        FRAG_SZ3 = MLX4_EN_ALLOC_SIZE
 };
index b6c60fdef4ff6d1d5498e1bfb688b4edfa7ad8bd..106eb972f2acade4f52ebdd6ceed74f6cac7c5bd 100644 (file)
@@ -1600,7 +1600,6 @@ ks8695_drv_remove(struct platform_device *pdev)
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct ks8695_priv *ksp = netdev_priv(ndev);
 
-       platform_set_drvdata(pdev, NULL);
        netif_napi_del(&ksp->napi);
 
        unregister_netdev(ndev);
index fbcb9e74d7fc598f1fe52951a087603f58e11efc..e393d998be89dd2128fccaef65efd36a92c09d26 100644 (file)
@@ -1250,7 +1250,6 @@ static int ks8842_remove(struct platform_device *pdev)
        iounmap(adapter->hw_addr);
        free_netdev(netdev);
        release_mem_region(iomem->start, resource_size(iomem));
-       platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
index ddaf138ce0d4aa79344584f938dad12047a73c97..ac20098b542a37697f8e78989428653d6d29ba67 100644 (file)
@@ -35,6 +35,9 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/ks8851_mll.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_net.h>
 
 #define        DRV_NAME        "ks8851_mll"
 
@@ -1524,6 +1527,13 @@ static int ks_hw_init(struct ks_net *ks)
        return true;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id ks8851_ml_dt_ids[] = {
+       { .compatible = "micrel,ks8851-mll" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ks8851_ml_dt_ids);
+#endif
 
 static int ks8851_probe(struct platform_device *pdev)
 {
@@ -1532,7 +1542,7 @@ static int ks8851_probe(struct platform_device *pdev)
        struct net_device *netdev;
        struct ks_net *ks;
        u16 id, data;
-       struct ks8851_mll_platform_data *pdata;
+       const char *mac;
 
        io_d = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        io_c = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -1619,13 +1629,21 @@ static int ks8851_probe(struct platform_device *pdev)
        ks_wrreg16(ks, KS_OBCR, data | OBCR_ODS_16MA);
 
        /* overwriting the default MAC address */
-       pdata = pdev->dev.platform_data;
-       if (!pdata) {
-               netdev_err(netdev, "No platform data\n");
-               err = -ENODEV;
-               goto err_pdata;
+       if (pdev->dev.of_node) {
+               mac = of_get_mac_address(pdev->dev.of_node);
+               if (mac)
+                       memcpy(ks->mac_addr, mac, ETH_ALEN);
+       } else {
+               struct ks8851_mll_platform_data *pdata;
+
+               pdata = pdev->dev.platform_data;
+               if (!pdata) {
+                       netdev_err(netdev, "No platform data\n");
+                       err = -ENODEV;
+                       goto err_pdata;
+               }
+               memcpy(ks->mac_addr, pdata->mac_addr, ETH_ALEN);
        }
-       memcpy(ks->mac_addr, pdata->mac_addr, 6);
        if (!is_valid_ether_addr(ks->mac_addr)) {
                /* Use random MAC address if none passed */
                eth_random_addr(ks->mac_addr);
@@ -1671,7 +1689,6 @@ static int ks8851_remove(struct platform_device *pdev)
        iounmap(ks->hw_addr);
        free_netdev(netdev);
        release_mem_region(iomem->start, resource_size(iomem));
-       platform_set_drvdata(pdev, NULL);
        return 0;
 
 }
@@ -1680,6 +1697,7 @@ static struct platform_driver ks8851_platform_driver = {
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(ks8851_ml_dt_ids),
        },
        .probe = ks8851_probe,
        .remove = ks8851_remove,
index cb9e6383150043e3186bfc1c51ee8f334fb090c0..dc2c6f561e9ade6175fb72bf187db05e528d17f7 100644 (file)
@@ -422,7 +422,6 @@ exit_free_pfifo:
 exit_free_xc:
        free_xc(priv->xc);
 exit_free_netdev:
-       platform_set_drvdata(pdev, NULL);
        free_netdev(ndev);
 exit:
        return ret;
@@ -430,11 +429,9 @@ exit:
 
 static int netx_eth_drv_remove(struct platform_device *pdev)
 {
-       struct net_device *ndev = dev_get_drvdata(&pdev->dev);
+       struct net_device *ndev = platform_get_drvdata(pdev);
        struct netx_eth_priv *priv = netdev_priv(ndev);
 
-       platform_set_drvdata(pdev, NULL);
-
        unregister_netdev(ndev);
        xc_stop(priv->xc);
        free_xc(priv->xc);
index 3df8287b7452d77b69bee0262a9f950125020b8e..e88bdb1aa669c1f60c9b161f2b81fb10150c7777 100644 (file)
@@ -1051,7 +1051,6 @@ failed_put_clk:
        clk_put(ether->clk);
 failed_free_rxirq:
        free_irq(ether->rxirq, pdev);
-       platform_set_drvdata(pdev, NULL);
 failed_free_txirq:
        free_irq(ether->txirq, pdev);
 failed_free_io:
@@ -1080,7 +1079,6 @@ static int w90p910_ether_remove(struct platform_device *pdev)
        free_irq(ether->rxirq, dev);
 
        del_timer_sync(&ether->check_timer);
-       platform_set_drvdata(pdev, NULL);
 
        free_netdev(dev);
        return 0;
index b003fe53c8e2508e3de8f2c2a118060b57ac02ac..098b96dad66f901582c9d147416f7e2a2448d861 100644 (file)
@@ -6340,7 +6340,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = {
        {0,},
 };
 
-static struct pci_driver driver = {
+static struct pci_driver forcedeth_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = pci_tbl,
        .probe          = nv_probe,
@@ -6349,16 +6349,6 @@ static struct pci_driver driver = {
        .driver.pm      = NV_PM_OPS,
 };
 
-static int __init init_nic(void)
-{
-       return pci_register_driver(&driver);
-}
-
-static void __exit exit_nic(void)
-{
-       pci_unregister_driver(&driver);
-}
-
 module_param(max_interrupt_work, int, 0);
 MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt");
 module_param(optimization_mode, int, 0);
@@ -6379,11 +6369,8 @@ module_param(debug_tx_timeout, bool, 0);
 MODULE_PARM_DESC(debug_tx_timeout,
                 "Dump tx related registers and ring when tx_timeout happens");
 
+module_pci_driver(forcedeth_pci_driver);
 MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");
 MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
 MODULE_LICENSE("GPL");
-
 MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-module_init(init_nic);
-module_exit(exit_nic);
index 55a5548d6add50d43202cc74b46acd37934e556a..a061b93efe66a29fd663a49bf16d1a510ff0879f 100644 (file)
@@ -1483,7 +1483,6 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
        return 0;
 
 err_out_unregister_netdev:
-       platform_set_drvdata(pdev, NULL);
        unregister_netdev(ndev);
 err_out_dma_unmap:
        if (!use_iram_for_net(&pldat->pdev->dev) ||
@@ -1511,7 +1510,6 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
        struct netdata_local *pldat = netdev_priv(ndev);
 
        unregister_netdev(ndev);
-       platform_set_drvdata(pdev, NULL);
 
        if (!use_iram_for_net(&pldat->pdev->dev) ||
            pldat->dma_buff_size > lpc32xx_return_iram_size())
index 921729f9c85c53baa17cd334f4a7b8f35f590561..e6e029237a63895a0726c0b442d0a6f59728d389 100644 (file)
@@ -1437,7 +1437,7 @@ static int octeon_mgmt_probe(struct platform_device *pdev)
 
        SET_NETDEV_DEV(netdev, &pdev->dev);
 
-       dev_set_drvdata(&pdev->dev, netdev);
+       platform_set_drvdata(pdev, netdev);
        p = netdev_priv(netdev);
        netif_napi_add(netdev, &p->napi, octeon_mgmt_napi_poll,
                       OCTEON_MGMT_NAPI_WEIGHT);
@@ -1559,7 +1559,7 @@ err:
 
 static int octeon_mgmt_remove(struct platform_device *pdev)
 {
-       struct net_device *netdev = dev_get_drvdata(&pdev->dev);
+       struct net_device *netdev = platform_get_drvdata(pdev);
 
        unregister_netdev(netdev);
        free_netdev(netdev);
index 322a36b76727d3522bb8bb1a35440d18ee21b696..3fe09ab2d7c9f368a53188bc7645d212c0d6c53e 100644 (file)
@@ -53,8 +53,8 @@
 
 #define _NETXEN_NIC_LINUX_MAJOR 4
 #define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 80
-#define NETXEN_NIC_LINUX_VERSIONID  "4.0.80"
+#define _NETXEN_NIC_LINUX_SUBVERSION 81
+#define NETXEN_NIC_LINUX_VERSIONID  "4.0.81"
 
 #define NETXEN_VERSION_CODE(a, b, c)   (((a) << 24) + ((b) << 16) + (c))
 #define _major(v)      (((v) >> 24) & 0xff)
@@ -1855,7 +1855,7 @@ static const struct netxen_brdinfo netxen_boards[] = {
 
 #define NUM_SUPPORTED_BOARDS ARRAY_SIZE(netxen_boards)
 
-static inline void get_brd_name_by_type(u32 type, char *name)
+static inline int netxen_nic_get_brd_name_by_type(u32 type, char *name)
 {
        int i, found = 0;
        for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) {
@@ -1864,10 +1864,14 @@ static inline void get_brd_name_by_type(u32 type, char *name)
                        found = 1;
                        break;
                }
+       }
 
+       if (!found) {
+               strcpy(name, "Unknown");
+               return -EINVAL;
        }
-       if (!found)
-               name = "Unknown";
+
+       return 0;
 }
 
 static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring)
index 28e076960bcb5c8400e13eb62ac8d29c7d2f0841..32c790659f9c1ba0410614c30818eb9cf20a46ee 100644 (file)
@@ -734,6 +734,9 @@ enum {
 #define NIC_CRB_BASE_2         (NETXEN_CAM_RAM(0x700))
 #define NETXEN_NIC_REG(X)      (NIC_CRB_BASE+(X))
 #define NETXEN_NIC_REG_2(X)    (NIC_CRB_BASE_2+(X))
+#define NETXEN_INTR_MODE_REG   NETXEN_NIC_REG(0x44)
+#define NETXEN_MSI_MODE                0x1
+#define NETXEN_INTX_MODE       0x2
 
 #define NX_CDRP_CRB_OFFSET             (NETXEN_NIC_REG(0x18))
 #define NX_ARG1_CRB_OFFSET             (NETXEN_NIC_REG(0x1c))
index af951f343ff6d1396589ffbbf462aa2c7a80c776..c401b0b4353d94d543e357c16c184c8771eafe7a 100644 (file)
@@ -592,48 +592,60 @@ static const struct net_device_ops netxen_netdev_ops = {
 #endif
 };
 
-static void
-netxen_setup_intr(struct netxen_adapter *adapter)
+static inline bool netxen_function_zero(struct pci_dev *pdev)
 {
-       struct netxen_legacy_intr_set *legacy_intrp;
-       struct pci_dev *pdev = adapter->pdev;
-       int err, num_msix;
+       return (PCI_FUNC(pdev->devfn) == 0) ? true : false;
+}
 
-       if (adapter->rss_supported) {
-               num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ?
-                       MSIX_ENTRIES_PER_ADAPTER : 2;
-       } else
-               num_msix = 1;
+static inline void netxen_set_interrupt_mode(struct netxen_adapter *adapter,
+                                            u32 mode)
+{
+       NXWR32(adapter, NETXEN_INTR_MODE_REG, mode);
+}
 
-       adapter->max_sds_rings = 1;
+static inline u32 netxen_get_interrupt_mode(struct netxen_adapter *adapter)
+{
+       return NXRD32(adapter, NETXEN_INTR_MODE_REG);
+}
 
-       adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
+static void
+netxen_initialize_interrupt_registers(struct netxen_adapter *adapter)
+{
+       struct netxen_legacy_intr_set *legacy_intrp;
+       u32 tgt_status_reg, int_state_reg;
 
        if (adapter->ahw.revision_id >= NX_P3_B0)
                legacy_intrp = &legacy_intr[adapter->ahw.pci_func];
        else
                legacy_intrp = &legacy_intr[0];
 
+       tgt_status_reg = legacy_intrp->tgt_status_reg;
+       int_state_reg = ISR_INT_STATE_REG;
+
        adapter->int_vec_bit = legacy_intrp->int_vec_bit;
-       adapter->tgt_status_reg = netxen_get_ioaddr(adapter,
-                       legacy_intrp->tgt_status_reg);
+       adapter->tgt_status_reg = netxen_get_ioaddr(adapter, tgt_status_reg);
        adapter->tgt_mask_reg = netxen_get_ioaddr(adapter,
-                       legacy_intrp->tgt_mask_reg);
+                                                 legacy_intrp->tgt_mask_reg);
        adapter->pci_int_reg = netxen_get_ioaddr(adapter,
-                       legacy_intrp->pci_int_reg);
+                                                legacy_intrp->pci_int_reg);
        adapter->isr_int_vec = netxen_get_ioaddr(adapter, ISR_INT_VECTOR);
 
        if (adapter->ahw.revision_id >= NX_P3_B1)
                adapter->crb_int_state_reg = netxen_get_ioaddr(adapter,
-                       ISR_INT_STATE_REG);
+                                                              int_state_reg);
        else
                adapter->crb_int_state_reg = netxen_get_ioaddr(adapter,
-                       CRB_INT_VECTOR);
+                                                              CRB_INT_VECTOR);
+}
 
-       netxen_set_msix_bit(pdev, 0);
+static int netxen_setup_msi_interrupts(struct netxen_adapter *adapter,
+                                      int num_msix)
+{
+       struct pci_dev *pdev = adapter->pdev;
+       u32 value;
+       int err;
 
        if (adapter->msix_supported) {
-
                netxen_init_msix_entries(adapter, num_msix);
                err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
                if (err == 0) {
@@ -644,26 +656,59 @@ netxen_setup_intr(struct netxen_adapter *adapter)
                                adapter->max_sds_rings = num_msix;
 
                        dev_info(&pdev->dev, "using msi-x interrupts\n");
-                       return;
+                       return 0;
                }
-
-               if (err > 0)
-                       pci_disable_msix(pdev);
-
                /* fall through for msi */
        }
 
        if (use_msi && !pci_enable_msi(pdev)) {
+               value = msi_tgt_status[adapter->ahw.pci_func];
                adapter->flags |= NETXEN_NIC_MSI_ENABLED;
-               adapter->tgt_status_reg = netxen_get_ioaddr(adapter,
-                               msi_tgt_status[adapter->ahw.pci_func]);
-               dev_info(&pdev->dev, "using msi interrupts\n");
+               adapter->tgt_status_reg = netxen_get_ioaddr(adapter, value);
                adapter->msix_entries[0].vector = pdev->irq;
-               return;
+               dev_info(&pdev->dev, "using msi interrupts\n");
+               return 0;
        }
 
-       dev_info(&pdev->dev, "using legacy interrupts\n");
-       adapter->msix_entries[0].vector = pdev->irq;
+       dev_err(&pdev->dev, "Failed to acquire MSI-X/MSI interrupt vector\n");
+       return -EIO;
+}
+
+static int netxen_setup_intr(struct netxen_adapter *adapter)
+{
+       struct pci_dev *pdev = adapter->pdev;
+       int num_msix;
+
+       if (adapter->rss_supported)
+               num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ?
+                           MSIX_ENTRIES_PER_ADAPTER : 2;
+       else
+               num_msix = 1;
+
+       adapter->max_sds_rings = 1;
+       adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
+
+       netxen_initialize_interrupt_registers(adapter);
+       netxen_set_msix_bit(pdev, 0);
+
+       if (netxen_function_zero(pdev)) {
+               if (!netxen_setup_msi_interrupts(adapter, num_msix))
+                       netxen_set_interrupt_mode(adapter, NETXEN_MSI_MODE);
+               else
+                       netxen_set_interrupt_mode(adapter, NETXEN_INTX_MODE);
+       } else {
+               if (netxen_get_interrupt_mode(adapter) == NETXEN_MSI_MODE &&
+                   netxen_setup_msi_interrupts(adapter, num_msix)) {
+                       dev_err(&pdev->dev, "Co-existence of MSI-X/MSI and INTx interrupts is not supported\n");
+                       return -EIO;
+               }
+       }
+
+       if (!NETXEN_IS_MSI_FAMILY(adapter)) {
+               adapter->msix_entries[0].vector = pdev->irq;
+               dev_info(&pdev->dev, "using legacy interrupts\n");
+       }
+       return 0;
 }
 
 static void
@@ -841,7 +886,9 @@ netxen_check_options(struct netxen_adapter *adapter)
        }
 
        if (adapter->portnum == 0) {
-               get_brd_name_by_type(adapter->ahw.board_type, brd_name);
+               if (netxen_nic_get_brd_name_by_type(adapter->ahw.board_type,
+                                                   brd_name))
+                       strcpy(serial_num, "Unknown");
 
                pr_info("%s: %s Board S/N %s  Chip rev 0x%x\n",
                                module_name(THIS_MODULE),
@@ -860,9 +907,9 @@ netxen_check_options(struct netxen_adapter *adapter)
                adapter->ahw.cut_through = (i & 0x8000) ? 1 : 0;
        }
 
-       dev_info(&pdev->dev, "firmware v%d.%d.%d [%s]\n",
-                       fw_major, fw_minor, fw_build,
-                       adapter->ahw.cut_through ? "cut-through" : "legacy");
+       dev_info(&pdev->dev, "Driver v%s, firmware v%d.%d.%d [%s]\n",
+                NETXEN_NIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build,
+                adapter->ahw.cut_through ? "cut-through" : "legacy");
 
        if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222))
                adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
@@ -1508,7 +1555,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        netxen_nic_clear_stats(adapter);
 
-       netxen_setup_intr(adapter);
+       err = netxen_setup_intr(adapter);
+
+       if (err) {
+               dev_err(&adapter->pdev->dev,
+                       "Failed to setup interrupts, error = %d\n", err);
+               goto err_out_disable_msi;
+       }
 
        err = netxen_setup_netdev(adapter, netdev);
        if (err)
@@ -1596,7 +1649,7 @@ static void netxen_nic_remove(struct pci_dev *pdev)
        clear_bit(__NX_RESETTING, &adapter->state);
 
        netxen_teardown_intr(adapter);
-
+       netxen_set_interrupt_mode(adapter, 0);
        netxen_remove_diag_entries(adapter);
 
        netxen_cleanup_pci_map(adapter);
@@ -2721,7 +2774,7 @@ netxen_store_bridged_mode(struct device *dev,
        if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
                goto err_out;
 
-       if (strict_strtoul(buf, 2, &new))
+       if (kstrtoul(buf, 2, &new))
                goto err_out;
 
        if (!netxen_config_bridged_mode(adapter, !!new))
@@ -2760,7 +2813,7 @@ netxen_store_diag_mode(struct device *dev,
        struct netxen_adapter *adapter = dev_get_drvdata(dev);
        unsigned long new;
 
-       if (strict_strtoul(buf, 2, &new))
+       if (kstrtoul(buf, 2, &new))
                return -EINVAL;
 
        if (!!new != !!(adapter->flags & NETXEN_NIC_DIAG_ENABLED))
@@ -3311,7 +3364,7 @@ static int netxen_netdev_event(struct notifier_block *this,
                                 unsigned long event, void *ptr)
 {
        struct netxen_adapter *adapter;
-       struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net_device *orig_dev = dev;
        struct net_device *slave;
 
index c1b693cb3df38b180d1cece6d4acfe5582bb9d6a..534e36ed855a45f2f22ff2d0eaab906b19ca9889 100644 (file)
@@ -38,8 +38,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 2
-#define _QLCNIC_LINUX_SUBVERSION 42
-#define QLCNIC_LINUX_VERSIONID  "5.2.42"
+#define _QLCNIC_LINUX_SUBVERSION 43
+#define QLCNIC_LINUX_VERSIONID  "5.2.43"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
                 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -303,7 +303,6 @@ extern int qlcnic_use_msi;
 extern int qlcnic_use_msi_x;
 extern int qlcnic_auto_fw_reset;
 extern int qlcnic_load_fw_file;
-extern int qlcnic_config_npars;
 
 /* Number of status descriptors to handle per interrupt */
 #define MAX_STATUS_HANDLE      (64)
@@ -443,6 +442,7 @@ struct qlcnic_hardware_context {
        u16 max_mtu;
        u32 msg_enable;
        u16 act_pci_func;
+       u16 max_pci_func;
 
        u32 capabilities;
        u32 capabilities2;
@@ -816,6 +816,7 @@ struct qlcnic_mac_list_s {
 #define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2
 #define QLCNIC_FW_CAP2_HW_LRO_IPV6             BIT_3
 #define QLCNIC_FW_CAPABILITY_2_OCBB            BIT_5
+#define QLCNIC_FW_CAPABILITY_2_BEACON          BIT_7
 
 /* module types */
 #define LINKEVENT_MODULE_NOT_PRESENT                   1
@@ -913,6 +914,9 @@ struct qlcnic_ipaddr {
 #define QLCNIC_IS_TSO_CAPABLE(adapter)  \
        ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
 
+#define QLCNIC_BEACON_EANBLE           0xC
+#define QLCNIC_BEACON_DISABLE          0xD
+
 #define QLCNIC_DEF_NUM_STS_DESC_RINGS  4
 #define QLCNIC_MSIX_TBL_SPACE          8192
 #define QLCNIC_PCI_REG_MSIX_TBL        0x44
@@ -932,6 +936,7 @@ struct qlcnic_ipaddr {
 #define __QLCNIC_SRIOV_ENABLE          10
 #define __QLCNIC_SRIOV_CAPABLE         11
 #define __QLCNIC_MBX_POLL_ENABLE       12
+#define __QLCNIC_DIAG_MODE             13
 
 #define QLCNIC_INTERRUPT_TEST          1
 #define QLCNIC_LOOPBACK_TEST           2
@@ -1543,6 +1548,7 @@ 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);
@@ -1886,6 +1892,21 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
                writel(0xfbff, adapter->tgt_mask_reg);
 }
 
+static inline int qlcnic_get_diag_lock(struct qlcnic_adapter *adapter)
+{
+       return test_and_set_bit(__QLCNIC_DIAG_MODE, &adapter->state);
+}
+
+static inline void qlcnic_release_diag_lock(struct qlcnic_adapter *adapter)
+{
+       clear_bit(__QLCNIC_DIAG_MODE, &adapter->state);
+}
+
+static inline int qlcnic_check_diag_status(struct qlcnic_adapter *adapter)
+{
+       return test_bit(__QLCNIC_DIAG_MODE, &adapter->state);
+}
+
 extern const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops;
 extern const struct ethtool_ops qlcnic_ethtool_ops;
 extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
index b4ff1e35a11de24863966e1b8cdae2898cda8c6a..f63a6957025609b948b078e4e42955b62f884a47 100644 (file)
@@ -312,6 +312,11 @@ inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
        writel(0, adapter->tgt_mask_reg);
 }
 
+inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
+{
+       writel(1, adapter->tgt_mask_reg);
+}
+
 /* Enable MSI-x and INT-x interrupts */
 void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter,
                             struct qlcnic_host_sds_ring *sds_ring)
@@ -458,6 +463,9 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
 {
        u32 num_msix;
 
+       if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
+               qlcnic_83xx_set_legacy_intr_mask(adapter);
+
        qlcnic_83xx_disable_mbx_intr(adapter);
 
        if (adapter->flags & QLCNIC_MSIX_ENABLED)
@@ -474,7 +482,6 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
 {
        irq_handler_t handler;
        u32 val;
-       char name[32];
        int err = 0;
        unsigned long flags = 0;
 
@@ -485,9 +492,7 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
        if (adapter->flags & QLCNIC_MSIX_ENABLED) {
                handler = qlcnic_83xx_handle_aen;
                val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
-               snprintf(name, (IFNAMSIZ + 4),
-                        "%s[%s]", "qlcnic", "aen");
-               err = request_irq(val, handler, flags, name, adapter);
+               err = request_irq(val, handler, flags, "qlcnic-MB", adapter);
                if (err) {
                        dev_err(&adapter->pdev->dev,
                                "failed to register MBX interrupt\n");
@@ -1588,16 +1593,24 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings;
 
-       QLCDB(adapter, DRV, "%s loopback test in progress\n",
-             mode == QLCNIC_ILB_MODE ? "internal" : "external");
        if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
-               dev_warn(&adapter->pdev->dev,
-                        "Loopback test not supported for non privilege function\n");
+               netdev_warn(netdev,
+                           "Loopback test not supported in non privileged mode\n");
                return ret;
        }
 
-       if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+       if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
+               netdev_info(netdev, "Device is resetting\n");
                return -EBUSY;
+       }
+
+       if (qlcnic_get_diag_lock(adapter)) {
+               netdev_info(netdev, "Device is in diagnostics mode\n");
+               return -EBUSY;
+       }
+
+       netdev_info(netdev, "%s loopback test in progress\n",
+                   mode == QLCNIC_ILB_MODE ? "internal" : "external");
 
        ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST,
                                         max_sds_rings);
@@ -1638,7 +1651,7 @@ free_diag_res:
 
 fail_diag_alloc:
        adapter->max_sds_rings = max_sds_rings;
-       clear_bit(__QLCNIC_RESETTING, &adapter->state);
+       qlcnic_release_diag_lock(adapter);
        return ret;
 }
 
@@ -2121,26 +2134,25 @@ out:
 int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
                             struct qlcnic_pci_info *pci_info)
 {
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       struct device *dev = &adapter->pdev->dev;
+       struct qlcnic_cmd_args cmd;
        int i, err = 0, j = 0;
        u32 temp;
-       struct qlcnic_cmd_args cmd;
 
        qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
        err = qlcnic_issue_cmd(adapter, &cmd);
 
-       adapter->ahw->act_pci_func = 0;
+       ahw->act_pci_func = 0;
        if (err == QLCNIC_RCODE_SUCCESS) {
-               pci_info->func_count = cmd.rsp.arg[1] & 0xFF;
-               dev_info(&adapter->pdev->dev,
-                        "%s: total functions = %d\n",
-                        __func__, pci_info->func_count);
+               ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF;
                for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
                        pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
                        pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
                        i++;
                        pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
                        if (pci_info->type == QLCNIC_TYPE_NIC)
-                               adapter->ahw->act_pci_func++;
+                               ahw->act_pci_func++;
                        temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
                        pci_info->default_port = temp;
                        i++;
@@ -2152,18 +2164,21 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
                        i++;
                        memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
                        i = i + 3;
-
-                       dev_info(&adapter->pdev->dev, "%s:\n"
-                                "\tid = %d active = %d type = %d\n"
-                                "\tport = %d min bw = %d max bw = %d\n"
-                                "\tmac_addr =  %pM\n", __func__,
-                                pci_info->id, pci_info->active, pci_info->type,
-                                pci_info->default_port, pci_info->tx_min_bw,
-                                pci_info->tx_max_bw, pci_info->mac);
+                       if (ahw->op_mode == QLCNIC_MGMT_FUNC)
+                               dev_info(dev, "id = %d active = %d type = %d\n"
+                                        "\tport = %d min bw = %d max bw = %d\n"
+                                        "\tmac_addr =  %pM\n", pci_info->id,
+                                        pci_info->active, pci_info->type,
+                                        pci_info->default_port,
+                                        pci_info->tx_min_bw,
+                                        pci_info->tx_max_bw, pci_info->mac);
                }
+               if (ahw->op_mode == QLCNIC_MGMT_FUNC)
+                       dev_info(dev, "Max vNIC functions = %d, active vNIC functions = %d\n",
+                                ahw->max_pci_func, ahw->act_pci_func);
+
        } else {
-               dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n",
-                       err);
+               dev_err(dev, "Failed to get PCI Info, error = %d\n", err);
                err = -EIO;
        }
 
@@ -3113,8 +3128,10 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
        u8 val;
        int ret, max_sds_rings = adapter->max_sds_rings;
 
-       if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
-               return -EIO;
+       if (qlcnic_get_diag_lock(adapter)) {
+               netdev_info(netdev, "Device in diagnostics mode\n");
+               return -EBUSY;
+       }
 
        ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST,
                                         max_sds_rings);
@@ -3156,7 +3173,7 @@ done:
 
 fail_diag_irq:
        adapter->max_sds_rings = max_sds_rings;
-       clear_bit(__QLCNIC_RESETTING, &adapter->state);
+       qlcnic_release_diag_lock(adapter);
        return ret;
 }
 
index f5db67fc9f55a0dd319112462b0952af932f3ffe..1bfe283a94125f6b6ba0abbeaa4692c00e37f491 100644 (file)
@@ -314,6 +314,7 @@ struct qlc_83xx_idc {
        u8              vnic_state;
        u8              vnic_wait_limit;
        u8              quiesce_req;
+       u8              delay_reset;
        char            **name;
 };
 
index 5e7fb1dfb97b54c63c46314eea8eeccd9dbbc643..aa26250d73740e7eadf0c9b442ac4f6fa627bfef 100644 (file)
@@ -649,6 +649,7 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
        ahw->idc.collect_dump = 0;
        ahw->reset_context = 0;
        adapter->tx_timeo_cnt = 0;
+       ahw->idc.delay_reset = 0;
 
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 }
@@ -883,21 +884,41 @@ static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)
        int ret = 0;
 
        if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) {
-               qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
                qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
                set_bit(__QLCNIC_RESETTING, &adapter->state);
                clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
                if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE)
                        qlcnic_83xx_disable_vnic_mode(adapter, 1);
-               qlcnic_83xx_idc_detach_driver(adapter);
+
+               if (qlcnic_check_diag_status(adapter)) {
+                       dev_info(&adapter->pdev->dev,
+                                "%s: Wait for diag completion\n", __func__);
+                       adapter->ahw->idc.delay_reset = 1;
+                       return 0;
+               } else {
+                       qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
+                       qlcnic_83xx_idc_detach_driver(adapter);
+               }
        }
 
-       /* Check ACK from other functions */
-       ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter);
-       if (ret) {
+       if (qlcnic_check_diag_status(adapter)) {
                dev_info(&adapter->pdev->dev,
-                        "%s: Waiting for reset ACK\n", __func__);
-               return 0;
+                        "%s: Wait for diag completion\n", __func__);
+               return  -1;
+       } else {
+               if (adapter->ahw->idc.delay_reset) {
+                       qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
+                       qlcnic_83xx_idc_detach_driver(adapter);
+                       adapter->ahw->idc.delay_reset = 0;
+               }
+
+               /* Check for ACK from other functions */
+               ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter);
+               if (ret) {
+                       dev_info(&adapter->pdev->dev,
+                                "%s: Waiting for reset ACK\n", __func__);
+                       return -1;
+               }
        }
 
        /* Transit to INIT state and restart the HW */
index b0c3de9ede03657ea0b868ddc6c98203b16aac4d..b5054e1d17109464dfb4cc9a05144648b74c5d5b 100644 (file)
@@ -42,27 +42,18 @@ int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
 static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
 {
        u8 id;
-       int i, ret = -EBUSY;
+       int ret = -EBUSY;
        u32 data = QLCNIC_MGMT_FUNC;
        struct qlcnic_hardware_context *ahw = adapter->ahw;
 
        if (qlcnic_83xx_lock_driver(adapter))
                return ret;
 
-       if (qlcnic_config_npars) {
-               for (i = 0; i < ahw->act_pci_func; i++) {
-                       id = adapter->npars[i].pci_func;
-                       if (id == ahw->pci_func)
-                               continue;
-                       data |= qlcnic_config_npars &
-                               QLC_83XX_SET_FUNC_OPMODE(0x3, id);
-               }
-       } else {
-               data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
-               data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, ahw->pci_func)) |
-                      QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC,
-                                               ahw->pci_func);
-       }
+       id = ahw->pci_func;
+       data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
+       data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, id)) |
+              QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, id);
+
        QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data);
 
        qlcnic_83xx_unlock_driver(adapter);
@@ -196,20 +187,24 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
        else
                priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
                                                         ahw->pci_func);
-
-       if (priv_level == QLCNIC_NON_PRIV_FUNC) {
+       switch (priv_level) {
+       case QLCNIC_NON_PRIV_FUNC:
                ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
                ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
                nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic;
-       } else if (priv_level == QLCNIC_PRIV_FUNC) {
+               break;
+       case QLCNIC_PRIV_FUNC:
                ahw->op_mode = QLCNIC_PRIV_FUNC;
                ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry;
                nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic;
-       } else if (priv_level == QLCNIC_MGMT_FUNC) {
+               break;
+       case QLCNIC_MGMT_FUNC:
                ahw->op_mode = QLCNIC_MGMT_FUNC;
                ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
                nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic;
-       } else {
+               break;
+       default:
+               dev_err(&adapter->pdev->dev, "Invalid Virtual NIC opmode\n");
                return -EIO;
        }
 
@@ -218,8 +213,8 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
        else
                adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
 
-       adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
-       adapter->ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
+       ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
+       ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
 
        return 0;
 }
index 43562c256379539b8f739d4b72950886c067b75e..9d0ae11589ce270c94a8a17c5832dbeeb94aa9cf 100644 (file)
@@ -37,6 +37,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
        {QLCNIC_CMD_TEMP_SIZE, 4, 4},
        {QLCNIC_CMD_GET_TEMP_HDR, 4, 1},
        {QLCNIC_CMD_SET_DRV_VER, 4, 1},
+       {QLCNIC_CMD_GET_LED_STATUS, 4, 2},
 };
 
 static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw)
@@ -882,11 +883,12 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
 
 /* Configure eSwitch for port mirroring */
 int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
-                               u8 enable_mirroring, u8 pci_func)
+                                u8 enable_mirroring, u8 pci_func)
 {
+       struct device *dev = &adapter->pdev->dev;
+       struct qlcnic_cmd_args cmd;
        int err = -EIO;
        u32 arg1;
-       struct qlcnic_cmd_args cmd;
 
        if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
            !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
@@ -900,13 +902,11 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
        err = qlcnic_issue_cmd(adapter, &cmd);
 
        if (err != QLCNIC_RCODE_SUCCESS)
-               dev_err(&adapter->pdev->dev,
-                       "Failed to configure port mirroring%d on eswitch:%d\n",
+               dev_err(dev, "Failed to configure port mirroring for vNIC function %d on eSwitch %d\n",
                        pci_func, id);
        else
-               dev_info(&adapter->pdev->dev,
-                       "Configured eSwitch %d for port mirroring:%d\n",
-                       id, pci_func);
+               dev_info(dev, "Configured port mirroring for vNIC function %d on eSwitch %d\n",
+                        pci_func, id);
        qlcnic_free_mbx_args(&cmd);
 
        return err;
@@ -1121,14 +1121,13 @@ err_ret:
        return -EIO;
 }
 
-static int
-__qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
-                                       u32 *arg1, u32 *arg2)
+static int __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
+                                           u32 *arg1, u32 *arg2)
 {
-       int err = -EIO;
+       struct device *dev = &adapter->pdev->dev;
        struct qlcnic_cmd_args cmd;
-       u8 pci_func;
-       pci_func = (*arg1 >> 8);
+       u8 pci_func = *arg1 >> 8;
+       int err = -EIO;
 
        qlcnic_alloc_mbx_args(&cmd, adapter,
                              QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
@@ -1139,12 +1138,11 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
        qlcnic_free_mbx_args(&cmd);
 
        if (err == QLCNIC_RCODE_SUCCESS)
-               dev_info(&adapter->pdev->dev,
-                        "eSwitch port config for pci func %d\n", pci_func);
+               dev_info(dev, "Get eSwitch port config for vNIC function %d\n",
+                        pci_func);
        else
-               dev_err(&adapter->pdev->dev,
-                       "Failed to get eswitch port config for pci func %d\n",
-                                                               pci_func);
+               dev_err(dev, "Failed to get eswitch port config for vNIC function %d\n",
+                       pci_func);
        return err;
 }
 /* Configure eSwitch port
@@ -1157,9 +1155,10 @@ op_type = 1 for port vlan_id
 int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
                struct qlcnic_esw_func_cfg *esw_cfg)
 {
+       struct device *dev = &adapter->pdev->dev;
+       struct qlcnic_cmd_args cmd;
        int err = -EIO, index;
        u32 arg1, arg2 = 0;
-       struct qlcnic_cmd_args cmd;
        u8 pci_func;
 
        if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
@@ -1216,11 +1215,11 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
        qlcnic_free_mbx_args(&cmd);
 
        if (err != QLCNIC_RCODE_SUCCESS)
-               dev_err(&adapter->pdev->dev,
-                       "Failed to configure eswitch pci func %d\n", pci_func);
+               dev_err(dev, "Failed to configure eswitch for vNIC function %d\n",
+                       pci_func);
        else
-               dev_info(&adapter->pdev->dev,
-                        "Configured eSwitch for pci func %d\n", pci_func);
+               dev_info(dev, "Configured eSwitch for vNIC function %d\n",
+                        pci_func);
 
        return err;
 }
index 106a12f2a02f5173fea587ed8a09f0b2882c0335..218978db29630f45862da1b3954c11cdae764af8 100644 (file)
@@ -1503,6 +1503,21 @@ 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)
+{
+       struct qlcnic_cmd_args cmd;
+       int err;
+
+       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];
+       }
+       qlcnic_free_mbx_args(&cmd);
+       return err;
+}
+
 void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter)
 {
        void __iomem *msix_base_addr;
index b6818f4356b905de891ed09660a7be62b3262e56..812fd07baef37f9e5dfcf92592c07285e4f690ba 100644 (file)
@@ -87,6 +87,7 @@ enum qlcnic_regs {
 #define        QLCNIC_CMD_CONFIG_VPORT                 0x32
 #define QLCNIC_CMD_GET_MAC_STATS               0x37
 #define QLCNIC_CMD_SET_DRV_VER                 0x38
+#define QLCNIC_CMD_GET_LED_STATUS              0x3C
 #define QLCNIC_CMD_CONFIGURE_RSS               0x41
 #define QLCNIC_CMD_CONFIG_INTR_COAL            0x43
 #define QLCNIC_CMD_CONFIGURE_LED               0x44
index aeb26a8506799c6a9263e41fa5d82633deafb9d7..0ae88355ad51357072cf9d6000b6586b30487b72 100644 (file)
@@ -52,10 +52,6 @@ int qlcnic_load_fw_file;
 MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file)");
 module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444);
 
-int qlcnic_config_npars;
-module_param(qlcnic_config_npars, int, 0444);
-MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled)");
-
 static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void qlcnic_remove(struct pci_dev *pdev);
 static int qlcnic_open(struct net_device *netdev);
@@ -449,6 +445,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
        .ndo_set_vf_tx_rate     = qlcnic_sriov_set_vf_tx_rate,
        .ndo_get_vf_config      = qlcnic_sriov_get_vf_config,
        .ndo_set_vf_vlan        = qlcnic_sriov_set_vf_vlan,
+       .ndo_set_vf_spoofchk    = qlcnic_sriov_set_vf_spoofchk,
 #endif
 };
 
@@ -768,7 +765,7 @@ static int
 qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
 {
        u8 id;
-       int i, ret = 1;
+       int ret;
        u32 data = QLCNIC_MGMT_FUNC;
        struct qlcnic_hardware_context *ahw = adapter->ahw;
 
@@ -776,20 +773,10 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
        if (ret)
                goto err_lock;
 
-       if (qlcnic_config_npars) {
-               for (i = 0; i < ahw->act_pci_func; i++) {
-                       id = adapter->npars[i].pci_func;
-                       if (id == ahw->pci_func)
-                               continue;
-                       data |= (qlcnic_config_npars &
-                                       QLC_DEV_SET_DRV(0xf, id));
-               }
-       } else {
-               data = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE);
-               data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) |
-                       (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC,
-                                        ahw->pci_func));
-       }
+       id = ahw->pci_func;
+       data = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE);
+       data = (data & ~QLC_DEV_SET_DRV(0xf, id)) |
+              QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, id);
        QLC_SHARED_REG_WR32(adapter, QLCNIC_DRV_OP_MODE, data);
        qlcnic_api_unlock(adapter);
 err_lock:
@@ -875,6 +862,27 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev,
        return 0;
 }
 
+static inline bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter,
+                                               int index)
+{
+       struct pci_dev *pdev = adapter->pdev;
+       unsigned short subsystem_vendor;
+       bool ret = true;
+
+       subsystem_vendor = pdev->subsystem_vendor;
+
+       if (pdev->device == PCI_DEVICE_ID_QLOGIC_QLE824X ||
+           pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) {
+               if (qlcnic_boards[index].sub_vendor == subsystem_vendor &&
+                   qlcnic_boards[index].sub_device == pdev->subsystem_device)
+                       ret = true;
+               else
+                       ret = false;
+       }
+
+       return ret;
+}
+
 static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name)
 {
        struct pci_dev *pdev = adapter->pdev;
@@ -882,20 +890,18 @@ static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name)
 
        for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) {
                if (qlcnic_boards[i].vendor == pdev->vendor &&
-                       qlcnic_boards[i].device == pdev->device &&
-                       qlcnic_boards[i].sub_vendor == pdev->subsystem_vendor &&
-                       qlcnic_boards[i].sub_device == pdev->subsystem_device) {
-                               sprintf(name, "%pM: %s" ,
-                                       adapter->mac_addr,
-                                       qlcnic_boards[i].short_name);
-                               found = 1;
-                               break;
+                   qlcnic_boards[i].device == pdev->device &&
+                   qlcnic_validate_subsystem_id(adapter, i)) {
+                       found = 1;
+                       break;
                }
-
        }
 
        if (!found)
                sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr);
+       else
+               sprintf(name, "%pM: %s" , adapter->mac_addr,
+                       qlcnic_boards[i].short_name);
 }
 
 static void
@@ -1395,16 +1401,23 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
                        for (ring = 0; ring < num_sds_rings; ring++) {
                                sds_ring = &recv_ctx->sds_rings[ring];
                                if (qlcnic_82xx_check(adapter) &&
-                                   (ring == (num_sds_rings - 1)))
+                                   (ring == (num_sds_rings - 1))) {
+                                       if (!(adapter->flags &
+                                             QLCNIC_MSIX_ENABLED))
+                                               snprintf(sds_ring->name,
+                                                        sizeof(sds_ring->name),
+                                                        "qlcnic");
+                                       else
+                                               snprintf(sds_ring->name,
+                                                        sizeof(sds_ring->name),
+                                                        "%s-tx-0-rx-%d",
+                                                        netdev->name, ring);
+                               } else {
                                        snprintf(sds_ring->name,
                                                 sizeof(sds_ring->name),
-                                                "qlcnic-%s[Tx0+Rx%d]",
-                                                netdev->name, ring);
-                               else
-                                       snprintf(sds_ring->name,
-                                                sizeof(sds_ring->name),
-                                                "qlcnic-%s[Rx%d]",
+                                                "%s-rx-%d",
                                                 netdev->name, ring);
+                               }
                                err = request_irq(sds_ring->irq, handler, flags,
                                                  sds_ring->name, sds_ring);
                                if (err)
@@ -1419,7 +1432,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
                             ring++) {
                                tx_ring = &adapter->tx_ring[ring];
                                snprintf(tx_ring->name, sizeof(tx_ring->name),
-                                        "qlcnic-%s[Tx%d]", netdev->name, ring);
+                                        "%s-tx-%d", netdev->name, ring);
                                err = request_irq(tx_ring->irq, handler, flags,
                                                  tx_ring->name, tx_ring);
                                if (err)
@@ -3219,7 +3232,6 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
        if (err)
                return err;
 
-       pci_set_power_state(pdev, PCI_D0);
        pci_set_master(pdev);
        pci_restore_state(pdev);
 
@@ -3517,7 +3529,7 @@ static int qlcnic_netdev_event(struct notifier_block *this,
                                 unsigned long event, void *ptr)
 {
        struct qlcnic_adapter *adapter;
-       struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
 recheck:
        if (dev == NULL)
index d85fbb57c25b1abc879668422158578e71eb515a..9176cb015732dcc3a37f58f10450be0fbfbf36b7 100644 (file)
@@ -129,6 +129,7 @@ struct qlcnic_vport {
        u8                      vlan_mode;
        u16                     vlan;
        u8                      qos;
+       bool                    spoofchk;
        u8                      mac[6];
 };
 
@@ -225,6 +226,7 @@ int qlcnic_sriov_set_vf_tx_rate(struct net_device *, int, int);
 int qlcnic_sriov_get_vf_config(struct net_device *, int ,
                               struct ifla_vf_info *);
 int qlcnic_sriov_set_vf_vlan(struct net_device *, int, u16, u8);
+int qlcnic_sriov_set_vf_spoofchk(struct net_device *, int, bool);
 #else
 static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {}
 static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {}
index 196b2d100407bf1de67d284c85f88e9f48d310c1..bcd200eff9819d3f954bb93afafc46936ba0cb6e 100644 (file)
@@ -35,6 +35,7 @@ static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *);
 static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *);
 static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *,
                                  struct qlcnic_cmd_args *);
+static void qlcnic_sriov_process_bc_cmd(struct work_struct *);
 
 static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
        .read_crb                       = qlcnic_83xx_read_crb,
@@ -179,6 +180,8 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
                spin_lock_init(&vf->rcv_pend.lock);
                init_completion(&vf->ch_free_cmpl);
 
+               INIT_WORK(&vf->trans_work, qlcnic_sriov_process_bc_cmd);
+
                if (qlcnic_sriov_pf_check(adapter)) {
                        vp = kzalloc(sizeof(struct qlcnic_vport), GFP_KERNEL);
                        if (!vp) {
@@ -187,6 +190,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
                        }
                        sriov->vf_info[i].vp = vp;
                        vp->max_tx_bw = MAX_BW;
+                       vp->spoofchk = true;
                        random_ether_addr(vp->mac);
                        dev_info(&adapter->pdev->dev,
                                 "MAC Address %pM is configured for VF %d\n",
@@ -652,6 +656,8 @@ int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac)
        if (qlcnic_read_mac_addr(adapter))
                dev_warn(&adapter->pdev->dev, "failed to read mac addr\n");
 
+       INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
+
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
        return 0;
 }
@@ -864,7 +870,6 @@ static void qlcnic_sriov_schedule_bc_cmd(struct qlcnic_sriov *sriov,
            vf->adapter->need_fw_reset)
                return;
 
-       INIT_WORK(&vf->trans_work, func);
        queue_work(sriov->bc.bc_trans_wq, &vf->trans_work);
 }
 
index 1a66ccded235e202616be03ae9bdb08c6bad9155..ee0c1d307966d842d824c3ed64449690946b7d76 100644 (file)
@@ -580,6 +580,7 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func)
        struct qlcnic_cmd_args cmd;
        struct qlcnic_vport *vp;
        int err, id;
+       u8 *mac;
 
        id = qlcnic_sriov_func_to_index(adapter, func);
        if (id < 0)
@@ -591,6 +592,14 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func)
                return err;
 
        cmd.req.arg[1] = 0x3 | func << 16;
+       if (vp->spoofchk == true) {
+               mac = vp->mac;
+               cmd.req.arg[2] |= BIT_1 | BIT_3 | BIT_8;
+               cmd.req.arg[4] = mac[5] | mac[4] << 8 | mac[3] << 16 |
+                                mac[2] << 24;
+               cmd.req.arg[5] = mac[1] | mac[0] << 8;
+       }
+
        if (vp->vlan_mode == QLC_PVID_MODE) {
                cmd.req.arg[2] |= BIT_6;
                cmd.req.arg[3] |= vp->vlan << 8;
@@ -1767,6 +1776,7 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev,
        memcpy(&ivi->mac, vp->mac, ETH_ALEN);
        ivi->vlan = vp->vlan;
        ivi->qos = vp->qos;
+       ivi->spoofchk = vp->spoofchk;
        if (vp->max_tx_bw == MAX_BW)
                ivi->tx_rate = 0;
        else
@@ -1775,3 +1785,29 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev,
        ivi->vf = vf;
        return 0;
 }
+
+int qlcnic_sriov_set_vf_spoofchk(struct net_device *netdev, int vf, bool chk)
+{
+       struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       struct qlcnic_sriov *sriov = adapter->ahw->sriov;
+       struct qlcnic_vf_info *vf_info;
+       struct qlcnic_vport *vp;
+
+       if (!qlcnic_sriov_pf_check(adapter))
+               return -EOPNOTSUPP;
+
+       if (vf >= sriov->num_vfs)
+               return -EINVAL;
+
+       vf_info = &sriov->vf_info[vf];
+       vp = vf_info->vp;
+       if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) {
+               netdev_err(netdev,
+                          "Spoof check change failed for VF %d, as VF driver is loaded. Please unload VF driver and retry the operation\n",
+                          vf);
+               return -EOPNOTSUPP;
+       }
+
+       vp->spoofchk = chk;
+       return 0;
+}
index e7a2fe21b64911939b5279e3f459f7108054fed6..7ec030abdf07710b2fd55df9cd40ef9948ac80cc 100644 (file)
@@ -47,7 +47,7 @@ static ssize_t qlcnic_store_bridged_mode(struct device *dev,
        if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
                goto err_out;
 
-       if (strict_strtoul(buf, 2, &new))
+       if (kstrtoul(buf, 2, &new))
                goto err_out;
 
        if (!qlcnic_config_bridged_mode(adapter, !!new))
@@ -77,7 +77,7 @@ static ssize_t qlcnic_store_diag_mode(struct device *dev,
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        unsigned long new;
 
-       if (strict_strtoul(buf, 2, &new))
+       if (kstrtoul(buf, 2, &new))
                return -EINVAL;
 
        if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
@@ -114,57 +114,51 @@ static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon,
        return 0;
 }
 
-static ssize_t qlcnic_store_beacon(struct device *dev,
-                                  struct device_attribute *attr,
-                                  const char *buf, size_t len)
+static int qlcnic_83xx_store_beacon(struct qlcnic_adapter *adapter,
+                                   const char *buf, size_t len)
 {
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_hardware_context *ahw = adapter->ahw;
-       int err, max_sds_rings = adapter->max_sds_rings;
-       u16 beacon;
-       u8 b_state, b_rate;
        unsigned long h_beacon;
+       int err;
 
-       if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
-               dev_warn(dev,
-                        "LED test not supported in non privileged mode\n");
-               return -EOPNOTSUPP;
-       }
+       if (test_bit(__QLCNIC_RESETTING, &adapter->state))
+               return -EIO;
 
-       if (qlcnic_83xx_check(adapter) &&
-           !test_bit(__QLCNIC_RESETTING, &adapter->state)) {
-               if (kstrtoul(buf, 2, &h_beacon))
-                       return -EINVAL;
+       if (kstrtoul(buf, 2, &h_beacon))
+               return -EINVAL;
 
-               if (ahw->beacon_state == h_beacon)
-                       return len;
+       if (ahw->beacon_state == h_beacon)
+               return len;
 
-               rtnl_lock();
-               if (!ahw->beacon_state) {
-                       if (test_and_set_bit(__QLCNIC_LED_ENABLE,
-                                            &adapter->state)) {
-                               rtnl_unlock();
-                               return -EBUSY;
-                       }
-               }
-               if (h_beacon) {
-                       err = qlcnic_83xx_config_led(adapter, 1, h_beacon);
-                       if (err)
-                               goto beacon_err;
-               } else {
-                       err = qlcnic_83xx_config_led(adapter, 0, !h_beacon);
-                       if (err)
-                               goto beacon_err;
+       rtnl_lock();
+       if (!ahw->beacon_state) {
+               if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
+                       rtnl_unlock();
+                       return -EBUSY;
                }
-               /* set the current beacon state */
+       }
+
+       if (h_beacon)
+               err = qlcnic_83xx_config_led(adapter, 1, h_beacon);
+       else
+               err = qlcnic_83xx_config_led(adapter, 0, !h_beacon);
+       if (!err)
                ahw->beacon_state = h_beacon;
-beacon_err:
-               if (!ahw->beacon_state)
-                       clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
 
-               rtnl_unlock();
-               return len;
-       }
+       if (!ahw->beacon_state)
+               clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
+
+       rtnl_unlock();
+       return len;
+}
+
+static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
+                                   const char *buf, size_t len)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       int err, max_sds_rings = adapter->max_sds_rings;
+       u16 beacon;
+       u8 h_beacon_state, b_state, b_rate;
 
        if (len != sizeof(u16))
                return QL_STATUS_INVALID_PARAM;
@@ -174,16 +168,29 @@ beacon_err:
        if (err)
                return err;
 
-       if (adapter->ahw->beacon_state == b_state)
+       if ((ahw->capabilities2 & QLCNIC_FW_CAPABILITY_2_BEACON)) {
+               err = qlcnic_get_beacon_state(adapter, &h_beacon_state);
+               if (!err) {
+                       dev_info(&adapter->pdev->dev,
+                                "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;
+               }
+       }
+
+       if (ahw->beacon_state == b_state)
                return len;
 
        rtnl_lock();
-
-       if (!adapter->ahw->beacon_state)
+       if (!ahw->beacon_state) {
                if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
                        rtnl_unlock();
                        return -EBUSY;
                }
+       }
 
        if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
                err = -EIO;
@@ -206,14 +213,37 @@ beacon_err:
        if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
                qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
 
- out:
-       if (!adapter->ahw->beacon_state)
+out:
+       if (!ahw->beacon_state)
                clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
        rtnl_unlock();
 
        return err;
 }
 
+static ssize_t qlcnic_store_beacon(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t len)
+{
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       int err = 0;
+
+       if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
+               dev_warn(dev,
+                        "LED test not supported in non privileged mode\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (qlcnic_82xx_check(adapter))
+               err = qlcnic_82xx_store_beacon(adapter, buf, len);
+       else if (qlcnic_83xx_check(adapter))
+               err = qlcnic_83xx_store_beacon(adapter, buf, len);
+       else
+               return -EIO;
+
+       return err;
+}
+
 static ssize_t qlcnic_show_beacon(struct device *dev,
                                  struct device_attribute *attr, char *buf)
 {
index f87cc216045b5feb5e20dbc2f4df3fe2190eba14..2553cf4503b9f83996bb72bd291fb756558644f9 100644 (file)
@@ -4946,15 +4946,4 @@ static struct pci_driver qlge_driver = {
        .err_handler = &qlge_err_handler
 };
 
-static int __init qlge_init_module(void)
-{
-       return pci_register_driver(&qlge_driver);
-}
-
-static void __exit qlge_exit(void)
-{
-       pci_unregister_driver(&qlge_driver);
-}
-
-module_init(qlge_init_module);
-module_exit(qlge_exit);
+module_pci_driver(qlge_driver);
index 42e9dd05c936df55e2bc62754259e1ff6e81785d..399a7c968e0d4d9e2ab48052c8f25819aac23db8 100644 (file)
@@ -2803,7 +2803,6 @@ static int sh_eth_drv_remove(struct platform_device *pdev)
        unregister_netdev(ndev);
        pm_runtime_disable(&pdev->dev);
        free_netdev(ndev);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index b6739afeaca1517bf3351dae9e3a33469cccc46e..a99739c5142cb1f296a7fa8ea83a4efca8f68ea6 100644 (file)
@@ -1040,7 +1040,6 @@ static int s6gmac_remove(struct platform_device *pdev)
                unregister_netdev(dev);
                free_irq(dev->irq, dev);
                free_netdev(dev);
-               platform_set_drvdata(pdev, NULL);
        }
        return 0;
 }
index 0ad5694b41f8eb12d43d2e518b89607ef373bbea..856e523ac936edfbd4f32c55335fc13b1e2443d8 100644 (file)
@@ -818,7 +818,6 @@ static int __exit sgiseeq_remove(struct platform_device *pdev)
        dma_free_noncoherent(&pdev->dev, sizeof(*sp->srings), sp->srings,
                             sp->srings_dma);
        free_netdev(dev);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index 39e4cb39de29493d30079f3ddcfc81e46cfbf5b4..46cc11d5e205a22cdb6e6e4308731ea0b75b8b93 100644 (file)
@@ -2120,7 +2120,7 @@ static void efx_update_name(struct efx_nic *efx)
 static int efx_netdev_event(struct notifier_block *this,
                            unsigned long event, void *ptr)
 {
-       struct net_device *net_dev = ptr;
+       struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
 
        if (net_dev->netdev_ops == &efx_netdev_ops &&
            event == NETDEV_CHANGENAME)
index 7ed08c32a9c512621665d14566e3371f24108398..ffa78432164dd0f9a20e5ff66e67fedca1ab4425 100644 (file)
@@ -1398,16 +1398,6 @@ static struct pci_driver ioc3_driver = {
        .remove         = ioc3_remove_one,
 };
 
-static int __init ioc3_init_module(void)
-{
-       return pci_register_driver(&ioc3_driver);
-}
-
-static void __exit ioc3_cleanup_module(void)
-{
-       pci_unregister_driver(&ioc3_driver);
-}
-
 static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        unsigned long data;
@@ -1677,9 +1667,7 @@ static void ioc3_set_multicast_list(struct net_device *dev)
        netif_wake_queue(dev);                  /* Let us get going again. */
 }
 
+module_pci_driver(ioc3_driver);
 MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
 MODULE_DESCRIPTION("SGI IOC3 Ethernet driver");
 MODULE_LICENSE("GPL");
-
-module_init(ioc3_init_module);
-module_exit(ioc3_cleanup_module);
index 4bdbaad9932df37f1fb92e8eb3c5e76bc2efc6be..9f5f35e041ac599681576aa06b9ee24033cfbd12 100644 (file)
@@ -863,7 +863,6 @@ static int __exit meth_remove(struct platform_device *pdev)
 
        unregister_netdev(dev);
        free_netdev(dev);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index 28f7268f1b8802eed15756784b5d68f298a7976a..5eb933c97bbacf26123d1857949515e6b04adbee 100644 (file)
@@ -1578,19 +1578,7 @@ static struct pci_driver sc92031_pci_driver = {
        .resume         = sc92031_resume,
 };
 
-static int __init sc92031_init(void)
-{
-       return pci_register_driver(&sc92031_pci_driver);
-}
-
-static void __exit sc92031_exit(void)
-{
-       pci_unregister_driver(&sc92031_pci_driver);
-}
-
-module_init(sc92031_init);
-module_exit(sc92031_exit);
-
+module_pci_driver(sc92031_pci_driver);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Cesar Eduardo Barros <cesarb@cesarb.net>");
 MODULE_DESCRIPTION("Silan SC92031 PCI Fast Ethernet Adapter driver");
index 9a9c379420d120049bb43e53da5849be904d234d..02df0894690d698c7234e8057a58714ad65a2915 100644 (file)
@@ -1934,15 +1934,4 @@ static struct pci_driver sis190_pci_driver = {
        .remove         = sis190_remove_one,
 };
 
-static int __init sis190_init_module(void)
-{
-       return pci_register_driver(&sis190_pci_driver);
-}
-
-static void __exit sis190_cleanup_module(void)
-{
-       pci_unregister_driver(&sis190_pci_driver);
-}
-
-module_init(sis190_init_module);
-module_exit(sis190_cleanup_module);
+module_pci_driver(sis190_pci_driver);
index bb4c1674ff99b1df733baf3823f01ca565fe22a3..ff9e9947403900af8215ee809de77acfad719427 100644 (file)
@@ -97,7 +97,7 @@ config SMC911X
 
 config SMSC911X
        tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
-       depends on (ARM || SUPERH || BLACKFIN || MIPS || MN10300)
+       depends on HAS_IOMEM
        select CRC32
        select NET_CORE
        select MII
index 9dd842dbb8598b9d7825637238ce2d64aaa53f4a..345558fe7367fdeee216642981b0c632f734d9c0 100644 (file)
@@ -2087,7 +2087,6 @@ static int smc911x_drv_probe(struct platform_device *pdev)
        ndev->base_addr = res->start;
        ret = smc911x_probe(ndev);
        if (ret != 0) {
-               platform_set_drvdata(pdev, NULL);
                iounmap(addr);
 release_both:
                free_netdev(ndev);
@@ -2113,7 +2112,6 @@ static int smc911x_drv_remove(struct platform_device *pdev)
        struct resource *res;
 
        DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__);
-       platform_set_drvdata(pdev, NULL);
 
        unregister_netdev(ndev);
 
index dfbf978315dfb31a8cbbd01ce5beae06abc5f398..cde13be7c7ded5e5fc7265052693f6281dd7cd97 100644 (file)
@@ -2299,7 +2299,6 @@ static int smc_drv_probe(struct platform_device *pdev)
        return 0;
 
  out_iounmap:
-       platform_set_drvdata(pdev, NULL);
        iounmap(addr);
  out_release_attrib:
        smc_release_attrib(pdev, ndev);
@@ -2319,8 +2318,6 @@ static int smc_drv_remove(struct platform_device *pdev)
        struct smc_local *lp = netdev_priv(ndev);
        struct resource *res;
 
-       platform_set_drvdata(pdev, NULL);
-
        unregister_netdev(ndev);
 
        free_irq(ndev->irq, ndev);
index 3663b9e04a31345b3a0a02ba28e8c9111de11737..a1419211585bb150188262adec08291ad0a82f38 100644 (file)
@@ -2284,7 +2284,6 @@ static int smsc911x_drv_remove(struct platform_device *pdev)
        mdiobus_unregister(pdata->mii_bus);
        mdiobus_free(pdata->mii_bus);
 
-       platform_set_drvdata(pdev, NULL);
        unregister_netdev(dev);
        free_irq(dev->irq, dev);
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -2539,7 +2538,6 @@ out_disable_resources:
 out_enable_resources_fail:
        smsc911x_free_resources(pdev);
 out_request_resources_fail:
-       platform_set_drvdata(pdev, NULL);
        iounmap(pdata->ioaddr);
        free_netdev(dev);
 out_release_io_1:
index 1d3780f55ba2c9397641b1b5986b952680259e0c..17bc7827e7cafded7ce96bb4a024ac6d8ebf525d 100644 (file)
@@ -171,8 +171,6 @@ static int stmmac_pltfr_remove(struct platform_device *pdev)
        if (priv->plat->exit)
                priv->plat->exit(pdev);
 
-       platform_set_drvdata(pdev, NULL);
-
        return ret;
 }
 
index 95cff98d8a34e2a4ba355b03554562bb76d23152..fa322409bff33376dbedc59f6921a2337a60eebc 100644 (file)
@@ -10108,7 +10108,7 @@ static int niu_of_probe(struct platform_device *op)
                goto err_out_iounmap;
        }
 
-       dev_set_drvdata(&op->dev, dev);
+       platform_set_drvdata(op, dev);
 
        niu_device_announce(np);
 
@@ -10145,7 +10145,7 @@ err_out:
 
 static int niu_of_remove(struct platform_device *op)
 {
-       struct net_device *dev = dev_get_drvdata(&op->dev);
+       struct net_device *dev = platform_get_drvdata(op);
 
        if (dev) {
                struct niu *np = netdev_priv(dev);
@@ -10175,7 +10175,6 @@ static int niu_of_remove(struct platform_device *op)
                niu_put_parent(np);
 
                free_netdev(dev);
-               dev_set_drvdata(&op->dev, NULL);
        }
        return 0;
 }
index 054975939a184cc48035009420e8d1663871b0f9..09b4f8c0b199a390cf0ed8a7206e2788308f0818 100644 (file)
@@ -1017,10 +1017,7 @@ static void bigmac_set_multicast(struct net_device *dev)
                tmp |= BIGMAC_RXCFG_PMISC;
                sbus_writel(tmp, bregs + BMAC_RXCFG);
        } else {
-               u16 hash_table[4];
-
-               for (i = 0; i < 4; i++)
-                       hash_table[i] = 0;
+               u16 hash_table[4] = { 0 };
 
                netdev_for_each_mc_addr(ha, dev) {
                        crc = ether_crc_le(6, ha->addr);
index 5f3f9d52757dbffb60eb277d45acdc6a29eb49f6..e62df2b81302bd32881ca22daef127e04985679e 100644 (file)
@@ -3028,15 +3028,4 @@ static struct pci_driver gem_driver = {
 #endif /* CONFIG_PM */
 };
 
-static int __init gem_init(void)
-{
-       return pci_register_driver(&gem_driver);
-}
-
-static void __exit gem_cleanup(void)
-{
-       pci_unregister_driver(&gem_driver);
-}
-
-module_init(gem_init);
-module_exit(gem_cleanup);
+module_pci_driver(gem_driver);
index 436fa9d5a07190a555adc6a6b7119700845b2b73..171f5b0809c4d1659cd26d8ba7255a915c1d8f70 100644 (file)
@@ -2506,7 +2506,7 @@ static struct quattro *quattro_sbus_find(struct platform_device *child)
        struct quattro *qp;
 
        op = to_platform_device(parent);
-       qp = dev_get_drvdata(&op->dev);
+       qp = platform_get_drvdata(op);
        if (qp)
                return qp;
 
@@ -2521,7 +2521,7 @@ static struct quattro *quattro_sbus_find(struct platform_device *child)
                qp->next = qfe_sbus_list;
                qfe_sbus_list = qp;
 
-               dev_set_drvdata(&op->dev, qp);
+               platform_set_drvdata(op, qp);
        }
        return qp;
 }
index 8182591bc1876c77ddae935d6da64d9200a2dbcc..b072f4dba033c1661bf4a341747b1d82d4874fc7 100644 (file)
@@ -767,7 +767,7 @@ static struct sunqec *get_qec(struct platform_device *child)
        struct platform_device *op = to_platform_device(child->dev.parent);
        struct sunqec *qecp;
 
-       qecp = dev_get_drvdata(&op->dev);
+       qecp = platform_get_drvdata(op);
        if (!qecp) {
                qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL);
                if (qecp) {
@@ -801,7 +801,7 @@ static struct sunqec *get_qec(struct platform_device *child)
                                goto fail;
                        }
 
-                       dev_set_drvdata(&op->dev, qecp);
+                       platform_set_drvdata(op, qecp);
 
                        qecp->next_module = root_qec_dev;
                        root_qec_dev = qecp;
@@ -902,7 +902,7 @@ static int qec_ether_init(struct platform_device *op)
        if (res)
                goto fail;
 
-       dev_set_drvdata(&op->dev, qe);
+       platform_set_drvdata(op, qe);
 
        printk(KERN_INFO "%s: qe channel[%d] %pM\n", dev->name, qe->channel,
               dev->dev_addr);
@@ -934,7 +934,7 @@ static int qec_sbus_probe(struct platform_device *op)
 
 static int qec_sbus_remove(struct platform_device *op)
 {
-       struct sunqe *qp = dev_get_drvdata(&op->dev);
+       struct sunqe *qp = platform_get_drvdata(op);
        struct net_device *net_dev = qp->dev;
 
        unregister_netdev(net_dev);
@@ -948,8 +948,6 @@ static int qec_sbus_remove(struct platform_device *op)
 
        free_netdev(net_dev);
 
-       dev_set_drvdata(&op->dev, NULL);
-
        return 0;
 }
 
index 21a5b291b4b39d0ae65dcd8766c9e51a25665dee..a45f64eef8709b9d1ba3ec5196df4a3ba58fb740 100644 (file)
@@ -1554,6 +1554,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                if (mac_addr)
                        memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
+               slave_data->phy_if = of_get_phy_mode(slave_node);
+
                if (data->dual_emac) {
                        if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
                                                 &prop)) {
@@ -1940,7 +1942,6 @@ static int cpsw_remove(struct platform_device *pdev)
        struct cpsw_priv *priv = netdev_priv(ndev);
        int i;
 
-       platform_set_drvdata(pdev, NULL);
        if (priv->data.dual_emac)
                unregister_netdev(cpsw_get_slave_ndev(priv, 1));
        unregister_netdev(ndev);
index 49dfd592ac1ecd4e0a86d8d5ad01572a97e5c346..a377bc72774084b567642c7dab0e4e89922e4cf6 100644 (file)
@@ -64,6 +64,7 @@
 #define CPDMA_DESC_TO_PORT_EN  BIT(20)
 #define CPDMA_TO_PORT_SHIFT    16
 #define CPDMA_DESC_PORT_MASK   (BIT(18) | BIT(17) | BIT(16))
+#define CPDMA_DESC_CRC_LEN     4
 
 #define CPDMA_TEARDOWN_VALUE   0xfffffffc
 
@@ -798,6 +799,10 @@ static int __cpdma_chan_process(struct cpdma_chan *chan)
                status = -EBUSY;
                goto unlock_ret;
        }
+
+       if (status & CPDMA_DESC_PASS_CRC)
+               outlen -= CPDMA_DESC_CRC_LEN;
+
        status  = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE |
                            CPDMA_DESC_PORT_MASK);
 
index 860e15ddfbcbcd7232da1c71779793442d72a1c1..efb6f65a8be3d12d947e96d53bccd99f940f00f4 100644 (file)
@@ -2037,8 +2037,6 @@ static int davinci_emac_remove(struct platform_device *pdev)
 
        dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n");
 
-       platform_set_drvdata(pdev, NULL);
-
        if (priv->txchan)
                cpdma_chan_destroy(priv->txchan);
        if (priv->rxchan)
index 60c400f6d01ff540b6a2e132c3520972336adb1a..59abfbcd0d551e02cb25fae12216720a154f4bda 100644 (file)
@@ -533,7 +533,6 @@ static int tlan_probe1(struct pci_dev *pdev, long ioaddr, int irq, int rev,
                /* This is a hack. We need to know which board structure
                 * is suited for this adapter */
                device_id = inw(ioaddr + EISA_ID2);
-               priv->is_eisa = 1;
                if (device_id == 0x20F1) {
                        priv->adapter = &board_info[13]; /* NetFlex-3/E */
                        priv->adapter_rev = 23;         /* TLAN 2.3 */
index 5fc98a8e488900c07757b59c7464b5e0a54b7855..2eb33a250788abca1235d3ee93d809b422eb328d 100644 (file)
@@ -207,7 +207,6 @@ struct tlan_priv {
        u8                      tlan_full_duplex;
        spinlock_t              lock;
        u8                      link;
-       u8                      is_eisa;
        struct work_struct                      tlan_tqueue;
        u8                      neg_be_verbose;
 };
index fe256094db35d8c745873a29851e5622746b999a..a971b9cca564c910f8e928806ea9ac443ed22cf2 100644 (file)
@@ -2209,18 +2209,6 @@ MODULE_PARM_DESC(speed, "0:auto, 10:10Mbps, 100:100Mbps");
 module_param_named(duplex, options.duplex, int, 0);
 MODULE_PARM_DESC(duplex, "0:auto, 1:half, 2:full");
 
-static int __init tc35815_init_module(void)
-{
-       return pci_register_driver(&tc35815_pci_driver);
-}
-
-static void __exit tc35815_cleanup_module(void)
-{
-       pci_unregister_driver(&tc35815_pci_driver);
-}
-
-module_init(tc35815_init_module);
-module_exit(tc35815_cleanup_module);
-
+module_pci_driver(tc35815_pci_driver);
 MODULE_DESCRIPTION("TOSHIBA TC35815 PCI 10M/100M Ethernet driver");
 MODULE_LICENSE("GPL");
index 3c69a04608324c8c16bc33cee78f03f524329018..01bdc6ca0755feff940d8bede196ba83d85c2f06 100644 (file)
@@ -1682,7 +1682,6 @@ static int tsi108_ether_remove(struct platform_device *pdev)
 
        unregister_netdev(dev);
        tsi108_stop_ethernet(dev);
-       platform_set_drvdata(pdev, NULL);
        iounmap(priv->regs);
        iounmap(priv->phyregs);
        free_netdev(dev);
index 68a9ba66feba866f2da80d39f34eed63fc8082ca..6a87097d88c06b316a3a05e24a8017d4d350780e 100644 (file)
@@ -5,7 +5,6 @@
 config NET_VENDOR_VIA
        bool "VIA devices"
        default y
-       depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
@@ -45,7 +44,7 @@ config VIA_RHINE_MMIO
 
 config VIA_VELOCITY
        tristate "VIA Velocity support"
-       depends on PCI
+       depends on (PCI || USE_OF)
        select CRC32
        select CRC_CCITT
        select NET_CORE
index fb6248956ee26ec55c8c4cbcd853fc721c74e1d7..76919948b4ee32bd4e79a9ddce25e962e6437add 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/types.h>
 #include <linux/bitops.h>
 #include <linux/init.h>
+#include <linux/dma-mapping.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/if.h>
 #include <linux/uaccess.h>
 #include <linux/proc_fs.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/inetdevice.h>
+#include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 
 #include "via-velocity.h"
 
+enum velocity_bus_type {
+       BUS_PCI,
+       BUS_PLATFORM,
+};
 
 static int velocity_nics;
 static int msglevel = MSG_LEVEL_INFO;
 
+static void velocity_set_power_state(struct velocity_info *vptr, char state)
+{
+       void *addr = vptr->mac_regs;
+
+       if (vptr->pdev)
+               pci_set_power_state(vptr->pdev, state);
+       else
+               writeb(state, addr + 0x154);
+}
+
 /**
  *     mac_get_cam_mask        -       Read a CAM mask
  *     @regs: register block for this velocity
@@ -361,12 +380,23 @@ static struct velocity_info_tbl chip_info_table[] = {
  *     Describe the PCI device identifiers that we support in this
  *     device driver. Used for hotplug autoloading.
  */
-static DEFINE_PCI_DEVICE_TABLE(velocity_id_table) = {
+
+static DEFINE_PCI_DEVICE_TABLE(velocity_pci_id_table) = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
        { }
 };
 
-MODULE_DEVICE_TABLE(pci, velocity_id_table);
+MODULE_DEVICE_TABLE(pci, velocity_pci_id_table);
+
+/**
+ *     Describe the OF device identifiers that we support in this
+ *     device driver. Used for devicetree nodes.
+ */
+static struct of_device_id velocity_of_ids[] = {
+       { .compatible = "via,velocity-vt6110", .data = &chip_info_table[0] },
+       { /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, velocity_of_ids);
 
 /**
  *     get_chip_name   -       identifier to name
@@ -384,29 +414,6 @@ static const char *get_chip_name(enum chip_type chip_id)
        return chip_info_table[i].name;
 }
 
-/**
- *     velocity_remove1        -       device unplug
- *     @pdev: PCI device being removed
- *
- *     Device unload callback. Called on an unplug or on module
- *     unload for each active device that is present. Disconnects
- *     the device from the network layer and frees all the resources
- */
-static void velocity_remove1(struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct velocity_info *vptr = netdev_priv(dev);
-
-       unregister_netdev(dev);
-       iounmap(vptr->mac_regs);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
-       free_netdev(dev);
-
-       velocity_nics--;
-}
-
 /**
  *     velocity_set_int_opt    -       parser for integer options
  *     @opt: pointer to option value
@@ -998,9 +1005,9 @@ static void velocity_print_link_status(struct velocity_info *vptr)
 {
 
        if (vptr->mii_status & VELOCITY_LINK_FAIL) {
-               VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);
+               VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->netdev->name);
        } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
-               VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name);
+               VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->netdev->name);
 
                if (vptr->mii_status & VELOCITY_SPEED_1000)
                        VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");
@@ -1014,7 +1021,7 @@ static void velocity_print_link_status(struct velocity_info *vptr)
                else
                        VELOCITY_PRT(MSG_LEVEL_INFO, " half duplex\n");
        } else {
-               VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);
+               VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->netdev->name);
                switch (vptr->options.spd_dpx) {
                case SPD_DPX_1000_FULL:
                        VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps full duplex\n");
@@ -1180,6 +1187,17 @@ static void mii_init(struct velocity_info *vptr, u32 mii_status)
        u16 BMCR;
 
        switch (PHYID_GET_PHY_ID(vptr->phy_id)) {
+       case PHYID_ICPLUS_IP101A:
+               MII_REG_BITS_ON((ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP),
+                                               MII_ADVERTISE, vptr->mac_regs);
+               if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+                       MII_REG_BITS_ON(TCSR_ECHODIS, MII_SREVISION,
+                                                               vptr->mac_regs);
+               else
+                       MII_REG_BITS_OFF(TCSR_ECHODIS, MII_SREVISION,
+                                                               vptr->mac_regs);
+               MII_REG_BITS_ON(PLED_LALBE, MII_TPISTATUS, vptr->mac_regs);
+               break;
        case PHYID_CICADA_CS8201:
                /*
                 *      Reset to hardware default
@@ -1311,6 +1329,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
                                    enum velocity_init_type type)
 {
        struct mac_regs __iomem *regs = vptr->mac_regs;
+       struct net_device *netdev = vptr->netdev;
        int i, mii_status;
 
        mac_wol_reset(regs);
@@ -1319,7 +1338,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
        case VELOCITY_INIT_RESET:
        case VELOCITY_INIT_WOL:
 
-               netif_stop_queue(vptr->dev);
+               netif_stop_queue(netdev);
 
                /*
                 *      Reset RX to prevent RX pointer not on the 4X location
@@ -1332,7 +1351,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
                if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
                        velocity_print_link_status(vptr);
                        if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
-                               netif_wake_queue(vptr->dev);
+                               netif_wake_queue(netdev);
                }
 
                enable_flow_control_ability(vptr);
@@ -1352,9 +1371,11 @@ static void velocity_init_registers(struct velocity_info *vptr,
                velocity_soft_reset(vptr);
                mdelay(5);
 
-               mac_eeprom_reload(regs);
-               for (i = 0; i < 6; i++)
-                       writeb(vptr->dev->dev_addr[i], &(regs->PAR[i]));
+               if (!vptr->no_eeprom) {
+                       mac_eeprom_reload(regs);
+                       for (i = 0; i < 6; i++)
+                               writeb(netdev->dev_addr[i], regs->PAR + i);
+               }
 
                /*
                 *      clear Pre_ACPI bit.
@@ -1377,7 +1398,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
                /*
                 *      Set packet filter: Receive directed and broadcast address
                 */
-               velocity_set_multi(vptr->dev);
+               velocity_set_multi(netdev);
 
                /*
                 *      Enable MII auto-polling
@@ -1404,14 +1425,14 @@ static void velocity_init_registers(struct velocity_info *vptr,
                writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), &regs->CR0Set);
 
                mii_status = velocity_get_opt_media_mode(vptr);
-               netif_stop_queue(vptr->dev);
+               netif_stop_queue(netdev);
 
                mii_init(vptr, mii_status);
 
                if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
                        velocity_print_link_status(vptr);
                        if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
-                               netif_wake_queue(vptr->dev);
+                               netif_wake_queue(netdev);
                }
 
                enable_flow_control_ability(vptr);
@@ -1459,7 +1480,6 @@ static int velocity_init_dma_rings(struct velocity_info *vptr)
        struct velocity_opt *opt = &vptr->options;
        const unsigned int rx_ring_size = opt->numrx * sizeof(struct rx_desc);
        const unsigned int tx_ring_size = opt->numtx * sizeof(struct tx_desc);
-       struct pci_dev *pdev = vptr->pdev;
        dma_addr_t pool_dma;
        void *pool;
        unsigned int i;
@@ -1467,14 +1487,14 @@ static int velocity_init_dma_rings(struct velocity_info *vptr)
        /*
         * Allocate all RD/TD rings a single pool.
         *
-        * pci_alloc_consistent() fulfills the requirement for 64 bytes
+        * dma_alloc_coherent() fulfills the requirement for 64 bytes
         * alignment
         */
-       pool = pci_alloc_consistent(pdev, tx_ring_size * vptr->tx.numq +
-                                   rx_ring_size, &pool_dma);
+       pool = dma_alloc_coherent(vptr->dev, tx_ring_size * vptr->tx.numq +
+                                   rx_ring_size, &pool_dma, GFP_ATOMIC);
        if (!pool) {
-               dev_err(&pdev->dev, "%s : DMA memory allocation failed.\n",
-                       vptr->dev->name);
+               dev_err(vptr->dev, "%s : DMA memory allocation failed.\n",
+                       vptr->netdev->name);
                return -ENOMEM;
        }
 
@@ -1514,7 +1534,7 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
        struct rx_desc *rd = &(vptr->rx.ring[idx]);
        struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
 
-       rd_info->skb = netdev_alloc_skb(vptr->dev, vptr->rx.buf_sz + 64);
+       rd_info->skb = netdev_alloc_skb(vptr->netdev, vptr->rx.buf_sz + 64);
        if (rd_info->skb == NULL)
                return -ENOMEM;
 
@@ -1524,8 +1544,8 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
         */
        skb_reserve(rd_info->skb,
                        64 - ((unsigned long) rd_info->skb->data & 63));
-       rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->data,
-                                       vptr->rx.buf_sz, PCI_DMA_FROMDEVICE);
+       rd_info->skb_dma = dma_map_single(vptr->dev, rd_info->skb->data,
+                                       vptr->rx.buf_sz, DMA_FROM_DEVICE);
 
        /*
         *      Fill in the descriptor to match
@@ -1588,8 +1608,8 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
 
                if (!rd_info->skb)
                        continue;
-               pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx.buf_sz,
-                                PCI_DMA_FROMDEVICE);
+               dma_unmap_single(vptr->dev, rd_info->skb_dma, vptr->rx.buf_sz,
+                                DMA_FROM_DEVICE);
                rd_info->skb_dma = 0;
 
                dev_kfree_skb(rd_info->skb);
@@ -1620,7 +1640,7 @@ static int velocity_init_rd_ring(struct velocity_info *vptr)
 
        if (velocity_rx_refill(vptr) != vptr->options.numrx) {
                VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
-                       "%s: failed to allocate RX buffer.\n", vptr->dev->name);
+                       "%s: failed to allocate RX buffer.\n", vptr->netdev->name);
                velocity_free_rd_ring(vptr);
                goto out;
        }
@@ -1670,7 +1690,7 @@ static void velocity_free_dma_rings(struct velocity_info *vptr)
        const int size = vptr->options.numrx * sizeof(struct rx_desc) +
                vptr->options.numtx * sizeof(struct tx_desc) * vptr->tx.numq;
 
-       pci_free_consistent(vptr->pdev, size, vptr->rx.ring, vptr->rx.pool_dma);
+       dma_free_coherent(vptr->dev, size, vptr->rx.ring, vptr->rx.pool_dma);
 }
 
 static int velocity_init_rings(struct velocity_info *vptr, int mtu)
@@ -1727,8 +1747,8 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
                                pktlen = max_t(size_t, pktlen,
                                                td->td_buf[i].size & ~TD_QUEUE);
 
-                       pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i],
-                                       le16_to_cpu(pktlen), PCI_DMA_TODEVICE);
+                       dma_unmap_single(vptr->dev, tdinfo->skb_dma[i],
+                                       le16_to_cpu(pktlen), DMA_TO_DEVICE);
                }
        }
        dev_kfree_skb_irq(skb);
@@ -1750,8 +1770,8 @@ static void velocity_free_td_ring_entry(struct velocity_info *vptr,
        if (td_info->skb) {
                for (i = 0; i < td_info->nskb_dma; i++) {
                        if (td_info->skb_dma[i]) {
-                               pci_unmap_single(vptr->pdev, td_info->skb_dma[i],
-                                       td_info->skb->len, PCI_DMA_TODEVICE);
+                               dma_unmap_single(vptr->dev, td_info->skb_dma[i],
+                                       td_info->skb->len, DMA_TO_DEVICE);
                                td_info->skb_dma[i] = 0;
                        }
                }
@@ -1809,7 +1829,7 @@ static void velocity_error(struct velocity_info *vptr, int status)
                printk(KERN_ERR "TD structure error TDindex=%hx\n", readw(&regs->TDIdx[0]));
                BYTE_REG_BITS_ON(TXESR_TDSTR, &regs->TXESR);
                writew(TRDCSR_RUN, &regs->TDCSRClr);
-               netif_stop_queue(vptr->dev);
+               netif_stop_queue(vptr->netdev);
 
                /* FIXME: port over the pci_device_failed code and use it
                   here */
@@ -1850,10 +1870,10 @@ static void velocity_error(struct velocity_info *vptr, int status)
 
                if (linked) {
                        vptr->mii_status &= ~VELOCITY_LINK_FAIL;
-                       netif_carrier_on(vptr->dev);
+                       netif_carrier_on(vptr->netdev);
                } else {
                        vptr->mii_status |= VELOCITY_LINK_FAIL;
-                       netif_carrier_off(vptr->dev);
+                       netif_carrier_off(vptr->netdev);
                }
 
                velocity_print_link_status(vptr);
@@ -1867,9 +1887,9 @@ static void velocity_error(struct velocity_info *vptr, int status)
                enable_mii_autopoll(regs);
 
                if (vptr->mii_status & VELOCITY_LINK_FAIL)
-                       netif_stop_queue(vptr->dev);
+                       netif_stop_queue(vptr->netdev);
                else
-                       netif_wake_queue(vptr->dev);
+                       netif_wake_queue(vptr->netdev);
 
        }
        if (status & ISR_MIBFI)
@@ -1894,7 +1914,7 @@ static int velocity_tx_srv(struct velocity_info *vptr)
        int idx;
        int works = 0;
        struct velocity_td_info *tdinfo;
-       struct net_device_stats *stats = &vptr->dev->stats;
+       struct net_device_stats *stats = &vptr->netdev->stats;
 
        for (qnum = 0; qnum < vptr->tx.numq; qnum++) {
                for (idx = vptr->tx.tail[qnum]; vptr->tx.used[qnum] > 0;
@@ -1939,9 +1959,9 @@ static int velocity_tx_srv(struct velocity_info *vptr)
         *      Look to see if we should kick the transmit network
         *      layer for more work.
         */
-       if (netif_queue_stopped(vptr->dev) && (full == 0) &&
+       if (netif_queue_stopped(vptr->netdev) && (full == 0) &&
            (!(vptr->mii_status & VELOCITY_LINK_FAIL))) {
-               netif_wake_queue(vptr->dev);
+               netif_wake_queue(vptr->netdev);
        }
        return works;
 }
@@ -1989,7 +2009,7 @@ static int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size,
        if (pkt_size < rx_copybreak) {
                struct sk_buff *new_skb;
 
-               new_skb = netdev_alloc_skb_ip_align(vptr->dev, pkt_size);
+               new_skb = netdev_alloc_skb_ip_align(vptr->netdev, pkt_size);
                if (new_skb) {
                        new_skb->ip_summed = rx_skb[0]->ip_summed;
                        skb_copy_from_linear_data(*rx_skb, new_skb->data, pkt_size);
@@ -2029,15 +2049,14 @@ static inline void velocity_iph_realign(struct velocity_info *vptr,
  */
 static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 {
-       void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int);
-       struct net_device_stats *stats = &vptr->dev->stats;
+       struct net_device_stats *stats = &vptr->netdev->stats;
        struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
        struct rx_desc *rd = &(vptr->rx.ring[idx]);
        int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff;
        struct sk_buff *skb;
 
        if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
-               VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->dev->name);
+               VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->netdev->name);
                stats->rx_length_errors++;
                return -EINVAL;
        }
@@ -2047,8 +2066,8 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 
        skb = rd_info->skb;
 
-       pci_dma_sync_single_for_cpu(vptr->pdev, rd_info->skb_dma,
-                                   vptr->rx.buf_sz, PCI_DMA_FROMDEVICE);
+       dma_sync_single_for_cpu(vptr->dev, rd_info->skb_dma,
+                                   vptr->rx.buf_sz, DMA_FROM_DEVICE);
 
        /*
         *      Drop frame not meeting IEEE 802.3
@@ -2061,21 +2080,20 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
                }
        }
 
-       pci_action = pci_dma_sync_single_for_device;
-
        velocity_rx_csum(rd, skb);
 
        if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) {
                velocity_iph_realign(vptr, skb, pkt_len);
-               pci_action = pci_unmap_single;
                rd_info->skb = NULL;
+               dma_unmap_single(vptr->dev, rd_info->skb_dma, vptr->rx.buf_sz,
+                                DMA_FROM_DEVICE);
+       } else {
+               dma_sync_single_for_device(vptr->dev, rd_info->skb_dma,
+                                          vptr->rx.buf_sz, DMA_FROM_DEVICE);
        }
 
-       pci_action(vptr->pdev, rd_info->skb_dma, vptr->rx.buf_sz,
-                  PCI_DMA_FROMDEVICE);
-
        skb_put(skb, pkt_len - 4);
-       skb->protocol = eth_type_trans(skb, vptr->dev);
+       skb->protocol = eth_type_trans(skb, vptr->netdev);
 
        if (rd->rdesc0.RSR & RSR_DETAG) {
                u16 vid = swab16(le16_to_cpu(rd->rdesc1.PQTAG));
@@ -2100,7 +2118,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
  */
 static int velocity_rx_srv(struct velocity_info *vptr, int budget_left)
 {
-       struct net_device_stats *stats = &vptr->dev->stats;
+       struct net_device_stats *stats = &vptr->netdev->stats;
        int rd_curr = vptr->rx.curr;
        int works = 0;
 
@@ -2235,15 +2253,15 @@ static int velocity_open(struct net_device *dev)
                goto out;
 
        /* Ensure chip is running */
-       pci_set_power_state(vptr->pdev, PCI_D0);
+       velocity_set_power_state(vptr, PCI_D0);
 
        velocity_init_registers(vptr, VELOCITY_INIT_COLD);
 
-       ret = request_irq(vptr->pdev->irq, velocity_intr, IRQF_SHARED,
+       ret = request_irq(dev->irq, velocity_intr, IRQF_SHARED,
                          dev->name, dev);
        if (ret < 0) {
                /* Power down the chip */
-               pci_set_power_state(vptr->pdev, PCI_D3hot);
+               velocity_set_power_state(vptr, PCI_D3hot);
                velocity_free_rings(vptr);
                goto out;
        }
@@ -2292,7 +2310,7 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
 
        if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) {
                VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n",
-                               vptr->dev->name);
+                               vptr->netdev->name);
                ret = -EINVAL;
                goto out_0;
        }
@@ -2314,8 +2332,9 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
                        goto out_0;
                }
 
-               tmp_vptr->dev = dev;
+               tmp_vptr->netdev = dev;
                tmp_vptr->pdev = vptr->pdev;
+               tmp_vptr->dev = vptr->dev;
                tmp_vptr->options = vptr->options;
                tmp_vptr->tx.numq = vptr->tx.numq;
 
@@ -2415,7 +2434,7 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
           saving then we need to bring the device back up to talk to it */
 
        if (!netif_running(dev))
-               pci_set_power_state(vptr->pdev, PCI_D0);
+               velocity_set_power_state(vptr, PCI_D0);
 
        switch (cmd) {
        case SIOCGMIIPHY:       /* Get address of MII PHY in use. */
@@ -2428,7 +2447,7 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                ret = -EOPNOTSUPP;
        }
        if (!netif_running(dev))
-               pci_set_power_state(vptr->pdev, PCI_D3hot);
+               velocity_set_power_state(vptr, PCI_D3hot);
 
 
        return ret;
@@ -2494,7 +2513,7 @@ static int velocity_close(struct net_device *dev)
        if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED)
                velocity_get_ip(vptr);
 
-       free_irq(vptr->pdev->irq, dev);
+       free_irq(dev->irq, dev);
 
        velocity_free_rings(vptr);
 
@@ -2550,7 +2569,8 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
         *      add it to the transmit ring.
         */
        tdinfo->skb = skb;
-       tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE);
+       tdinfo->skb_dma[0] = dma_map_single(vptr->dev, skb->data, pktlen,
+                                                               DMA_TO_DEVICE);
        td_ptr->tdesc0.len = cpu_to_le16(pktlen);
        td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
        td_ptr->td_buf[0].pa_high = 0;
@@ -2560,7 +2580,7 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
-               tdinfo->skb_dma[i + 1] = skb_frag_dma_map(&vptr->pdev->dev,
+               tdinfo->skb_dma[i + 1] = skb_frag_dma_map(vptr->dev,
                                                          frag, 0,
                                                          skb_frag_size(frag),
                                                          DMA_TO_DEVICE);
@@ -2632,12 +2652,9 @@ static const struct net_device_ops velocity_netdev_ops = {
  *     Set up the initial velocity_info struct for the device that has been
  *     discovered.
  */
-static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr,
-                              const struct velocity_info_tbl *info)
+static void velocity_init_info(struct velocity_info *vptr,
+                               const struct velocity_info_tbl *info)
 {
-       memset(vptr, 0, sizeof(struct velocity_info));
-
-       vptr->pdev = pdev;
        vptr->chip_id = info->chip_id;
        vptr->tx.numq = info->txqueue;
        vptr->multicast_limit = MCAM_SIZE;
@@ -2652,10 +2669,9 @@ static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr,
  *     Retrieve the PCI configuration space data that interests us from
  *     the kernel PCI layer
  */
-static int velocity_get_pci_info(struct velocity_info *vptr,
-                                struct pci_dev *pdev)
+static int velocity_get_pci_info(struct velocity_info *vptr)
 {
-       vptr->rev_id = pdev->revision;
+       struct pci_dev *pdev = vptr->pdev;
 
        pci_set_master(pdev);
 
@@ -2678,7 +2694,37 @@ static int velocity_get_pci_info(struct velocity_info *vptr,
                dev_err(&pdev->dev, "region #1 is too small.\n");
                return -EINVAL;
        }
-       vptr->pdev = pdev;
+
+       return 0;
+}
+
+/**
+ *     velocity_get_platform_info - retrieve platform info for device
+ *     @vptr: velocity device
+ *     @pdev: platform device it matches
+ *
+ *     Retrieve the Platform configuration data that interests us
+ */
+static int velocity_get_platform_info(struct velocity_info *vptr)
+{
+       struct resource res;
+       int ret;
+
+       if (of_get_property(vptr->dev->of_node, "no-eeprom", NULL))
+               vptr->no_eeprom = 1;
+
+       ret = of_address_to_resource(vptr->dev->of_node, 0, &res);
+       if (ret) {
+               dev_err(vptr->dev, "unable to find memory address\n");
+               return ret;
+       }
+
+       vptr->memaddr = res.start;
+
+       if (resource_size(&res) < VELOCITY_IO_SIZE) {
+               dev_err(vptr->dev, "memory region is too small.\n");
+               return -EINVAL;
+       }
 
        return 0;
 }
@@ -2692,7 +2738,7 @@ static int velocity_get_pci_info(struct velocity_info *vptr,
  */
 static void velocity_print_info(struct velocity_info *vptr)
 {
-       struct net_device *dev = vptr->dev;
+       struct net_device *dev = vptr->netdev;
 
        printk(KERN_INFO "%s: %s\n", dev->name, get_chip_name(vptr->chip_id));
        printk(KERN_INFO "%s: Ethernet Address: %pM\n",
@@ -2707,21 +2753,22 @@ static u32 velocity_get_link(struct net_device *dev)
 }
 
 /**
- *     velocity_found1         -       set up discovered velocity card
+ *     velocity_probe - set up discovered velocity device
  *     @pdev: PCI device
  *     @ent: PCI device table entry that matched
+ *     @bustype: bus that device is connected to
  *
  *     Configure a discovered adapter from scratch. Return a negative
  *     errno error code on failure paths.
  */
-static int velocity_found1(struct pci_dev *pdev,
-                          const struct pci_device_id *ent)
+static int velocity_probe(struct device *dev, int irq,
+                          const struct velocity_info_tbl *info,
+                          enum velocity_bus_type bustype)
 {
        static int first = 1;
-       struct net_device *dev;
+       struct net_device *netdev;
        int i;
        const char *drv_string;
-       const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data];
        struct velocity_info *vptr;
        struct mac_regs __iomem *regs;
        int ret = -ENOMEM;
@@ -2730,20 +2777,18 @@ static int velocity_found1(struct pci_dev *pdev,
         * can support more than MAX_UNITS.
         */
        if (velocity_nics >= MAX_UNITS) {
-               dev_notice(&pdev->dev, "already found %d NICs.\n",
-                          velocity_nics);
+               dev_notice(dev, "already found %d NICs.\n", velocity_nics);
                return -ENODEV;
        }
 
-       dev = alloc_etherdev(sizeof(struct velocity_info));
-       if (!dev)
+       netdev = alloc_etherdev(sizeof(struct velocity_info));
+       if (!netdev)
                goto out;
 
        /* Chain it all together */
 
-       SET_NETDEV_DEV(dev, &pdev->dev);
-       vptr = netdev_priv(dev);
-
+       SET_NETDEV_DEV(netdev, dev);
+       vptr = netdev_priv(netdev);
 
        if (first) {
                printk(KERN_INFO "%s Ver. %s\n",
@@ -2753,41 +2798,41 @@ static int velocity_found1(struct pci_dev *pdev,
                first = 0;
        }
 
-       velocity_init_info(pdev, vptr, info);
-
+       netdev->irq = irq;
+       vptr->netdev = netdev;
        vptr->dev = dev;
 
-       ret = pci_enable_device(pdev);
-       if (ret < 0)
-               goto err_free_dev;
+       velocity_init_info(vptr, info);
 
-       ret = velocity_get_pci_info(vptr, pdev);
-       if (ret < 0) {
-               /* error message already printed */
-               goto err_disable;
-       }
+       if (bustype == BUS_PCI) {
+               vptr->pdev = to_pci_dev(dev);
 
-       ret = pci_request_regions(pdev, VELOCITY_NAME);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "No PCI resources.\n");
-               goto err_disable;
+               ret = velocity_get_pci_info(vptr);
+               if (ret < 0)
+                       goto err_free_dev;
+       } else {
+               vptr->pdev = NULL;
+               ret = velocity_get_platform_info(vptr);
+               if (ret < 0)
+                       goto err_free_dev;
        }
 
        regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);
        if (regs == NULL) {
                ret = -EIO;
-               goto err_release_res;
+               goto err_free_dev;
        }
 
        vptr->mac_regs = regs;
+       vptr->rev_id = readb(&regs->rev_id);
 
        mac_wol_reset(regs);
 
        for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = readb(&regs->PAR[i]);
+               netdev->dev_addr[i] = readb(&regs->PAR[i]);
 
 
-       drv_string = dev_driver_string(&pdev->dev);
+       drv_string = dev_driver_string(dev);
 
        velocity_get_options(&vptr->options, velocity_nics, drv_string);
 
@@ -2808,46 +2853,125 @@ static int velocity_found1(struct pci_dev *pdev,
 
        vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
 
-       dev->netdev_ops = &velocity_netdev_ops;
-       dev->ethtool_ops = &velocity_ethtool_ops;
-       netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT);
+       netdev->netdev_ops = &velocity_netdev_ops;
+       netdev->ethtool_ops = &velocity_ethtool_ops;
+       netif_napi_add(netdev, &vptr->napi, velocity_poll,
+                                                       VELOCITY_NAPI_WEIGHT);
 
-       dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
+       netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
                           NETIF_F_HW_VLAN_CTAG_TX;
-       dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_FILTER |
-                        NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_IP_CSUM;
+       netdev->features |= NETIF_F_HW_VLAN_CTAG_TX |
+                       NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX |
+                       NETIF_F_IP_CSUM;
 
-       ret = register_netdev(dev);
+       ret = register_netdev(netdev);
        if (ret < 0)
                goto err_iounmap;
 
-       if (!velocity_get_link(dev)) {
-               netif_carrier_off(dev);
+       if (!velocity_get_link(netdev)) {
+               netif_carrier_off(netdev);
                vptr->mii_status |= VELOCITY_LINK_FAIL;
        }
 
        velocity_print_info(vptr);
-       pci_set_drvdata(pdev, dev);
+       dev_set_drvdata(vptr->dev, netdev);
 
        /* and leave the chip powered down */
 
-       pci_set_power_state(pdev, PCI_D3hot);
+       velocity_set_power_state(vptr, PCI_D3hot);
        velocity_nics++;
 out:
        return ret;
 
 err_iounmap:
        iounmap(regs);
-err_release_res:
-       pci_release_regions(pdev);
-err_disable:
-       pci_disable_device(pdev);
 err_free_dev:
-       free_netdev(dev);
+       free_netdev(netdev);
        goto out;
 }
 
-#ifdef CONFIG_PM
+/**
+ *     velocity_remove - device unplug
+ *     @dev: device being removed
+ *
+ *     Device unload callback. Called on an unplug or on module
+ *     unload for each active device that is present. Disconnects
+ *     the device from the network layer and frees all the resources
+ */
+static int velocity_remove(struct device *dev)
+{
+       struct net_device *netdev = dev_get_drvdata(dev);
+       struct velocity_info *vptr = netdev_priv(netdev);
+
+       unregister_netdev(netdev);
+       iounmap(vptr->mac_regs);
+       free_netdev(netdev);
+       velocity_nics--;
+
+       return 0;
+}
+
+static int velocity_pci_probe(struct pci_dev *pdev,
+                              const struct pci_device_id *ent)
+{
+       const struct velocity_info_tbl *info =
+                                       &chip_info_table[ent->driver_data];
+       int ret;
+
+       ret = pci_enable_device(pdev);
+       if (ret < 0)
+               return ret;
+
+       ret = pci_request_regions(pdev, VELOCITY_NAME);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "No PCI resources.\n");
+               goto fail1;
+       }
+
+       ret = velocity_probe(&pdev->dev, pdev->irq, info, BUS_PCI);
+       if (ret == 0)
+               return 0;
+
+       pci_release_regions(pdev);
+fail1:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void velocity_pci_remove(struct pci_dev *pdev)
+{
+       velocity_remove(&pdev->dev);
+
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+}
+
+static int velocity_platform_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id;
+       const struct velocity_info_tbl *info;
+       int irq;
+
+       of_id = of_match_device(velocity_of_ids, &pdev->dev);
+       if (!of_id)
+               return -EINVAL;
+       info = of_id->data;
+
+       irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+       if (!irq)
+               return -EINVAL;
+
+       return velocity_probe(&pdev->dev, irq, info, BUS_PLATFORM);
+}
+
+static int velocity_platform_remove(struct platform_device *pdev)
+{
+       velocity_remove(&pdev->dev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
 /**
  *     wol_calc_crc            -       WOL CRC
  *     @pattern: data pattern
@@ -3004,32 +3128,35 @@ static void velocity_save_context(struct velocity_info *vptr, struct velocity_co
 
 }
 
-static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
+static int velocity_suspend(struct device *dev)
 {
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct velocity_info *vptr = netdev_priv(dev);
+       struct net_device *netdev = dev_get_drvdata(dev);
+       struct velocity_info *vptr = netdev_priv(netdev);
        unsigned long flags;
 
-       if (!netif_running(vptr->dev))
+       if (!netif_running(vptr->netdev))
                return 0;
 
-       netif_device_detach(vptr->dev);
+       netif_device_detach(vptr->netdev);
 
        spin_lock_irqsave(&vptr->lock, flags);
-       pci_save_state(pdev);
+       if (vptr->pdev)
+               pci_save_state(vptr->pdev);
 
        if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
                velocity_get_ip(vptr);
                velocity_save_context(vptr, &vptr->context);
                velocity_shutdown(vptr);
                velocity_set_wol(vptr);
-               pci_enable_wake(pdev, PCI_D3hot, 1);
-               pci_set_power_state(pdev, PCI_D3hot);
+               if (vptr->pdev)
+                       pci_enable_wake(vptr->pdev, PCI_D3hot, 1);
+               velocity_set_power_state(vptr, PCI_D3hot);
        } else {
                velocity_save_context(vptr, &vptr->context);
                velocity_shutdown(vptr);
-               pci_disable_device(pdev);
-               pci_set_power_state(pdev, pci_choose_state(pdev, state));
+               if (vptr->pdev)
+                       pci_disable_device(vptr->pdev);
+               velocity_set_power_state(vptr, PCI_D3hot);
        }
 
        spin_unlock_irqrestore(&vptr->lock, flags);
@@ -3071,19 +3198,22 @@ static void velocity_restore_context(struct velocity_info *vptr, struct velocity
                writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
 }
 
-static int velocity_resume(struct pci_dev *pdev)
+static int velocity_resume(struct device *dev)
 {
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct velocity_info *vptr = netdev_priv(dev);
+       struct net_device *netdev = dev_get_drvdata(dev);
+       struct velocity_info *vptr = netdev_priv(netdev);
        unsigned long flags;
        int i;
 
-       if (!netif_running(vptr->dev))
+       if (!netif_running(vptr->netdev))
                return 0;
 
-       pci_set_power_state(pdev, PCI_D0);
-       pci_enable_wake(pdev, 0, 0);
-       pci_restore_state(pdev);
+       velocity_set_power_state(vptr, PCI_D0);
+
+       if (vptr->pdev) {
+               pci_enable_wake(vptr->pdev, 0, 0);
+               pci_restore_state(vptr->pdev);
+       }
 
        mac_wol_reset(vptr->mac_regs);
 
@@ -3101,27 +3231,38 @@ static int velocity_resume(struct pci_dev *pdev)
 
        mac_enable_int(vptr->mac_regs);
        spin_unlock_irqrestore(&vptr->lock, flags);
-       netif_device_attach(vptr->dev);
+       netif_device_attach(vptr->netdev);
 
        return 0;
 }
-#endif
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(velocity_pm_ops, velocity_suspend, velocity_resume);
 
 /*
  *     Definition for our device driver. The PCI layer interface
  *     uses this to handle all our card discover and plugging
  */
-static struct pci_driver velocity_driver = {
+static struct pci_driver velocity_pci_driver = {
        .name           = VELOCITY_NAME,
-       .id_table       = velocity_id_table,
-       .probe          = velocity_found1,
-       .remove         = velocity_remove1,
-#ifdef CONFIG_PM
-       .suspend        = velocity_suspend,
-       .resume         = velocity_resume,
-#endif
+       .id_table       = velocity_pci_id_table,
+       .probe          = velocity_pci_probe,
+       .remove         = velocity_pci_remove,
+       .driver = {
+               .pm = &velocity_pm_ops,
+       },
 };
 
+static struct platform_driver velocity_platform_driver = {
+       .probe          = velocity_platform_probe,
+       .remove         = velocity_platform_remove,
+       .driver = {
+               .name = "via-velocity",
+               .owner = THIS_MODULE,
+               .of_match_table = velocity_of_ids,
+               .pm = &velocity_pm_ops,
+       },
+};
 
 /**
  *     velocity_ethtool_up     -       pre hook for ethtool
@@ -3134,7 +3275,7 @@ static int velocity_ethtool_up(struct net_device *dev)
 {
        struct velocity_info *vptr = netdev_priv(dev);
        if (!netif_running(dev))
-               pci_set_power_state(vptr->pdev, PCI_D0);
+               velocity_set_power_state(vptr, PCI_D0);
        return 0;
 }
 
@@ -3149,7 +3290,7 @@ static void velocity_ethtool_down(struct net_device *dev)
 {
        struct velocity_info *vptr = netdev_priv(dev);
        if (!netif_running(dev))
-               pci_set_power_state(vptr->pdev, PCI_D3hot);
+               velocity_set_power_state(vptr, PCI_D3hot);
 }
 
 static int velocity_get_settings(struct net_device *dev,
@@ -3269,9 +3410,14 @@ static int velocity_set_settings(struct net_device *dev,
 static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct velocity_info *vptr = netdev_priv(dev);
+
        strlcpy(info->driver, VELOCITY_NAME, sizeof(info->driver));
        strlcpy(info->version, VELOCITY_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(vptr->pdev), sizeof(info->bus_info));
+       if (vptr->pdev)
+               strlcpy(info->bus_info, pci_name(vptr->pdev),
+                                               sizeof(info->bus_info));
+       else
+               strlcpy(info->bus_info, "platform", sizeof(info->bus_info));
 }
 
 static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -3561,13 +3707,20 @@ static void velocity_unregister_notifier(void)
  */
 static int __init velocity_init_module(void)
 {
-       int ret;
+       int ret_pci, ret_platform;
 
        velocity_register_notifier();
-       ret = pci_register_driver(&velocity_driver);
-       if (ret < 0)
+
+       ret_pci = pci_register_driver(&velocity_pci_driver);
+       ret_platform = platform_driver_register(&velocity_platform_driver);
+
+       /* if both_registers failed, remove the notifier */
+       if ((ret_pci < 0) && (ret_platform < 0)) {
                velocity_unregister_notifier();
-       return ret;
+               return ret_pci;
+       }
+
+       return 0;
 }
 
 /**
@@ -3581,7 +3734,9 @@ static int __init velocity_init_module(void)
 static void __exit velocity_cleanup_module(void)
 {
        velocity_unregister_notifier();
-       pci_unregister_driver(&velocity_driver);
+
+       pci_unregister_driver(&velocity_pci_driver);
+       platform_driver_unregister(&velocity_platform_driver);
 }
 
 module_init(velocity_init_module);
index 4cb9f13485e957c2a510976841ac07023e774457..9453bfa9324a54fd41c86cabf3ca95c3536ed790 100644 (file)
@@ -1265,7 +1265,7 @@ struct velocity_context {
 #define PHYID_VT3216_64BIT  0x000FC600UL
 #define PHYID_MARVELL_1000  0x01410C50UL
 #define PHYID_MARVELL_1000S 0x01410C40UL
-
+#define PHYID_ICPLUS_IP101A 0x02430C54UL
 #define PHYID_REV_ID_MASK   0x0000000FUL
 
 #define PHYID_GET_PHY_ID(i)         ((i) & ~PHYID_REV_ID_MASK)
@@ -1434,8 +1434,10 @@ struct velocity_opt {
 #define GET_RD_BY_IDX(vptr, idx)   (vptr->rd_ring[idx])
 
 struct velocity_info {
+       struct device *dev;
        struct pci_dev *pdev;
-       struct net_device *dev;
+       struct net_device *netdev;
+       int no_eeprom;
 
        unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
        u8 ip_addr[4];
@@ -1514,7 +1516,7 @@ static inline int velocity_get_ip(struct velocity_info *vptr)
        int res = -ENOENT;
 
        rcu_read_lock();
-       in_dev = __in_dev_get_rcu(vptr->dev);
+       in_dev = __in_dev_get_rcu(vptr->netdev);
        if (in_dev != NULL) {
                ifa = (struct in_ifaddr *) in_dev->ifa_list;
                if (ifa != NULL) {
index a518dcab396e69cdbd96b8133bef82e237c5daf3..30fed08d1674377bf5b51d6461ef0b13b229cfff 100644 (file)
@@ -734,7 +734,6 @@ err_hw_probe:
        unregister_netdev(ndev);
 err_register:
        free_netdev(ndev);
-       platform_set_drvdata(pdev, NULL);
        return err;
 }
 
@@ -750,7 +749,6 @@ static int w5100_remove(struct platform_device *pdev)
 
        unregister_netdev(ndev);
        free_netdev(ndev);
-       platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
index 6e00e3f94ce4e4909d9b624b710f888039f68ded..e92884564e1e97c43c0a95769b8db950e244bfe5 100644 (file)
@@ -646,7 +646,6 @@ err_hw_probe:
        unregister_netdev(ndev);
 err_register:
        free_netdev(ndev);
-       platform_set_drvdata(pdev, NULL);
        return err;
 }
 
@@ -662,7 +661,6 @@ static int w5300_remove(struct platform_device *pdev)
 
        unregister_netdev(ndev);
        free_netdev(ndev);
-       platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
index 122d60c0481b0d8eab2a95b56bc495665390a0ec..7b90a5eba0995326ce6d808749c65aa6f77cf8e7 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_XILINX
        bool "Xilinx devices"
        default y
-       depends on PPC || PPC32 || MICROBLAZE
+       depends on PPC || PPC32 || MICROBLAZE || ARCH_ZYNQ
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
@@ -20,7 +20,7 @@ if NET_VENDOR_XILINX
 
 config XILINX_EMACLITE
        tristate "Xilinx 10/100 Ethernet Lite support"
-       depends on (PPC32 || MICROBLAZE)
+       depends on (PPC32 || MICROBLAZE || ARCH_ZYNQ)
        select PHYLIB
        ---help---
          This driver supports the 10/100 Ethernet Lite from Xilinx.
index 57c2e5ef2804ec5a89841557bb4e867c11cde5ec..58eb4488beff13201c411f5374f803cc730c7c8c 100644 (file)
@@ -1007,7 +1007,7 @@ static int temac_of_probe(struct platform_device *op)
                return -ENOMEM;
 
        ether_setup(ndev);
-       dev_set_drvdata(&op->dev, ndev);
+       platform_set_drvdata(op, ndev);
        SET_NETDEV_DEV(ndev, &op->dev);
        ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
        ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
@@ -1136,7 +1136,7 @@ static int temac_of_probe(struct platform_device *op)
 
 static int temac_of_remove(struct platform_device *op)
 {
-       struct net_device *ndev = dev_get_drvdata(&op->dev);
+       struct net_device *ndev = platform_get_drvdata(op);
        struct temac_local *lp = netdev_priv(ndev);
 
        temac_mdio_teardown(lp);
@@ -1145,7 +1145,6 @@ static int temac_of_remove(struct platform_device *op)
        if (lp->phy_node)
                of_node_put(lp->phy_node);
        lp->phy_node = NULL;
-       dev_set_drvdata(&op->dev, NULL);
        iounmap(lp->regs);
        if (lp->sdma_regs)
                iounmap(lp->sdma_regs);
index 24748e8367a1ad346a245bc890eb27bc8b659b0a..fb7d1c28a2ea345326c2b225915ca2676295a308 100644 (file)
@@ -1484,7 +1484,7 @@ static int axienet_of_probe(struct platform_device *op)
                return -ENOMEM;
 
        ether_setup(ndev);
-       dev_set_drvdata(&op->dev, ndev);
+       platform_set_drvdata(op, ndev);
 
        SET_NETDEV_DEV(ndev, &op->dev);
        ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
@@ -1622,7 +1622,7 @@ nodev:
 
 static int axienet_of_remove(struct platform_device *op)
 {
-       struct net_device *ndev = dev_get_drvdata(&op->dev);
+       struct net_device *ndev = platform_get_drvdata(op);
        struct axienet_local *lp = netdev_priv(ndev);
 
        axienet_mdio_teardown(lp);
@@ -1632,8 +1632,6 @@ static int axienet_of_remove(struct platform_device *op)
                of_node_put(lp->phy_node);
        lp->phy_node = NULL;
 
-       dev_set_drvdata(&op->dev, NULL);
-
        iounmap(lp->regs);
        if (lp->dma_regs)
                iounmap(lp->dma_regs);
index b7268b3dae777a1fc29b5aed36f19ec96df462aa..1cd131bde680bea02152fa14146bda981d3dd0e5 100644 (file)
@@ -2,9 +2,9 @@
  * Xilinx EmacLite Linux driver for the Xilinx Ethernet MAC Lite device.
  *
  * This is a new flat driver which is based on the original emac_lite
- * driver from John Williams <john.williams@petalogix.com>.
+ * driver from John Williams <john.williams@xilinx.com>.
  *
- * 2007-2009 (c) Xilinx, Inc.
+ * 2007 - 2013 (c) Xilinx, Inc.
  *
  * 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
@@ -159,34 +159,32 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
        u32 reg_data;
 
        /* Enable the Tx interrupts for the first Buffer */
-       reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET);
-       out_be32(drvdata->base_addr + XEL_TSR_OFFSET,
-                reg_data | XEL_TSR_XMIT_IE_MASK);
+       reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+       __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
+                    drvdata->base_addr + XEL_TSR_OFFSET);
 
        /* Enable the Tx interrupts for the second Buffer if
         * configured in HW */
        if (drvdata->tx_ping_pong != 0) {
-               reg_data = in_be32(drvdata->base_addr +
+               reg_data = __raw_readl(drvdata->base_addr +
                                   XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
-               out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                        XEL_TSR_OFFSET,
-                        reg_data | XEL_TSR_XMIT_IE_MASK);
+               __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
+                            drvdata->base_addr + XEL_BUFFER_OFFSET +
+                            XEL_TSR_OFFSET);
        }
 
        /* Enable the Rx interrupts for the first buffer */
-       out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
-                XEL_RSR_RECV_IE_MASK);
+       __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
 
        /* Enable the Rx interrupts for the second Buffer if
         * configured in HW */
        if (drvdata->rx_ping_pong != 0) {
-               out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                        XEL_RSR_OFFSET,
-                        XEL_RSR_RECV_IE_MASK);
+               __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr +
+                            XEL_BUFFER_OFFSET + XEL_RSR_OFFSET);
        }
 
        /* Enable the Global Interrupt Enable */
-       out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK);
+       __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
 }
 
 /**
@@ -201,37 +199,37 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata)
        u32 reg_data;
 
        /* Disable the Global Interrupt Enable */
-       out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK);
+       __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
 
        /* Disable the Tx interrupts for the first buffer */
-       reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET);
-       out_be32(drvdata->base_addr + XEL_TSR_OFFSET,
-                reg_data & (~XEL_TSR_XMIT_IE_MASK));
+       reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+       __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
+                    drvdata->base_addr + XEL_TSR_OFFSET);
 
        /* Disable the Tx interrupts for the second Buffer
         * if configured in HW */
        if (drvdata->tx_ping_pong != 0) {
-               reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
+               reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
                                   XEL_TSR_OFFSET);
-               out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                        XEL_TSR_OFFSET,
-                        reg_data & (~XEL_TSR_XMIT_IE_MASK));
+               __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
+                            drvdata->base_addr + XEL_BUFFER_OFFSET +
+                            XEL_TSR_OFFSET);
        }
 
        /* Disable the Rx interrupts for the first buffer */
-       reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET);
-       out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
-                reg_data & (~XEL_RSR_RECV_IE_MASK));
+       reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
+       __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
+                    drvdata->base_addr + XEL_RSR_OFFSET);
 
        /* Disable the Rx interrupts for the second buffer
         * if configured in HW */
        if (drvdata->rx_ping_pong != 0) {
 
-               reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
+               reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
                                   XEL_RSR_OFFSET);
-               out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                        XEL_RSR_OFFSET,
-                        reg_data & (~XEL_RSR_RECV_IE_MASK));
+               __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
+                            drvdata->base_addr + XEL_BUFFER_OFFSET +
+                            XEL_RSR_OFFSET);
        }
 }
 
@@ -351,7 +349,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
                byte_count = ETH_FRAME_LEN;
 
        /* Check if the expected buffer is available */
-       reg_data = in_be32(addr + XEL_TSR_OFFSET);
+       reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
        if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
             XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
 
@@ -364,7 +362,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
 
                addr = (void __iomem __force *)((u32 __force)addr ^
                                                 XEL_BUFFER_OFFSET);
-               reg_data = in_be32(addr + XEL_TSR_OFFSET);
+               reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
 
                if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
                     XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
@@ -375,15 +373,16 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
        /* Write the frame to the buffer */
        xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
 
-       out_be32(addr + XEL_TPLR_OFFSET, (byte_count & XEL_TPLR_LENGTH_MASK));
+       __raw_writel((byte_count & XEL_TPLR_LENGTH_MASK),
+                    addr + XEL_TPLR_OFFSET);
 
        /* Update the Tx Status Register to indicate that there is a
         * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
         * is used by the interrupt handler to check whether a frame
         * has been transmitted */
-       reg_data = in_be32(addr + XEL_TSR_OFFSET);
+       reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
        reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
-       out_be32(addr + XEL_TSR_OFFSET, reg_data);
+       __raw_writel(reg_data, addr + XEL_TSR_OFFSET);
 
        return 0;
 }
@@ -408,7 +407,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
        addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use);
 
        /* Verify which buffer has valid data */
-       reg_data = in_be32(addr + XEL_RSR_OFFSET);
+       reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
 
        if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
                if (drvdata->rx_ping_pong != 0)
@@ -425,14 +424,14 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
                        return 0;       /* No data was available */
 
                /* Verify that buffer has valid data */
-               reg_data = in_be32(addr + XEL_RSR_OFFSET);
+               reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
                if ((reg_data & XEL_RSR_RECV_DONE_MASK) !=
                     XEL_RSR_RECV_DONE_MASK)
                        return 0;       /* No data was available */
        }
 
        /* Get the protocol type of the ethernet frame that arrived */
-       proto_type = ((ntohl(in_be32(addr + XEL_HEADER_OFFSET +
+       proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET +
                        XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
                        XEL_RPLR_LENGTH_MASK);
 
@@ -441,7 +440,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
        if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
 
                if (proto_type == ETH_P_IP) {
-                       length = ((ntohl(in_be32(addr +
+                       length = ((ntohl(__raw_readl(addr +
                                        XEL_HEADER_IP_LENGTH_OFFSET +
                                        XEL_RXBUFF_OFFSET)) >>
                                        XEL_HEADER_SHIFT) &
@@ -463,9 +462,9 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
                                data, length);
 
        /* Acknowledge the frame */
-       reg_data = in_be32(addr + XEL_RSR_OFFSET);
+       reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
        reg_data &= ~XEL_RSR_RECV_DONE_MASK;
-       out_be32(addr + XEL_RSR_OFFSET, reg_data);
+       __raw_writel(reg_data, addr + XEL_RSR_OFFSET);
 
        return length;
 }
@@ -492,14 +491,14 @@ static void xemaclite_update_address(struct net_local *drvdata,
 
        xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
 
-       out_be32(addr + XEL_TPLR_OFFSET, ETH_ALEN);
+       __raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
 
        /* Update the MAC address in the EmacLite */
-       reg_data = in_be32(addr + XEL_TSR_OFFSET);
-       out_be32(addr + XEL_TSR_OFFSET, reg_data | XEL_TSR_PROG_MAC_ADDR);
+       reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+       __raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
 
        /* Wait for EmacLite to finish with the MAC address update */
-       while ((in_be32(addr + XEL_TSR_OFFSET) &
+       while ((__raw_readl(addr + XEL_TSR_OFFSET) &
                XEL_TSR_PROG_MAC_ADDR) != 0)
                ;
 }
@@ -669,31 +668,32 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
        u32 tx_status;
 
        /* Check if there is Rx Data available */
-       if ((in_be32(base_addr + XEL_RSR_OFFSET) & XEL_RSR_RECV_DONE_MASK) ||
-                       (in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
+       if ((__raw_readl(base_addr + XEL_RSR_OFFSET) &
+                        XEL_RSR_RECV_DONE_MASK) ||
+           (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
                         & XEL_RSR_RECV_DONE_MASK))
 
                xemaclite_rx_handler(dev);
 
        /* Check if the Transmission for the first buffer is completed */
-       tx_status = in_be32(base_addr + XEL_TSR_OFFSET);
+       tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET);
        if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
                (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
 
                tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
-               out_be32(base_addr + XEL_TSR_OFFSET, tx_status);
+               __raw_writel(tx_status, base_addr + XEL_TSR_OFFSET);
 
                tx_complete = true;
        }
 
        /* Check if the Transmission for the second buffer is completed */
-       tx_status = in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+       tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
        if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
                (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
 
                tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
-               out_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET,
-                        tx_status);
+               __raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
+                            XEL_TSR_OFFSET);
 
                tx_complete = true;
        }
@@ -726,7 +726,7 @@ static int xemaclite_mdio_wait(struct net_local *lp)
        /* wait for the MDIO interface to not be busy or timeout
           after some time.
        */
-       while (in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
+       while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
                        XEL_MDIOCTRL_MDIOSTS_MASK) {
                if (end - jiffies <= 0) {
                        WARN_ON(1);
@@ -762,17 +762,17 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg)
         * MDIO Address register. Set the Status bit in the MDIO Control
         * register to start a MDIO read transaction.
         */
-       ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
-       out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
-                XEL_MDIOADDR_OP_MASK |
-                ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
-       out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
-                ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
+       ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       __raw_writel(XEL_MDIOADDR_OP_MASK |
+                    ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+                    lp->base_addr + XEL_MDIOADDR_OFFSET);
+       __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+                    lp->base_addr + XEL_MDIOCTRL_OFFSET);
 
        if (xemaclite_mdio_wait(lp))
                return -ETIMEDOUT;
 
-       rc = in_be32(lp->base_addr + XEL_MDIORD_OFFSET);
+       rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET);
 
        dev_dbg(&lp->ndev->dev,
                "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
@@ -809,13 +809,13 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
         * Data register. Finally, set the Status bit in the MDIO Control
         * register to start a MDIO write transaction.
         */
-       ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
-       out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
-                ~XEL_MDIOADDR_OP_MASK &
-                ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
-       out_be32(lp->base_addr + XEL_MDIOWR_OFFSET, val);
-       out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
-                ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
+       ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       __raw_writel(~XEL_MDIOADDR_OP_MASK &
+                    ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+                    lp->base_addr + XEL_MDIOADDR_OFFSET);
+       __raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
+       __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+                    lp->base_addr + XEL_MDIOCTRL_OFFSET);
 
        return 0;
 }
@@ -848,24 +848,39 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
        int rc;
        struct resource res;
        struct device_node *np = of_get_parent(lp->phy_node);
+       struct device_node *npp;
 
        /* Don't register the MDIO bus if the phy_node or its parent node
         * can't be found.
         */
-       if (!np)
+       if (!np) {
+               dev_err(dev, "Failed to register mdio bus.\n");
                return -ENODEV;
+       }
+       npp = of_get_parent(np);
+
+       of_address_to_resource(npp, 0, &res);
+       if (lp->ndev->mem_start != res.start) {
+               struct phy_device *phydev;
+               phydev = of_phy_find_device(lp->phy_node);
+               if (!phydev)
+                       dev_info(dev,
+                                "MDIO of the phy is not registered yet\n");
+               return 0;
+       }
 
        /* Enable the MDIO bus by asserting the enable bit in MDIO Control
         * register.
         */
-       out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
-                XEL_MDIOCTRL_MDIOEN_MASK);
+       __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK,
+                    lp->base_addr + XEL_MDIOCTRL_OFFSET);
 
        bus = mdiobus_alloc();
-       if (!bus)
+       if (!bus) {
+               dev_err(dev, "Failed to allocate mdiobus\n");
                return -ENOMEM;
+       }
 
-       of_address_to_resource(np, 0, &res);
        snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
                 (unsigned long long)res.start);
        bus->priv = lp;
@@ -879,8 +894,10 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
        lp->mii_bus = bus;
 
        rc = of_mdiobus_register(bus, np);
-       if (rc)
+       if (rc) {
+               dev_err(dev, "Failed to register mdio bus.\n");
                goto err_register;
+       }
 
        return 0;
 
@@ -896,7 +913,7 @@ err_register:
  * There's nothing in the Emaclite device to be configured when the link
  * state changes. We just print the status.
  */
-void xemaclite_adjust_link(struct net_device *ndev)
+static void xemaclite_adjust_link(struct net_device *ndev)
 {
        struct net_local *lp = netdev_priv(ndev);
        struct phy_device *phy = lp->phy_dev;
@@ -1058,13 +1075,14 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev)
  * This function un maps the IO region of the Emaclite device and frees the net
  * device.
  */
-static void xemaclite_remove_ndev(struct net_device *ndev)
+static void xemaclite_remove_ndev(struct net_device *ndev,
+                                 struct platform_device *pdev)
 {
        if (ndev) {
                struct net_local *lp = netdev_priv(ndev);
 
                if (lp->base_addr)
-                       iounmap((void __iomem __force *) (lp->base_addr));
+                       devm_iounmap(&pdev->dev, lp->base_addr);
                free_netdev(ndev);
        }
 }
@@ -1110,8 +1128,7 @@ static struct net_device_ops xemaclite_netdev_ops;
  */
 static int xemaclite_of_probe(struct platform_device *ofdev)
 {
-       struct resource r_irq; /* Interrupt resources */
-       struct resource r_mem; /* IO mem resources */
+       struct resource *res;
        struct net_device *ndev = NULL;
        struct net_local *lp = NULL;
        struct device *dev = &ofdev->dev;
@@ -1121,20 +1138,6 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
 
        dev_info(dev, "Device Tree Probing\n");
 
-       /* Get iospace for the device */
-       rc = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem);
-       if (rc) {
-               dev_err(dev, "invalid address\n");
-               return rc;
-       }
-
-       /* Get IRQ for the device */
-       rc = of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq);
-       if (!rc) {
-               dev_err(dev, "no IRQ found\n");
-               return rc;
-       }
-
        /* Create an ethernet device instance */
        ndev = alloc_etherdev(sizeof(struct net_local));
        if (!ndev)
@@ -1143,29 +1146,25 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
        dev_set_drvdata(dev, ndev);
        SET_NETDEV_DEV(ndev, &ofdev->dev);
 
-       ndev->irq = r_irq.start;
-       ndev->mem_start = r_mem.start;
-       ndev->mem_end = r_mem.end;
-
        lp = netdev_priv(ndev);
        lp->ndev = ndev;
 
-       if (!request_mem_region(ndev->mem_start,
-                               ndev->mem_end - ndev->mem_start + 1,
-                               DRIVER_NAME)) {
-               dev_err(dev, "Couldn't lock memory region at %p\n",
-                       (void *)ndev->mem_start);
-               rc = -EBUSY;
-               goto error2;
+       /* Get IRQ for the device */
+       res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(dev, "no IRQ found\n");
+               goto error;
        }
 
-       /* Get the virtual base address for the device */
-       lp->base_addr = ioremap(r_mem.start, resource_size(&r_mem));
-       if (NULL == lp->base_addr) {
-               dev_err(dev, "EmacLite: Could not allocate iomem\n");
-               rc = -EIO;
-               goto error1;
-       }
+       ndev->irq = res->start;
+
+       res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+       lp->base_addr = devm_request_and_ioremap(&ofdev->dev, res);
+       if (!lp->base_addr)
+               goto error;
+
+       ndev->mem_start = res->start;
+       ndev->mem_end = res->end;
 
        spin_lock_init(&lp->reset_lock);
        lp->next_tx_buf_to_use = 0x0;
@@ -1181,8 +1180,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
                dev_warn(dev, "No MAC address found\n");
 
        /* Clear the Tx CSR's in case this is a restart */
-       out_be32(lp->base_addr + XEL_TSR_OFFSET, 0);
-       out_be32(lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0);
+       __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET);
+       __raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
 
        /* Set the MAC address in the EmacLite device */
        xemaclite_update_address(lp, ndev->dev_addr);
@@ -1203,7 +1202,7 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
        if (rc) {
                dev_err(dev,
                        "Cannot register network device, aborting\n");
-               goto error1;
+               goto error;
        }
 
        dev_info(dev,
@@ -1212,11 +1211,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
                 (unsigned int __force)lp->base_addr, ndev->irq);
        return 0;
 
-error1:
-       release_mem_region(ndev->mem_start, resource_size(&r_mem));
-
-error2:
-       xemaclite_remove_ndev(ndev);
+error:
+       xemaclite_remove_ndev(ndev, ofdev);
        return rc;
 }
 
@@ -1251,9 +1247,7 @@ static int xemaclite_of_remove(struct platform_device *of_dev)
                of_node_put(lp->phy_node);
        lp->phy_node = NULL;
 
-       release_mem_region(ndev->mem_start, ndev->mem_end-ndev->mem_start + 1);
-
-       xemaclite_remove_ndev(ndev);
+       xemaclite_remove_ndev(ndev, of_dev);
        dev_set_drvdata(dev, NULL);
 
        return 0;
index 6958a5e87703bb3625b917bcdecfe8a7ef50e7e9..3d689fcb7917bd62e193fc1c8414d2a9075e0be5 100644 (file)
@@ -1472,7 +1472,6 @@ err_phy_dis:
        phy_disconnect(port->phydev);
 err_free_mem:
        npe_port_tab[NPE_ID(port->id)] = NULL;
-       platform_set_drvdata(pdev, NULL);
        release_resource(port->mem_res);
 err_npe_rel:
        npe_release(port->npe);
@@ -1489,7 +1488,6 @@ static int eth_remove_one(struct platform_device *pdev)
        unregister_netdev(dev);
        phy_disconnect(port->phydev);
        npe_port_tab[NPE_ID(port->id)] = NULL;
-       platform_set_drvdata(pdev, NULL);
        npe_release(port->npe);
        release_resource(port->mem_res);
        free_netdev(dev);
index d5bd563ac131e59362b7df5c33b25f5266f9370f..f5d7305a5784174f9868f045d186e9c90d2bbc20 100644 (file)
@@ -2246,15 +2246,4 @@ static struct pci_driver skfddi_pci_driver = {
        .remove         = skfp_remove_one,
 };
 
-static int __init skfd_init(void)
-{
-       return pci_register_driver(&skfddi_pci_driver);
-}
-
-static void __exit skfd_exit(void)
-{
-       pci_unregister_driver(&skfddi_pci_driver);
-}
-
-module_init(skfd_init);
-module_exit(skfd_exit);
+module_pci_driver(skfddi_pci_driver);
index 02de6c891670b87b9f19ef9a418b27ce39fa745c..f91bf0ddf031a077b89d961ca5cb16c87f8321ac 100644 (file)
@@ -103,7 +103,7 @@ static struct packet_type bpq_packet_type __read_mostly = {
 };
 
 static struct notifier_block bpq_dev_notifier = {
-       .notifier_call =bpq_device_event,
+       .notifier_call = bpq_device_event,
 };
 
 
@@ -544,9 +544,10 @@ static void bpq_free_device(struct net_device *ndev)
 /*
  *     Handle device status changes.
  */
-static int bpq_device_event(struct notifier_block *this,unsigned long event, void *ptr)
+static int bpq_device_event(struct notifier_block *this,
+                           unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (!net_eq(dev_net(dev), &init_net))
                return NOTIFY_DONE;
index 3c4d6274bb9b25527aa2af7e1daf4f07fe3a84d0..00ed75155ce8d4b7faff9ca9f3a98c28d355ff4c 100644 (file)
@@ -1686,15 +1686,4 @@ static struct pci_driver rr_driver = {
        .remove         = rr_remove_one,
 };
 
-static int __init rr_init_module(void)
-{
-       return pci_register_driver(&rr_driver);
-}
-
-static void __exit rr_cleanup_module(void)
-{
-       pci_unregister_driver(&rr_driver);
-}
-
-module_init(rr_init_module);
-module_exit(rr_cleanup_module);
+module_pci_driver(rr_driver);
index 22b4527321b1cf6a99140f8845ba40137f8cf451..c74f384c87d50a0314b84e2808ab735c00ee8684 100644 (file)
@@ -794,7 +794,6 @@ static int bfin_sir_remove(struct platform_device *pdev)
        kfree(self->rx_buff.head);
        free_netdev(dev);
        kfree(sir_port);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index 9448587de4531c79517f05d0928b36163d474325..4455425f1c777865676150fa5da63b94f0ffc736 100644 (file)
@@ -838,7 +838,6 @@ static int sh_irda_remove(struct platform_device *pdev)
        sh_irda_remove_iobuf(self);
        iounmap(self->membase);
        free_netdev(ndev);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index 24aefcd840654aa10ca97cee1f7b323d9d7a404e..89682b49900ff2cac834c85cc58429ec4fb65ec3 100644 (file)
@@ -796,7 +796,6 @@ static int sh_sir_remove(struct platform_device *pdev)
        sh_sir_remove_iobuf(self);
        iounmap(self->membase);
        free_netdev(ndev);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index 1c502bb0c916ff549ab10400af5d24b7f61c4866..edfddc5f61b46a06dd0c333aed321e42e3c150cb 100644 (file)
@@ -921,7 +921,7 @@ static struct rtnl_link_ops macvlan_link_ops = {
 static int macvlan_device_event(struct notifier_block *unused,
                                unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct macvlan_dev *vlan, *next;
        struct macvlan_port *port;
        LIST_HEAD(list_kill);
index 59e9605de316809a702951a5c6de3dbee3a43a69..68efb91a56335b66552868a93ddb643ef8c33bc6 100644 (file)
@@ -1053,7 +1053,7 @@ EXPORT_SYMBOL_GPL(macvtap_get_socket);
 static int macvtap_device_event(struct notifier_block *unused,
                                unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct macvlan_dev *vlan;
        struct device *classdev;
        dev_t devt;
index 59ac143dec2576a697d9f383ef4d5d7372eef93c..1d1d0a12765ce943b1bb309bdcbc0534908d8f53 100644 (file)
@@ -653,12 +653,11 @@ static struct configfs_subsystem netconsole_subsys = {
 
 /* Handle network interface device notifications */
 static int netconsole_netdev_event(struct notifier_block *this,
-                                  unsigned long event,
-                                  void *ptr)
+                                  unsigned long event, void *ptr)
 {
        unsigned long flags;
        struct netconsole_target *nt;
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        bool stopped = false;
 
        if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
index 1e11f2bfd9cef59bbe1f1e563c28918c6ecc7f16..3a316b30089f9139384ef35b6424ccc6bd8fbe0a 100644 (file)
@@ -144,6 +144,16 @@ config MDIO_OCTEON
 
          If in doubt, say Y.
 
+config MDIO_SUN4I
+       tristate "Allwinner sun4i MDIO interface support"
+       depends on ARCH_SUNXI
+       select REGULATOR
+       select REGULATOR_FIXED_VOLTAGE
+       help
+         This driver supports the MDIO interface found in the network
+         interface units of the Allwinner SoC that have an EMAC (A10,
+         A12, A10s, etc.)
+
 config MDIO_BUS_MUX
        tristate
        depends on OF_MDIO
index 9645e389a58d34fbdb0c74a737d61b33a4885b6a..23a2ab2e847e54d0d5b7ace4e4002f6c836c49e4 100644 (file)
@@ -30,3 +30,4 @@ obj-$(CONFIG_AMD_PHY)         += amd.o
 obj-$(CONFIG_MDIO_BUS_MUX)     += mdio-mux.o
 obj-$(CONFIG_MDIO_BUS_MUX_GPIO)        += mdio-mux-gpio.o
 obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
+obj-$(CONFIG_MDIO_SUN4I)       += mdio-sun4i.o
index 45cbc10de01cddb802153c7c00fcab6f72486db9..1f7091b3c27ca5e972425602f7e56ce45c5d92a2 100644 (file)
 #define AT803X_MMD_ACCESS_CONTROL              0x0D
 #define AT803X_MMD_ACCESS_CONTROL_DATA         0x0E
 #define AT803X_FUNC_DATA                       0x4003
+#define AT803X_DEBUG_ADDR                      0x1D
+#define AT803X_DEBUG_DATA                      0x1E
+#define AT803X_DEBUG_SYSTEM_MODE_CTRL          0x05
+#define AT803X_DEBUG_RGMII_TX_CLK_DLY          BIT(8)
 
 MODULE_DESCRIPTION("Atheros 803x PHY driver");
 MODULE_AUTHOR("Matus Ujhelyi");
 MODULE_LICENSE("GPL");
 
-static void at803x_set_wol_mac_addr(struct phy_device *phydev)
+static int at803x_set_wol(struct phy_device *phydev,
+                         struct ethtool_wolinfo *wol)
 {
        struct net_device *ndev = phydev->attached_dev;
        const u8 *mac;
+       int ret;
+       u32 value;
        unsigned int i, offsets[] = {
                AT803X_LOC_MAC_ADDR_32_47_OFFSET,
                AT803X_LOC_MAC_ADDR_16_31_OFFSET,
@@ -43,30 +50,61 @@ static void at803x_set_wol_mac_addr(struct phy_device *phydev)
        };
 
        if (!ndev)
-               return;
+               return -ENODEV;
 
-       mac = (const u8 *) ndev->dev_addr;
+       if (wol->wolopts & WAKE_MAGIC) {
+               mac = (const u8 *) ndev->dev_addr;
 
-       if (!is_valid_ether_addr(mac))
-               return;
+               if (!is_valid_ether_addr(mac))
+                       return -EFAULT;
 
-       for (i = 0; i < 3; i++) {
-               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+               for (i = 0; i < 3; i++) {
+                       phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
                                  AT803X_DEVICE_ADDR);
-               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                       phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
                                  offsets[i]);
-               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+                       phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
                                  AT803X_FUNC_DATA);
-               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                       phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
                                  mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
+               }
+
+               value = phy_read(phydev, AT803X_INTR_ENABLE);
+               value |= AT803X_WOL_ENABLE;
+               ret = phy_write(phydev, AT803X_INTR_ENABLE, value);
+               if (ret)
+                       return ret;
+               value = phy_read(phydev, AT803X_INTR_STATUS);
+       } else {
+               value = phy_read(phydev, AT803X_INTR_ENABLE);
+               value &= (~AT803X_WOL_ENABLE);
+               ret = phy_write(phydev, AT803X_INTR_ENABLE, value);
+               if (ret)
+                       return ret;
+               value = phy_read(phydev, AT803X_INTR_STATUS);
        }
+
+       return ret;
+}
+
+static void at803x_get_wol(struct phy_device *phydev,
+                          struct ethtool_wolinfo *wol)
+{
+       u32 value;
+
+       wol->supported = WAKE_MAGIC;
+       wol->wolopts = 0;
+
+       value = phy_read(phydev, AT803X_INTR_ENABLE);
+       if (value & AT803X_WOL_ENABLE)
+               wol->wolopts |= WAKE_MAGIC;
 }
 
 static int at803x_config_init(struct phy_device *phydev)
 {
        int val;
+       int ret;
        u32 features;
-       int status;
 
        features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI |
                   SUPPORTED_FIBRE | SUPPORTED_BNC;
@@ -100,20 +138,29 @@ static int at803x_config_init(struct phy_device *phydev)
        phydev->supported = features;
        phydev->advertising = features;
 
-       /* enable WOL */
-       at803x_set_wol_mac_addr(phydev);
-       status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE);
-       status = phy_read(phydev, AT803X_INTR_STATUS);
+       if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
+               ret = phy_write(phydev, AT803X_DEBUG_ADDR,
+                               AT803X_DEBUG_SYSTEM_MODE_CTRL);
+               if (ret)
+                       return ret;
+               ret = phy_write(phydev, AT803X_DEBUG_DATA,
+                               AT803X_DEBUG_RGMII_TX_CLK_DLY);
+               if (ret)
+                       return ret;
+       }
 
        return 0;
 }
 
-/* ATHEROS 8035 */
-static struct phy_driver at8035_driver = {
+static struct phy_driver at803x_driver[] = {
+{
+       /* ATHEROS 8035 */
        .phy_id         = 0x004dd072,
        .name           = "Atheros 8035 ethernet",
        .phy_id_mask    = 0xffffffef,
        .config_init    = at803x_config_init,
+       .set_wol        = at803x_set_wol,
+       .get_wol        = at803x_get_wol,
        .features       = PHY_GBIT_FEATURES,
        .flags          = PHY_HAS_INTERRUPT,
        .config_aneg    = &genphy_config_aneg,
@@ -121,14 +168,14 @@ static struct phy_driver at8035_driver = {
        .driver         = {
                .owner = THIS_MODULE,
        },
-};
-
-/* ATHEROS 8030 */
-static struct phy_driver at8030_driver = {
+}, {
+       /* ATHEROS 8030 */
        .phy_id         = 0x004dd076,
        .name           = "Atheros 8030 ethernet",
        .phy_id_mask    = 0xffffffef,
        .config_init    = at803x_config_init,
+       .set_wol        = at803x_set_wol,
+       .get_wol        = at803x_get_wol,
        .features       = PHY_GBIT_FEATURES,
        .flags          = PHY_HAS_INTERRUPT,
        .config_aneg    = &genphy_config_aneg,
@@ -136,32 +183,33 @@ static struct phy_driver at8030_driver = {
        .driver         = {
                .owner = THIS_MODULE,
        },
-};
+}, {
+       /* ATHEROS 8031 */
+       .phy_id         = 0x004dd074,
+       .name           = "Atheros 8031 ethernet",
+       .phy_id_mask    = 0xffffffef,
+       .config_init    = at803x_config_init,
+       .set_wol        = at803x_set_wol,
+       .get_wol        = at803x_get_wol,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .driver         = {
+               .owner = THIS_MODULE,
+       },
+} };
 
 static int __init atheros_init(void)
 {
-       int ret;
-
-       ret = phy_driver_register(&at8035_driver);
-       if (ret)
-               goto err1;
-
-       ret = phy_driver_register(&at8030_driver);
-       if (ret)
-               goto err2;
-
-       return 0;
-
-err2:
-       phy_driver_unregister(&at8035_driver);
-err1:
-       return ret;
+       return phy_drivers_register(at803x_driver,
+                                   ARRAY_SIZE(at803x_driver));
 }
 
 static void __exit atheros_exit(void)
 {
-       phy_driver_unregister(&at8035_driver);
-       phy_driver_unregister(&at8030_driver);
+       return phy_drivers_unregister(at803x_driver,
+                                     ARRAY_SIZE(at803x_driver));
 }
 
 module_init(atheros_init);
index 84c7a39b1c659a91a82cb8c82d1436e0f994cc5b..ac55b08078534e8170416630dced41dba150564c 100644 (file)
@@ -78,7 +78,7 @@ static struct phy_driver bcm63xx_driver[] = {
        .name           = "Broadcom BCM63XX (1)",
        /* ASYM_PAUSE bit is marked RO in datasheet, so don't cheat */
        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
-       .flags          = PHY_HAS_INTERRUPT,
+       .flags          = PHY_HAS_INTERRUPT | PHY_IS_INTERNAL,
        .config_init    = bcm63xx_config_init,
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
@@ -91,7 +91,7 @@ static struct phy_driver bcm63xx_driver[] = {
        .phy_id_mask    = 0xfffffc00,
        .name           = "Broadcom BCM63XX (2)",
        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
-       .flags          = PHY_HAS_INTERRUPT,
+       .flags          = PHY_HAS_INTERRUPT | PHY_IS_INTERNAL,
        .config_init    = bcm63xx_config_init,
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
index 202fe1ff1987950effe6e0a0426894a0ad8dea78..2e91477362d4d70b15df3db59ad41dec990a3c57 100644 (file)
 #define MII_M1011_PHY_STATUS_RESOLVED  0x0800
 #define MII_M1011_PHY_STATUS_LINK      0x0400
 
+#define MII_M1116R_CONTROL_REG_MAC     21
+
 
 MODULE_DESCRIPTION("Marvell PHY driver");
 MODULE_AUTHOR("Andy Fleming");
@@ -372,6 +374,66 @@ static int m88e1318_config_aneg(struct phy_device *phydev)
        return m88e1121_config_aneg(phydev);
 }
 
+static int m88e1510_config_aneg(struct phy_device *phydev)
+{
+       int err;
+
+       err = m88e1318_config_aneg(phydev);
+       if (err < 0)
+               return err;
+
+       return marvell_of_reg_init(phydev);
+}
+
+static int m88e1116r_config_init(struct phy_device *phydev)
+{
+       int temp;
+       int err;
+
+       temp = phy_read(phydev, MII_BMCR);
+       temp |= BMCR_RESET;
+       err = phy_write(phydev, MII_BMCR, temp);
+       if (err < 0)
+               return err;
+
+       mdelay(500);
+
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0);
+       if (err < 0)
+               return err;
+
+       temp = phy_read(phydev, MII_M1011_PHY_SCR);
+       temp |= (7 << 12);      /* max number of gigabit attempts */
+       temp |= (1 << 11);      /* enable downshift */
+       temp |= MII_M1011_PHY_SCR_AUTO_CROSS;
+       err = phy_write(phydev, MII_M1011_PHY_SCR, temp);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 2);
+       if (err < 0)
+               return err;
+       temp = phy_read(phydev, MII_M1116R_CONTROL_REG_MAC);
+       temp |= (1 << 5);
+       temp |= (1 << 4);
+       err = phy_write(phydev, MII_M1116R_CONTROL_REG_MAC, temp);
+       if (err < 0)
+               return err;
+       err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0);
+       if (err < 0)
+               return err;
+
+       temp = phy_read(phydev, MII_BMCR);
+       temp |= BMCR_RESET;
+       err = phy_write(phydev, MII_BMCR, temp);
+       if (err < 0)
+               return err;
+
+       mdelay(500);
+
+       return 0;
+}
+
 static int m88e1111_config_init(struct phy_device *phydev)
 {
        int err;
@@ -940,6 +1002,32 @@ static struct phy_driver marvell_drivers[] = {
                .config_intr = &marvell_config_intr,
                .driver = { .owner = THIS_MODULE },
        },
+       {
+               .phy_id = MARVELL_PHY_ID_88E1116R,
+               .phy_id_mask = MARVELL_PHY_ID_MASK,
+               .name = "Marvell 88E1116R",
+               .features = PHY_GBIT_FEATURES,
+               .flags = PHY_HAS_INTERRUPT,
+               .config_init = &m88e1116r_config_init,
+               .config_aneg = &genphy_config_aneg,
+               .read_status = &genphy_read_status,
+               .ack_interrupt = &marvell_ack_interrupt,
+               .config_intr = &marvell_config_intr,
+               .driver = { .owner = THIS_MODULE },
+       },
+       {
+               .phy_id = MARVELL_PHY_ID_88E1510,
+               .phy_id_mask = MARVELL_PHY_ID_MASK,
+               .name = "Marvell 88E1510",
+               .features = PHY_GBIT_FEATURES,
+               .flags = PHY_HAS_INTERRUPT,
+               .config_aneg = &m88e1510_config_aneg,
+               .read_status = &marvell_read_status,
+               .ack_interrupt = &marvell_ack_interrupt,
+               .config_intr = &marvell_config_intr,
+               .did_interrupt = &m88e1121_did_interrupt,
+               .driver = { .owner = THIS_MODULE },
+       },
 };
 
 static int __init marvell_init(void)
@@ -958,15 +1046,17 @@ module_init(marvell_init);
 module_exit(marvell_exit);
 
 static struct mdio_device_id __maybe_unused marvell_tbl[] = {
-       { 0x01410c60, 0xfffffff0 },
-       { 0x01410c90, 0xfffffff0 },
-       { 0x01410cc0, 0xfffffff0 },
-       { 0x01410e10, 0xfffffff0 },
-       { 0x01410cb0, 0xfffffff0 },
-       { 0x01410cd0, 0xfffffff0 },
-       { 0x01410e50, 0xfffffff0 },
-       { 0x01410e30, 0xfffffff0 },
-       { 0x01410e90, 0xfffffff0 },
+       { MARVELL_PHY_ID_88E1101, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1112, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1111, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1118, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1121R, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1145, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1149R, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK },
        { }
 };
 
diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c
new file mode 100644 (file)
index 0000000..61d3f4e
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Allwinner EMAC MDIO interface driver
+ *
+ * Copyright 2012-2013 Stefan Roese <sr@denx.de>
+ * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * Based on the Linux driver provided by Allwinner:
+ * Copyright (C) 1997  Sten Wang
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#define EMAC_MAC_MCMD_REG      (0x00)
+#define EMAC_MAC_MADR_REG      (0x04)
+#define EMAC_MAC_MWTD_REG      (0x08)
+#define EMAC_MAC_MRDD_REG      (0x0c)
+#define EMAC_MAC_MIND_REG      (0x10)
+#define EMAC_MAC_SSRR_REG      (0x14)
+
+#define MDIO_TIMEOUT           (msecs_to_jiffies(100))
+
+struct sun4i_mdio_data {
+       void __iomem            *membase;
+       struct regulator        *regulator;
+};
+
+static int sun4i_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+       struct sun4i_mdio_data *data = bus->priv;
+       unsigned long start_jiffies;
+       int value;
+
+       /* issue the phy address and reg */
+       writel((mii_id << 8) | regnum, data->membase + EMAC_MAC_MADR_REG);
+       /* pull up the phy io line */
+       writel(0x1, data->membase + EMAC_MAC_MCMD_REG);
+
+       /* Wait read complete */
+       start_jiffies = jiffies;
+       while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) {
+               if (time_after(start_jiffies,
+                              start_jiffies + MDIO_TIMEOUT))
+                       return -ETIMEDOUT;
+               msleep(1);
+       }
+
+       /* push down the phy io line */
+       writel(0x0, data->membase + EMAC_MAC_MCMD_REG);
+       /* and read data */
+       value = readl(data->membase + EMAC_MAC_MRDD_REG);
+
+       return value;
+}
+
+static int sun4i_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+                           u16 value)
+{
+       struct sun4i_mdio_data *data = bus->priv;
+       unsigned long start_jiffies;
+
+       /* issue the phy address and reg */
+       writel((mii_id << 8) | regnum, data->membase + EMAC_MAC_MADR_REG);
+       /* pull up the phy io line */
+       writel(0x1, data->membase + EMAC_MAC_MCMD_REG);
+
+       /* Wait read complete */
+       start_jiffies = jiffies;
+       while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) {
+               if (time_after(start_jiffies,
+                              start_jiffies + MDIO_TIMEOUT))
+                       return -ETIMEDOUT;
+               msleep(1);
+       }
+
+       /* push down the phy io line */
+       writel(0x0, data->membase + EMAC_MAC_MCMD_REG);
+       /* and write data */
+       writel(value, data->membase + EMAC_MAC_MWTD_REG);
+
+       return 0;
+}
+
+static int sun4i_mdio_reset(struct mii_bus *bus)
+{
+       return 0;
+}
+
+static int sun4i_mdio_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct mii_bus *bus;
+       struct sun4i_mdio_data *data;
+       int ret, i;
+
+       bus = mdiobus_alloc_size(sizeof(*data));
+       if (!bus)
+               return -ENOMEM;
+
+       bus->name = "sun4i_mii_bus";
+       bus->read = &sun4i_mdio_read;
+       bus->write = &sun4i_mdio_write;
+       bus->reset = &sun4i_mdio_reset;
+       snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev));
+       bus->parent = &pdev->dev;
+
+       bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+       if (!bus->irq) {
+               ret = -ENOMEM;
+               goto err_out_free_mdiobus;
+       }
+
+       for (i = 0; i < PHY_MAX_ADDR; i++)
+               bus->irq[i] = PHY_POLL;
+
+       data = bus->priv;
+       data->membase = of_iomap(np, 0);
+       if (!data->membase) {
+               ret = -ENOMEM;
+               goto err_out_free_mdio_irq;
+       }
+
+       data->regulator = devm_regulator_get(&pdev->dev, "phy");
+       if (IS_ERR(data->regulator)) {
+               if (PTR_ERR(data->regulator) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               dev_info(&pdev->dev, "no regulator found\n");
+       } else {
+               ret = regulator_enable(data->regulator);
+               if (ret)
+                       goto err_out_free_mdio_irq;
+       }
+
+       ret = of_mdiobus_register(bus, np);
+       if (ret < 0)
+               goto err_out_disable_regulator;
+
+       platform_set_drvdata(pdev, bus);
+
+       return 0;
+
+err_out_disable_regulator:
+       regulator_disable(data->regulator);
+err_out_free_mdio_irq:
+       kfree(bus->irq);
+err_out_free_mdiobus:
+       mdiobus_free(bus);
+       return ret;
+}
+
+static int sun4i_mdio_remove(struct platform_device *pdev)
+{
+       struct mii_bus *bus = platform_get_drvdata(pdev);
+
+       mdiobus_unregister(bus);
+       kfree(bus->irq);
+       mdiobus_free(bus);
+
+       return 0;
+}
+
+static const struct of_device_id sun4i_mdio_dt_ids[] = {
+       { .compatible = "allwinner,sun4i-mdio" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sun4i_mdio_dt_ids);
+
+static struct platform_driver sun4i_mdio_driver = {
+       .probe = sun4i_mdio_probe,
+       .remove = sun4i_mdio_remove,
+       .driver = {
+               .name = "sun4i-mdio",
+               .of_match_table = sun4i_mdio_dt_ids,
+       },
+};
+
+module_platform_driver(sun4i_mdio_driver);
+
+MODULE_DESCRIPTION("Allwinner EMAC MDIO interface driver");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_LICENSE("GPL");
index 38f0b312ff85e339bc742c8472ef244bb9c50a40..10d058ab4f7969b50a0f8b378ac360e263b2104e 100644 (file)
@@ -294,7 +294,8 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
        cmd->duplex = phydev->duplex;
        cmd->port = PORT_MII;
        cmd->phy_address = phydev->addr;
-       cmd->transceiver = XCVR_EXTERNAL;
+       cmd->transceiver = phy_is_internal(phydev) ?
+               XCVR_INTERNAL : XCVR_EXTERNAL;
        cmd->autoneg = phydev->autoneg;
 
        return 0;
@@ -419,8 +420,6 @@ out_unlock:
 EXPORT_SYMBOL(phy_start_aneg);
 
 
-static void phy_change(struct work_struct *work);
-
 /**
  * phy_start_machine - start PHY state machine tracking
  * @phydev: the phy_device struct
@@ -565,8 +564,6 @@ int phy_start_interrupts(struct phy_device *phydev)
 {
        int err = 0;
 
-       INIT_WORK(&phydev->phy_queue, phy_change);
-
        atomic_set(&phydev->irq_disable, 0);
        if (request_irq(phydev->irq, phy_interrupt,
                                IRQF_SHARED,
@@ -623,7 +620,7 @@ 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
  */
-static void phy_change(struct work_struct *work)
+void phy_change(struct work_struct *work)
 {
        int err;
        struct phy_device *phydev =
@@ -682,7 +679,7 @@ void phy_stop(struct phy_device *phydev)
        if (PHY_HALTED == phydev->state)
                goto out_unlock;
 
-       if (phydev->irq != PHY_POLL) {
+       if (phy_interrupt_is_valid(phydev)) {
                /* Disable PHY Interrupts */
                phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
 
@@ -828,8 +825,9 @@ void phy_state_machine(struct work_struct *work)
                        break;
                case PHY_RUNNING:
                        /* Only register a CHANGE if we are
-                        * polling */
-                       if (PHY_POLL == phydev->irq)
+                        * polling or ignoring interrupts
+                        */
+                       if (!phy_interrupt_is_valid(phydev))
                                phydev->state = PHY_CHANGELINK;
                        break;
                case PHY_CHANGELINK:
@@ -848,7 +846,7 @@ void phy_state_machine(struct work_struct *work)
 
                        phydev->adjust_link(phydev->attached_dev);
 
-                       if (PHY_POLL != phydev->irq)
+                       if (phy_interrupt_is_valid(phydev))
                                err = phy_config_interrupt(phydev,
                                                PHY_INTERRUPT_ENABLED);
                        break;
@@ -921,6 +919,14 @@ void phy_state_machine(struct work_struct *work)
        schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
 }
 
+void phy_mac_interrupt(struct phy_device *phydev, int new_link)
+{
+       cancel_work_sync(&phydev->phy_queue);
+       phydev->link = new_link;
+       schedule_work(&phydev->phy_queue);
+}
+EXPORT_SYMBOL(phy_mac_interrupt);
+
 static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
                                    int addr)
 {
index 3657b4a29124b57bc335417a1389f792aaf2ce79..74630e94fa3bc323b9528b691514d7456b9abd6d 100644 (file)
@@ -189,6 +189,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
 
        mutex_init(&dev->lock);
        INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
+       INIT_WORK(&dev->phy_queue, phy_change);
 
        /* Request the appropriate module unconditionally; don't
           bother trying to do so only if it isn't already loaded,
@@ -1009,10 +1010,16 @@ static int phy_probe(struct device *dev)
        phydrv = to_phy_driver(drv);
        phydev->drv = phydrv;
 
-       /* Disable the interrupt if the PHY doesn't support it */
-       if (!(phydrv->flags & PHY_HAS_INTERRUPT))
+       /* 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))
                phydev->irq = PHY_POLL;
 
+       if (phydrv->flags & PHY_IS_INTERNAL)
+               phydev->is_internal = true;
+
        mutex_lock(&phydev->lock);
 
        /* Start out supporting everything. Eventually,
index d11c93e69e03fafac4efee44cad6c47e55380dda..f3bea1346021273b85cfc8d5016e3def067eec46 100644 (file)
@@ -354,19 +354,7 @@ static struct spi_driver ks8995_driver = {
        .remove   = ks8995_remove,
 };
 
-static int __init ks8995_init(void)
-{
-       pr_info(DRV_DESC " version " DRV_VERSION "\n");
-
-       return spi_register_driver(&ks8995_driver);
-}
-module_init(ks8995_init);
-
-static void __exit ks8995_exit(void)
-{
-       spi_unregister_driver(&ks8995_driver);
-}
-module_exit(ks8995_exit);
+module_spi_driver(ks8995_driver);
 
 MODULE_DESCRIPTION(DRV_DESC);
 MODULE_VERSION(DRV_VERSION);
index 3492b53912731eae9407fe6dbb15468d35429263..69b482bce7d2449688fc67731cf923ce47ffcc32 100644 (file)
 #define MII_VSC8244_ISTAT_DUPLEX       0x1000
 
 /* Vitesse Auxiliary Control/Status Register */
-#define MII_VSC8244_AUX_CONSTAT                0x1c
-#define MII_VSC8244_AUXCONSTAT_INIT            0x0000
-#define MII_VSC8244_AUXCONSTAT_DUPLEX          0x0020
-#define MII_VSC8244_AUXCONSTAT_SPEED           0x0018
-#define MII_VSC8244_AUXCONSTAT_GBIT            0x0010
-#define MII_VSC8244_AUXCONSTAT_100             0x0008
+#define MII_VSC8244_AUX_CONSTAT                0x1c
+#define MII_VSC8244_AUXCONSTAT_INIT    0x0000
+#define MII_VSC8244_AUXCONSTAT_DUPLEX  0x0020
+#define MII_VSC8244_AUXCONSTAT_SPEED   0x0018
+#define MII_VSC8244_AUXCONSTAT_GBIT    0x0010
+#define MII_VSC8244_AUXCONSTAT_100     0x0008
 
 #define MII_VSC8221_AUXCONSTAT_INIT    0x0004 /* need to set this bit? */
 #define MII_VSC8221_AUXCONSTAT_RESERVED        0x0004
 
 #define PHY_ID_VSC8244                 0x000fc6c0
 #define PHY_ID_VSC8221                 0x000fc550
+#define PHY_ID_VSC8211                 0x000fc4b0
 
 MODULE_DESCRIPTION("Vitesse PHY driver");
 MODULE_AUTHOR("Kriston Carson");
@@ -100,9 +101,8 @@ static int vsc824x_config_init(struct phy_device *phydev)
 static int vsc824x_ack_interrupt(struct phy_device *phydev)
 {
        int err = 0;
-       
-       /*
-        * Don't bother to ACK the interrupts if interrupts
+
+       /* Don't bother to ACK the interrupts if interrupts
         * are disabled.  The 824x cannot clear the interrupts
         * if they are disabled.
         */
@@ -122,8 +122,7 @@ static int vsc82xx_config_intr(struct phy_device *phydev)
                                MII_VSC8244_IMASK_MASK :
                                MII_VSC8221_IMASK_MASK);
        else {
-               /*
-                * The Vitesse PHY cannot clear the interrupt
+               /* The Vitesse PHY cannot clear the interrupt
                 * once it has disabled them, so we clear them first
                 */
                err = phy_read(phydev, MII_VSC8244_ISTAT);
@@ -146,7 +145,8 @@ static int vsc8221_config_init(struct phy_device *phydev)
        return err;
 
        /* Perhaps we should set EXT_CON1 based on the interface?
-          Options are 802.3Z SerDes or SGMII */
+        * Options are 802.3Z SerDes or SGMII
+        */
 }
 
 /* Vitesse 824x */
@@ -176,6 +176,19 @@ static struct phy_driver vsc82xx_driver[] = {
        .ack_interrupt  = &vsc824x_ack_interrupt,
        .config_intr    = &vsc82xx_config_intr,
        .driver         = { .owner = THIS_MODULE,},
+}, {
+       /* Vitesse 8211 */
+       .phy_id         = PHY_ID_VSC8211,
+       .phy_id_mask    = 0x000ffff0,
+       .name           = "Vitesse VSC8211",
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = &vsc8221_config_init,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &vsc824x_ack_interrupt,
+       .config_intr    = &vsc82xx_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
 } };
 
 static int __init vsc82xx_init(void)
@@ -196,6 +209,7 @@ module_exit(vsc82xx_exit);
 static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
        { PHY_ID_VSC8244, 0x000fffc0 },
        { PHY_ID_VSC8221, 0x000ffff0 },
+       { PHY_ID_VSC8211, 0x000ffff0 },
        { }
 };
 
index bb07ba94c3aaedb8949c310d340c18ae1b9ab284..5f66e30d98239651283ec200cbf3c842e60eb2ae 100644 (file)
@@ -338,7 +338,7 @@ static void pppoe_flush_dev(struct net_device *dev)
 static int pppoe_device_event(struct notifier_block *this,
                              unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        /* Only look at sockets that are using this specific device. */
        switch (event) {
index d016a76ad44b40add050d83a7ba7335c304a63c1..04e9adb748c537ba6d4d370f0bb4327526578a79 100644 (file)
@@ -2648,7 +2648,7 @@ static void team_port_change_check(struct team_port *port, bool linkup)
 static int team_device_event(struct notifier_block *unused,
                             unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *) ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct team_port *port;
 
        port = team_port_get_rtnl(dev);
index 0192073e53a30723927558e624789874511847b0..6866eae3e388b76a1a688627580d5e9b29147c05 100644 (file)
@@ -221,12 +221,9 @@ done:
                memset(skb_put(skb, padlen), 0, padlen);
        }
 
-       netdev_dbg(
-               dev->net,
-               "Sending package with length %i and padding %i. Header: %02x:%02x:%02x:%02x:%02x:%02x.",
-               content_len, padlen, header_start[0], header_start[1],
-               header_start[2], header_start[3], header_start[4],
-               header_start[5]);
+       netdev_dbg(dev->net,
+               "Sending package with length %i and padding %i. Header: %6phC.",
+               content_len, padlen, header_start);
 
        return skb;
 }
@@ -263,32 +260,23 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                                sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp(
                                header_start, EXPECTED_UNKNOWN_HEADER_2,
                                sizeof(EXPECTED_UNKNOWN_HEADER_2))) {
-                               netdev_dbg(
-                                       dev->net,
-                                       "Received expected unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
-                                       header_start[0], header_start[1],
-                                       header_start[2], header_start[3],
-                                       header_start[4], header_start[5],
+                               netdev_dbg(dev->net,
+                                       "Received expected unknown frame header: %6phC. Package length: %i\n",
+                                       header_start,
                                        skb->len - KALMIA_HEADER_LENGTH);
                        }
                        else {
-                               netdev_err(
-                                       dev->net,
-                                       "Received unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
-                                       header_start[0], header_start[1],
-                                       header_start[2], header_start[3],
-                                       header_start[4], header_start[5],
+                               netdev_err(dev->net,
+                                       "Received unknown frame header: %6phC. Package length: %i\n",
+                                       header_start,
                                        skb->len - KALMIA_HEADER_LENGTH);
                                return 0;
                        }
                }
                else
-                       netdev_dbg(
-                               dev->net,
-                               "Received header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
-                               header_start[0], header_start[1], header_start[2],
-                               header_start[3], header_start[4], header_start[5],
-                               skb->len - KALMIA_HEADER_LENGTH);
+                       netdev_dbg(dev->net,
+                               "Received header: %6phC. Package length: %i\n",
+                               header_start, skb->len - KALMIA_HEADER_LENGTH);
 
                /* subtract start header and end header */
                usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH);
@@ -310,12 +298,9 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                                sizeof(HEADER_END_OF_USB_PACKET)) == 0);
                        if (!is_last) {
                                header_start = skb->data + ether_packet_length;
-                               netdev_dbg(
-                                       dev->net,
-                                       "End header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
-                                       header_start[0], header_start[1],
-                                       header_start[2], header_start[3],
-                                       header_start[4], header_start[5],
+                               netdev_dbg(dev->net,
+                                       "End header: %6phC. Package length: %i\n",
+                                       header_start,
                                        skb->len - KALMIA_HEADER_LENGTH);
                        }
                }
index 14e5198886311fca92b7bf1baf1facc6b5958221..d02bac82fc5759df00a8bfab5907e29f92be722c 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/signal.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/mii.h>
@@ -1749,18 +1748,7 @@ static struct usb_driver rtl8152_driver = {
        .resume =       rtl8152_resume
 };
 
-static int __init usb_rtl8152_init(void)
-{
-       return usb_register(&rtl8152_driver);
-}
-
-static void __exit usb_rtl8152_exit(void)
-{
-       usb_deregister(&rtl8152_driver);
-}
-
-module_init(usb_rtl8152_init);
-module_exit(usb_rtl8152_exit);
+module_usb_driver(rtl8152_driver);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
index 3b1d2ee7156b00195376c674f605f5749a2daf64..8111565c35fceec89b3da0afcf0e8861a19eed40 100644 (file)
@@ -44,6 +44,8 @@
 
 #define VXLAN_VERSION  "0.1"
 
+#define PORT_HASH_BITS 8
+#define PORT_HASH_SIZE  (1<<PORT_HASH_BITS)
 #define VNI_HASH_BITS  10
 #define VNI_HASH_SIZE  (1<<VNI_HASH_BITS)
 #define FDB_HASH_BITS  8
@@ -76,15 +78,25 @@ static bool log_ecn_error = true;
 module_param(log_ecn_error, bool, 0644);
 MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
 
-/* per-net private data for this module */
 static unsigned int vxlan_net_id;
-struct vxlan_net {
-       struct socket     *sock;        /* UDP encap socket */
+
+/* per UDP socket information */
+struct vxlan_sock {
+       struct hlist_node hlist;
+       struct rcu_head   rcu;
+       struct work_struct del_work;
+       unsigned int      refcnt;
+       struct socket     *sock;
        struct hlist_head vni_list[VNI_HASH_SIZE];
 };
 
+/* per-network namespace private data for this module */
+struct vxlan_net {
+       struct list_head  vxlan_list;
+       struct hlist_head sock_list[PORT_HASH_SIZE];
+};
+
 struct vxlan_rdst {
-       struct rcu_head          rcu;
        __be32                   remote_ip;
        __be16                   remote_port;
        u32                      remote_vni;
@@ -106,7 +118,9 @@ struct vxlan_fdb {
 
 /* Pseudo network device */
 struct vxlan_dev {
-       struct hlist_node hlist;
+       struct hlist_node hlist;        /* vni hash table */
+       struct list_head  next;         /* vxlan's per namespace list */
+       struct vxlan_sock *vn_sock;     /* listening socket */
        struct net_device *dev;
        struct vxlan_rdst default_dst;  /* default destination */
        __be32            saddr;        /* source address */
@@ -135,19 +149,43 @@ struct vxlan_dev {
 /* salt for hash table */
 static u32 vxlan_salt __read_mostly;
 
-static inline struct hlist_head *vni_head(struct net *net, u32 id)
+/* Virtual Network hash table head */
+static inline struct hlist_head *vni_head(struct vxlan_sock *vs, u32 id)
+{
+       return &vs->vni_list[hash_32(id, VNI_HASH_BITS)];
+}
+
+/* Socket hash table head */
+static inline struct hlist_head *vs_head(struct net *net, __be16 port)
 {
        struct vxlan_net *vn = net_generic(net, vxlan_net_id);
 
-       return &vn->vni_list[hash_32(id, VNI_HASH_BITS)];
+       return &vn->sock_list[hash_32(ntohs(port), PORT_HASH_BITS)];
+}
+
+/* Find VXLAN socket based on network namespace and UDP port */
+static struct vxlan_sock *vxlan_find_port(struct net *net, __be16 port)
+{
+       struct vxlan_sock *vs;
+
+       hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
+               if (inet_sk(vs->sock->sk)->inet_sport == port)
+                       return vs;
+       }
+       return NULL;
 }
 
 /* Look up VNI in a per net namespace table */
-static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id)
+static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, __be16 port)
 {
+       struct vxlan_sock *vs;
        struct vxlan_dev *vxlan;
 
-       hlist_for_each_entry_rcu(vxlan, vni_head(net, id), hlist) {
+       vs = vxlan_find_port(net, port);
+       if (!vs)
+               return NULL;
+
+       hlist_for_each_entry_rcu(vxlan, vni_head(vs, id), hlist) {
                if (vxlan->default_dst.remote_vni == id)
                        return vxlan;
        }
@@ -603,20 +641,18 @@ static void vxlan_snoop(struct net_device *dev,
 static bool vxlan_group_used(struct vxlan_net *vn,
                             const struct vxlan_dev *this)
 {
-       const struct vxlan_dev *vxlan;
-       unsigned h;
+       struct vxlan_dev *vxlan;
 
-       for (h = 0; h < VNI_HASH_SIZE; ++h)
-               hlist_for_each_entry(vxlan, &vn->vni_list[h], hlist) {
-                       if (vxlan == this)
-                               continue;
+       list_for_each_entry(vxlan, &vn->vxlan_list, next) {
+               if (vxlan == this)
+                       continue;
 
-                       if (!netif_running(vxlan->dev))
-                               continue;
+               if (!netif_running(vxlan->dev))
+                       continue;
 
-                       if (vxlan->default_dst.remote_ip == this->default_dst.remote_ip)
-                               return true;
-               }
+               if (vxlan->default_dst.remote_ip == this->default_dst.remote_ip)
+                       return true;
+       }
 
        return false;
 }
@@ -626,7 +662,7 @@ static int vxlan_join_group(struct net_device *dev)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
-       struct sock *sk = vn->sock->sk;
+       struct sock *sk = vxlan->vn_sock->sock->sk;
        struct ip_mreqn mreq = {
                .imr_multiaddr.s_addr   = vxlan->default_dst.remote_ip,
                .imr_ifindex            = vxlan->default_dst.remote_ifindex,
@@ -654,7 +690,7 @@ static int vxlan_leave_group(struct net_device *dev)
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
        int err = 0;
-       struct sock *sk = vn->sock->sk;
+       struct sock *sk = vxlan->vn_sock->sock->sk;
        struct ip_mreqn mreq = {
                .imr_multiaddr.s_addr   = vxlan->default_dst.remote_ip,
                .imr_ifindex            = vxlan->default_dst.remote_ifindex,
@@ -681,6 +717,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
        struct vxlanhdr *vxh;
        struct vxlan_dev *vxlan;
        struct pcpu_tstats *stats;
+       __be16 port;
        __u32 vni;
        int err;
 
@@ -704,9 +741,11 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
        /* Is this VNI defined? */
        vni = ntohl(vxh->vx_vni) >> 8;
-       vxlan = vxlan_find_vni(sock_net(sk), vni);
+       port = inet_sk(sk)->inet_sport;
+       vxlan = vxlan_find_vni(sock_net(sk), vni, port);
        if (!vxlan) {
-               netdev_dbg(skb->dev, "unknown vni %d\n", vni);
+               netdev_dbg(skb->dev, "unknown vni %d port %u\n",
+                          vni, ntohs(port));
                goto drop;
        }
 
@@ -886,7 +925,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
        return false;
 }
 
-static void vxlan_sock_free(struct sk_buff *skb)
+static void vxlan_sock_put(struct sk_buff *skb)
 {
        sock_put(skb->sk);
 }
@@ -894,13 +933,13 @@ static void vxlan_sock_free(struct sk_buff *skb)
 /* On transmit, associate with the tunnel socket */
 static void vxlan_set_owner(struct net_device *dev, struct sk_buff *skb)
 {
-       struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
-       struct sock *sk = vn->sock->sk;
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct sock *sk = vxlan->vn_sock->sock->sk;
 
        skb_orphan(skb);
        sock_hold(sk);
        skb->sk = sk;
-       skb->destructor = vxlan_sock_free;
+       skb->destructor = vxlan_sock_put;
 }
 
 /* Compute source port for outgoing packet
@@ -1042,7 +1081,7 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                struct vxlan_dev *dst_vxlan;
 
                ip_rt_put(rt);
-               dst_vxlan = vxlan_find_vni(dev_net(dev), vni);
+               dst_vxlan = vxlan_find_vni(dev_net(dev), vni, dst_port);
                if (!dst_vxlan)
                        goto tx_error;
                vxlan_encap_bypass(skb, vxlan, dst_vxlan);
@@ -1230,7 +1269,7 @@ static int vxlan_open(struct net_device *dev)
 /* Purge the forwarding table */
 static void vxlan_flush(struct vxlan_dev *vxlan)
 {
-       unsigned h;
+       unsigned int h;
 
        spin_lock_bh(&vxlan->hash_lock);
        for (h = 0; h < FDB_HASH_SIZE; ++h) {
@@ -1294,7 +1333,7 @@ static void vxlan_free(struct net_device *dev)
 static void vxlan_setup(struct net_device *dev)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
-       unsigned h;
+       unsigned int h;
        int low, high;
 
        eth_hw_addr_random(dev);
@@ -1317,6 +1356,7 @@ static void vxlan_setup(struct net_device *dev)
        dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
+       INIT_LIST_HEAD(&vxlan->next);
        spin_lock_init(&vxlan->hash_lock);
 
        init_timer_deferrable(&vxlan->age_timer);
@@ -1401,11 +1441,78 @@ static const struct ethtool_ops vxlan_ethtool_ops = {
        .get_link       = ethtool_op_get_link,
 };
 
+static void vxlan_del_work(struct work_struct *work)
+{
+       struct vxlan_sock *vs = container_of(work, struct vxlan_sock, del_work);
+
+       sk_release_kernel(vs->sock->sk);
+       kfree_rcu(vs, rcu);
+}
+
+/* Create new listen socket if needed */
+static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port)
+{
+       struct vxlan_sock *vs;
+       struct sock *sk;
+       struct sockaddr_in vxlan_addr = {
+               .sin_family = AF_INET,
+               .sin_addr.s_addr = htonl(INADDR_ANY),
+       };
+       int rc;
+       unsigned int h;
+
+       vs = kmalloc(sizeof(*vs), GFP_KERNEL);
+       if (!vs)
+               return ERR_PTR(-ENOMEM);
+
+       for (h = 0; h < VNI_HASH_SIZE; ++h)
+               INIT_HLIST_HEAD(&vs->vni_list[h]);
+
+       INIT_WORK(&vs->del_work, vxlan_del_work);
+
+       /* Create UDP socket for encapsulation receive. */
+       rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vs->sock);
+       if (rc < 0) {
+               pr_debug("UDP socket create failed\n");
+               kfree(vs);
+               return ERR_PTR(rc);
+       }
+
+       /* Put in proper namespace */
+       sk = vs->sock->sk;
+       sk_change_net(sk, net);
+
+       vxlan_addr.sin_port = port;
+
+       rc = kernel_bind(vs->sock, (struct sockaddr *) &vxlan_addr,
+                        sizeof(vxlan_addr));
+       if (rc < 0) {
+               pr_debug("bind for UDP socket %pI4:%u (%d)\n",
+                        &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc);
+               sk_release_kernel(sk);
+               kfree(vs);
+               return ERR_PTR(rc);
+       }
+
+       /* Disable multicast loopback */
+       inet_sk(sk)->mc_loop = 0;
+
+       /* Mark socket as an encapsulation socket. */
+       udp_sk(sk)->encap_type = 1;
+       udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv;
+       udp_encap_enable();
+
+       vs->refcnt = 1;
+       return vs;
+}
+
 static int vxlan_newlink(struct net *net, struct net_device *dev,
                         struct nlattr *tb[], struct nlattr *data[])
 {
+       struct vxlan_net *vn = net_generic(net, vxlan_net_id);
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_rdst *dst = &vxlan->default_dst;
+       struct vxlan_sock *vs;
        __u32 vni;
        int err;
 
@@ -1413,10 +1520,6 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
                return -EINVAL;
 
        vni = nla_get_u32(data[IFLA_VXLAN_ID]);
-       if (vxlan_find_vni(net, vni)) {
-               pr_info("duplicate VNI %u\n", vni);
-               return -EEXIST;
-       }
        dst->remote_vni = vni;
 
        if (data[IFLA_VXLAN_GROUP])
@@ -1482,22 +1585,58 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
        if (data[IFLA_VXLAN_PORT])
                vxlan->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]);
 
+       if (vxlan_find_vni(net, vni, vxlan->dst_port)) {
+               pr_info("duplicate VNI %u\n", vni);
+               return -EEXIST;
+       }
+
+       vs = vxlan_find_port(net, vxlan->dst_port);
+       if (vs)
+               ++vs->refcnt;
+       else {
+               /* Drop lock because socket create acquires RTNL lock */
+               rtnl_unlock();
+               vs = vxlan_socket_create(net, vxlan->dst_port);
+               rtnl_lock();
+               if (IS_ERR(vs))
+                       return PTR_ERR(vs);
+
+               hlist_add_head_rcu(&vs->hlist, vs_head(net, vxlan->dst_port));
+       }
+       vxlan->vn_sock = vs;
+
        SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops);
 
        err = register_netdevice(dev);
-       if (!err)
-               hlist_add_head_rcu(&vxlan->hlist, vni_head(net, dst->remote_vni));
+       if (err) {
+               if (--vs->refcnt == 0) {
+                       rtnl_unlock();
+                       sk_release_kernel(vs->sock->sk);
+                       kfree(vs);
+                       rtnl_lock();
+               }
+               return err;
+       }
 
-       return err;
+       list_add(&vxlan->next, &vn->vxlan_list);
+       hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni));
+
+       return 0;
 }
 
 static void vxlan_dellink(struct net_device *dev, struct list_head *head)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct vxlan_sock *vs = vxlan->vn_sock;
 
        hlist_del_rcu(&vxlan->hlist);
-
+       list_del(&vxlan->next);
        unregister_netdevice_queue(dev, head);
+
+       if (--vs->refcnt == 0) {
+               hlist_del_rcu(&vs->hlist);
+               schedule_work(&vs->del_work);
+       }
 }
 
 static size_t vxlan_get_size(const struct net_device *dev)
@@ -1583,46 +1722,12 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = {
 static __net_init int vxlan_init_net(struct net *net)
 {
        struct vxlan_net *vn = net_generic(net, vxlan_net_id);
-       struct sock *sk;
-       struct sockaddr_in vxlan_addr = {
-               .sin_family = AF_INET,
-               .sin_addr.s_addr = htonl(INADDR_ANY),
-       };
-       int rc;
-       unsigned h;
-
-       /* Create UDP socket for encapsulation receive. */
-       rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vn->sock);
-       if (rc < 0) {
-               pr_debug("UDP socket create failed\n");
-               return rc;
-       }
-       /* Put in proper namespace */
-       sk = vn->sock->sk;
-       sk_change_net(sk, net);
-
-       vxlan_addr.sin_port = htons(vxlan_port);
-
-       rc = kernel_bind(vn->sock, (struct sockaddr *) &vxlan_addr,
-                        sizeof(vxlan_addr));
-       if (rc < 0) {
-               pr_debug("bind for UDP socket %pI4:%u (%d)\n",
-                        &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc);
-               sk_release_kernel(sk);
-               vn->sock = NULL;
-               return rc;
-       }
+       unsigned int h;
 
-       /* Disable multicast loopback */
-       inet_sk(sk)->mc_loop = 0;
+       INIT_LIST_HEAD(&vn->vxlan_list);
 
-       /* Mark socket as an encapsulation socket. */
-       udp_sk(sk)->encap_type = 1;
-       udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv;
-       udp_encap_enable();
-
-       for (h = 0; h < VNI_HASH_SIZE; ++h)
-               INIT_HLIST_HEAD(&vn->vni_list[h]);
+       for (h = 0; h < PORT_HASH_SIZE; ++h)
+               INIT_HLIST_HEAD(&vn->sock_list[h]);
 
        return 0;
 }
@@ -1631,18 +1736,11 @@ static __net_exit void vxlan_exit_net(struct net *net)
 {
        struct vxlan_net *vn = net_generic(net, vxlan_net_id);
        struct vxlan_dev *vxlan;
-       unsigned h;
 
        rtnl_lock();
-       for (h = 0; h < VNI_HASH_SIZE; ++h)
-               hlist_for_each_entry(vxlan, &vn->vni_list[h], hlist)
-                       dev_close(vxlan->dev);
+       list_for_each_entry(vxlan, &vn->vxlan_list, next)
+               dev_close(vxlan->dev);
        rtnl_unlock();
-
-       if (vn->sock) {
-               sk_release_kernel(vn->sock->sk);
-               vn->sock = NULL;
-       }
 }
 
 static struct pernet_operations vxlan_net_ops = {
@@ -1673,7 +1771,7 @@ out2:
 out1:
        return rc;
 }
-module_init(vxlan_init_module);
+late_initcall(vxlan_init_module);
 
 static void __exit vxlan_cleanup_module(void)
 {
index 147614ed86aa8ae5d4a8a5451304337a70bb0960..70ac59929f800af871f422a4a18b91102e4e78df 100644 (file)
@@ -477,7 +477,7 @@ static void dlci_setup(struct net_device *dev)
 static int dlci_dev_event(struct notifier_block *unused,
                          unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *) ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (dev_net(dev) != &init_net)
                return NOTIFY_DONE;
index a0a932c63d0a29e367daad9febe6ccf7f6370f3d..9c33ca918e19f7c03bc66ee8aff4b5365ec031eb 100644 (file)
@@ -99,7 +99,7 @@ static inline void hdlc_proto_stop(struct net_device *dev)
 static int hdlc_device_event(struct notifier_block *this, unsigned long event,
                             void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        hdlc_device *hdlc;
        unsigned long flags;
        int on;
index fc9d11d74d605de87107d9b8642732dd1944f7da..e7bbdb7af53ac7dcbdd21d12705613054efe8626 100644 (file)
@@ -1384,7 +1384,6 @@ static int hss_remove_one(struct platform_device *pdev)
        unregister_hdlc_device(port->netdev);
        free_netdev(port->netdev);
        npe_release(port->npe);
-       platform_set_drvdata(pdev, NULL);
        kfree(port);
        return 0;
 }
index a73b49eb87e37a150c6096299a08460ad921d32d..a33a46fa88dd0216871502622a0f06b976ac94d5 100644 (file)
@@ -370,7 +370,7 @@ static int lapbeth_device_event(struct notifier_block *this,
                                unsigned long event, void *ptr)
 {
        struct lapbethdev *lapbeth;
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (dev_net(dev) != &init_net)
                return NOTIFY_DONE;
index 8e8bcc7a4805914ba64888ea683c13b3b76ddb0a..e9bc9e616b69c94e4c6758ae2c2327768778b942 100644 (file)
@@ -185,7 +185,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
 
  err_free_hw:
        ieee80211_free_hw(hw);
-       platform_set_drvdata(pdev, NULL);
  err_iounmap:
         iounmap(mem);
  err_out:
@@ -221,7 +220,6 @@ static int ath_ahb_remove(struct platform_device *pdev)
 
        ath5k_deinit_ah(ah);
        iounmap(ah->iobase);
-       platform_set_drvdata(pdev, NULL);
        ieee80211_free_hw(hw);
 
        return 0;
index d1ff3c246a1232cd1be306fbddce97df9a3d0d28..072e4b53106765ce8e0d6c833652501a7abde62d 100644 (file)
@@ -150,7 +150,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
        free_irq(irq, sc);
  err_free_hw:
        ieee80211_free_hw(hw);
-       platform_set_drvdata(pdev, NULL);
        return ret;
 }
 
@@ -164,7 +163,6 @@ static int ath_ahb_remove(struct platform_device *pdev)
                ath9k_deinit_device(sc);
                free_irq(sc->irq, sc);
                ieee80211_free_hw(sc->hw);
-               platform_set_drvdata(pdev, NULL);
        }
 
        return 0;
index b37eb8d38811587a72bd575805c40c0680387c3f..51cc0fa5cd3e4f3bb2b351ac780d8228e9a64685 100644 (file)
@@ -69,7 +69,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
                return -EFAULT;
 
        buf[len] = '\0';
-       if (strict_strtoul(buf, 0, &mask))
+       if (kstrtoul(buf, 0, &mask))
                return -EINVAL;
 
        common->debug_mask = mask;
@@ -114,7 +114,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
                return -EFAULT;
 
        buf[len] = '\0';
-       if (strict_strtoul(buf, 0, &mask))
+       if (kstrtoul(buf, 0, &mask))
                return -EINVAL;
 
        ah->txchainmask = mask;
@@ -157,7 +157,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
                return -EFAULT;
 
        buf[len] = '\0';
-       if (strict_strtoul(buf, 0, &mask))
+       if (kstrtoul(buf, 0, &mask))
                return -EINVAL;
 
        ah->rxchainmask = mask;
@@ -200,7 +200,7 @@ static ssize_t write_file_disable_ani(struct file *file,
                return -EFAULT;
 
        buf[len] = '\0';
-       if (strict_strtoul(buf, 0, &disable_ani))
+       if (kstrtoul(buf, 0, &disable_ani))
                return -EINVAL;
 
        common->disable_ani = !!disable_ani;
@@ -253,7 +253,7 @@ static ssize_t write_file_ant_diversity(struct file *file,
                goto exit;
 
        buf[len] = '\0';
-       if (strict_strtoul(buf, 0, &antenna_diversity))
+       if (kstrtoul(buf, 0, &antenna_diversity))
                return -EINVAL;
 
        common->antenna_diversity = !!antenna_diversity;
@@ -1278,7 +1278,7 @@ static ssize_t write_file_regidx(struct file *file, const char __user *user_buf,
                return -EFAULT;
 
        buf[len] = '\0';
-       if (strict_strtoul(buf, 0, &regidx))
+       if (kstrtoul(buf, 0, &regidx))
                return -EINVAL;
 
        sc->debug.regidx = regidx;
@@ -1323,7 +1323,7 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf,
                return -EFAULT;
 
        buf[len] = '\0';
-       if (strict_strtoul(buf, 0, &regval))
+       if (kstrtoul(buf, 0, &regval))
                return -EINVAL;
 
        ath9k_ps_wakeup(sc);
index b7611b7bbe437e289bd5f452c5cdf6d125a6c702..3c6e4138a95d13405ed8b2cff14ffbd5a2f52bb5 100644 (file)
@@ -96,7 +96,7 @@ static ssize_t write_file_dfs(struct file *file, const char __user *user_buf,
                return -EFAULT;
 
        buf[len] = '\0';
-       if (strict_strtoul(buf, 0, &val))
+       if (kstrtoul(buf, 0, &val))
                return -EINVAL;
 
        if (val == DFS_STATS_RESET_MAGIC)
index 87110de577effcafa57cbfba7adad21b67bc2973..d08ef24e969686bd379468fde063e5cb2be0e8d6 100644 (file)
@@ -471,7 +471,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
                return -EFAULT;
 
        buf[len] = '\0';
-       if (strict_strtoul(buf, 0, &mask))
+       if (kstrtoul(buf, 0, &mask))
                return -EINVAL;
 
        common->debug_mask = mask;
index b37a582ccbe7872eca2e5f5f8da14abe32f335e1..dce5e8f030b275ac61b3bf195d6537093ead49b2 100644 (file)
@@ -3119,7 +3119,7 @@ il3945_store_debug_level(struct device *d, struct device_attribute *attr,
        unsigned long val;
        int ret;
 
-       ret = strict_strtoul(buf, 0, &val);
+       ret = kstrtoul(buf, 0, &val);
        if (ret)
                IL_INFO("%s is not in hex or decimal form.\n", buf);
        else
index 9a95045c97b6b4fe6041f457a1999ecfb7926d12..3c4899b7c1ab8c393219abe661960007e132cb4c 100644 (file)
@@ -4567,7 +4567,7 @@ il4965_store_debug_level(struct device *d, struct device_attribute *attr,
        unsigned long val;
        int ret;
 
-       ret = strict_strtoul(buf, 0, &val);
+       ret = kstrtoul(buf, 0, &val);
        if (ret)
                IL_ERR("%s is not in hex or decimal form.\n", buf);
        else
@@ -4614,7 +4614,7 @@ il4965_store_tx_power(struct device *d, struct device_attribute *attr,
        unsigned long val;
        int ret;
 
-       ret = strict_strtoul(buf, 10, &val);
+       ret = kstrtoul(buf, 10, &val);
        if (ret)
                IL_INFO("%s is not in decimal form.\n", buf);
        else {
index 3e81264db81e937d25b3dda0a5fb7543d4c4379e..efae07e05c807cf12fe9081723377eb9bc895e81 100644 (file)
@@ -240,7 +240,7 @@ static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
        memset(&mesh_access, 0, sizeof(mesh_access));
        mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
 
-       if (!strict_strtoul(buf, 10, &retry_limit))
+       if (!kstrtoul(buf, 10, &retry_limit))
                return -ENOTSUPP;
        if (retry_limit > 15)
                return -ENOTSUPP;
index af59dd5718e1b90eab623b8b04bf94b0332fce45..8053f775d392d68479fb996dd4ac5582a99691b4 100644 (file)
@@ -1817,7 +1817,7 @@ static ssize_t rtl_store_debug_level(struct device *d,
        unsigned long val;
        int ret;
 
-       ret = strict_strtoul(buf, 0, &val);
+       ret = kstrtoul(buf, 0, &val);
        if (ret) {
                printk(KERN_DEBUG "%s is not in hex or decimal form.\n", buf);
        } else {
index 9d7f1723dd8f750126337d7792a0614fea8ca601..8a4d77ee9c5b61a312c3f2142ffa42fc0671e122 100644 (file)
@@ -57,8 +57,12 @@ struct xenvif {
 
        u8               fe_dev_addr[6];
 
-       /* Physical parameters of the comms window. */
-       unsigned int     irq;
+       /* When feature-split-event-channels = 0, tx_irq = rx_irq. */
+       unsigned int tx_irq;
+       unsigned int rx_irq;
+       /* Only used when feature-split-event-channels = 1 */
+       char tx_irq_name[IFNAMSIZ+4]; /* DEVNAME-tx */
+       char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */
 
        /* List of frontends to notify after a batch of frames sent. */
        struct list_head notify_list;
@@ -113,13 +117,15 @@ struct xenvif *xenvif_alloc(struct device *parent,
                            unsigned int handle);
 
 int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
-                  unsigned long rx_ring_ref, unsigned int evtchn);
+                  unsigned long rx_ring_ref, unsigned int tx_evtchn,
+                  unsigned int rx_evtchn);
 void xenvif_disconnect(struct xenvif *vif);
 
 void xenvif_get(struct xenvif *vif);
 void xenvif_put(struct xenvif *vif);
 
 int xenvif_xenbus_init(void);
+void xenvif_xenbus_fini(void);
 
 int xenvif_schedulable(struct xenvif *vif);
 
@@ -157,4 +163,6 @@ void xenvif_carrier_off(struct xenvif *vif);
 /* Returns number of ring slots required to send an skb to the frontend */
 unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb);
 
+extern bool separate_tx_rx_irq;
+
 #endif /* __XEN_NETBACK__COMMON_H__ */
index d984141684857c1708085af50ad8fed208a06f85..087d2db0389d04efc3368a0ba48a925a3b070124 100644 (file)
@@ -60,21 +60,39 @@ static int xenvif_rx_schedulable(struct xenvif *vif)
        return xenvif_schedulable(vif) && !xen_netbk_rx_ring_full(vif);
 }
 
-static irqreturn_t xenvif_interrupt(int irq, void *dev_id)
+static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id)
 {
        struct xenvif *vif = dev_id;
 
        if (vif->netbk == NULL)
-               return IRQ_NONE;
+               return IRQ_HANDLED;
 
        xen_netbk_schedule_xenvif(vif);
 
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
+{
+       struct xenvif *vif = dev_id;
+
+       if (vif->netbk == NULL)
+               return IRQ_HANDLED;
+
        if (xenvif_rx_schedulable(vif))
                netif_wake_queue(vif->dev);
 
        return IRQ_HANDLED;
 }
 
+static irqreturn_t xenvif_interrupt(int irq, void *dev_id)
+{
+       xenvif_tx_interrupt(irq, dev_id);
+       xenvif_rx_interrupt(irq, dev_id);
+
+       return IRQ_HANDLED;
+}
+
 static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct xenvif *vif = netdev_priv(dev);
@@ -125,13 +143,17 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
 static void xenvif_up(struct xenvif *vif)
 {
        xen_netbk_add_xenvif(vif);
-       enable_irq(vif->irq);
+       enable_irq(vif->tx_irq);
+       if (vif->tx_irq != vif->rx_irq)
+               enable_irq(vif->rx_irq);
        xen_netbk_check_rx_xenvif(vif);
 }
 
 static void xenvif_down(struct xenvif *vif)
 {
-       disable_irq(vif->irq);
+       disable_irq(vif->tx_irq);
+       if (vif->tx_irq != vif->rx_irq)
+               disable_irq(vif->rx_irq);
        del_timer_sync(&vif->credit_timeout);
        xen_netbk_deschedule_xenvif(vif);
        xen_netbk_remove_xenvif(vif);
@@ -308,25 +330,52 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 }
 
 int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
-                  unsigned long rx_ring_ref, unsigned int evtchn)
+                  unsigned long rx_ring_ref, unsigned int tx_evtchn,
+                  unsigned int rx_evtchn)
 {
        int err = -ENOMEM;
 
        /* Already connected through? */
-       if (vif->irq)
+       if (vif->tx_irq)
                return 0;
 
+       __module_get(THIS_MODULE);
+
        err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
        if (err < 0)
                goto err;
 
-       err = bind_interdomain_evtchn_to_irqhandler(
-               vif->domid, evtchn, xenvif_interrupt, 0,
-               vif->dev->name, vif);
-       if (err < 0)
-               goto err_unmap;
-       vif->irq = err;
-       disable_irq(vif->irq);
+       if (tx_evtchn == rx_evtchn) {
+               /* feature-split-event-channels == 0 */
+               err = bind_interdomain_evtchn_to_irqhandler(
+                       vif->domid, tx_evtchn, xenvif_interrupt, 0,
+                       vif->dev->name, vif);
+               if (err < 0)
+                       goto err_unmap;
+               vif->tx_irq = vif->rx_irq = err;
+               disable_irq(vif->tx_irq);
+       } else {
+               /* feature-split-event-channels == 1 */
+               snprintf(vif->tx_irq_name, sizeof(vif->tx_irq_name),
+                        "%s-tx", vif->dev->name);
+               err = bind_interdomain_evtchn_to_irqhandler(
+                       vif->domid, tx_evtchn, xenvif_tx_interrupt, 0,
+                       vif->tx_irq_name, vif);
+               if (err < 0)
+                       goto err_unmap;
+               vif->tx_irq = err;
+               disable_irq(vif->tx_irq);
+
+               snprintf(vif->rx_irq_name, sizeof(vif->rx_irq_name),
+                        "%s-rx", vif->dev->name);
+               err = bind_interdomain_evtchn_to_irqhandler(
+                       vif->domid, rx_evtchn, xenvif_rx_interrupt, 0,
+                       vif->rx_irq_name, vif);
+               if (err < 0)
+                       goto err_tx_unbind;
+               vif->rx_irq = err;
+               disable_irq(vif->rx_irq);
+       }
 
        xenvif_get(vif);
 
@@ -340,9 +389,13 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
        rtnl_unlock();
 
        return 0;
+err_tx_unbind:
+       unbind_from_irqhandler(vif->tx_irq, vif);
+       vif->tx_irq = 0;
 err_unmap:
        xen_netbk_unmap_frontend_rings(vif);
 err:
+       module_put(THIS_MODULE);
        return err;
 }
 
@@ -360,18 +413,37 @@ void xenvif_carrier_off(struct xenvif *vif)
 
 void xenvif_disconnect(struct xenvif *vif)
 {
+       /* Disconnect funtion might get called by generic framework
+        * even before vif connects, so we need to check if we really
+        * need to do a module_put.
+        */
+       int need_module_put = 0;
+
        if (netif_carrier_ok(vif->dev))
                xenvif_carrier_off(vif);
 
        atomic_dec(&vif->refcnt);
        wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0);
 
-       if (vif->irq)
-               unbind_from_irqhandler(vif->irq, vif);
+       if (vif->tx_irq) {
+               if (vif->tx_irq == vif->rx_irq)
+                       unbind_from_irqhandler(vif->tx_irq, vif);
+               else {
+                       unbind_from_irqhandler(vif->tx_irq, vif);
+                       unbind_from_irqhandler(vif->rx_irq, vif);
+               }
+               /* vif->irq is valid, we had a module_get in
+                * xenvif_connect.
+                */
+               need_module_put = 1;
+       }
 
        unregister_netdev(vif->dev);
 
        xen_netbk_unmap_frontend_rings(vif);
 
        free_netdev(vif->dev);
+
+       if (need_module_put)
+               module_put(THIS_MODULE);
 }
index 37984e6d4e99f9d81dddd760e01ac416010bdea8..82576fffb4526a9964cd4f5074e77770bbb7373b 100644 (file)
 #include <asm/xen/hypercall.h>
 #include <asm/xen/page.h>
 
+/* Provide an option to disable split event channels at load time as
+ * event channels are limited resource. Split event channels are
+ * enabled by default.
+ */
+bool separate_tx_rx_irq = 1;
+module_param(separate_tx_rx_irq, bool, 0644);
+
 /*
  * This is the maximum slots a skb can have. If a guest sends a skb
  * which exceeds this limit it is considered malicious.
@@ -662,7 +669,7 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk)
 {
        struct xenvif *vif = NULL, *tmp;
        s8 status;
-       u16 irq, flags;
+       u16 flags;
        struct xen_netif_rx_response *resp;
        struct sk_buff_head rxq;
        struct sk_buff *skb;
@@ -771,7 +778,6 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk)
                                         sco->meta_slots_used);
 
                RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->rx, ret);
-               irq = vif->irq;
                if (ret && list_empty(&vif->notify_list))
                        list_add_tail(&vif->notify_list, &notify);
 
@@ -783,7 +789,7 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk)
        }
 
        list_for_each_entry_safe(vif, tmp, &notify, notify_list) {
-               notify_remote_via_irq(vif->irq);
+               notify_remote_via_irq(vif->rx_irq);
                list_del_init(&vif->notify_list);
        }
 
@@ -1762,7 +1768,7 @@ static void make_tx_response(struct xenvif *vif,
        vif->tx.rsp_prod_pvt = ++i;
        RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->tx, notify);
        if (notify)
-               notify_remote_via_irq(vif->irq);
+               notify_remote_via_irq(vif->tx_irq);
 }
 
 static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
@@ -1939,10 +1945,6 @@ static int __init netback_init(void)
 failed_init:
        while (--group >= 0) {
                struct xen_netbk *netbk = &xen_netbk[group];
-               for (i = 0; i < MAX_PENDING_REQS; i++) {
-                       if (netbk->mmap_pages[i])
-                               __free_page(netbk->mmap_pages[i]);
-               }
                del_timer(&netbk->net_timer);
                kthread_stop(netbk->task);
        }
@@ -1953,5 +1955,25 @@ failed_init:
 
 module_init(netback_init);
 
+static void __exit netback_fini(void)
+{
+       int i, j;
+
+       xenvif_xenbus_fini();
+
+       for (i = 0; i < xen_netbk_group_nr; i++) {
+               struct xen_netbk *netbk = &xen_netbk[i];
+               del_timer_sync(&netbk->net_timer);
+               kthread_stop(netbk->task);
+               for (j = 0; j < MAX_PENDING_REQS; j++) {
+                       if (netbk->mmap_pages[i])
+                               __free_page(netbk->mmap_pages[i]);
+               }
+       }
+
+       vfree(xen_netbk);
+}
+module_exit(netback_fini);
+
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_ALIAS("xen-backend:vif");
index 410018c4c52818f0b3a697d64e4300a505825f91..04bd860d16a9c29afb6458906529d3f38aa6d72f 100644 (file)
@@ -122,6 +122,16 @@ static int netback_probe(struct xenbus_device *dev,
                goto fail;
        }
 
+       /*
+        * Split event channels support, this is optional so it is not
+        * put inside the above loop.
+        */
+       err = xenbus_printf(XBT_NIL, dev->nodename,
+                           "feature-split-event-channels",
+                           "%u", separate_tx_rx_irq);
+       if (err)
+               pr_debug("Error writing feature-split-event-channels");
+
        err = xenbus_switch_state(dev, XenbusStateInitWait);
        if (err)
                goto fail;
@@ -393,21 +403,36 @@ static int connect_rings(struct backend_info *be)
        struct xenvif *vif = be->vif;
        struct xenbus_device *dev = be->dev;
        unsigned long tx_ring_ref, rx_ring_ref;
-       unsigned int evtchn, rx_copy;
+       unsigned int tx_evtchn, rx_evtchn, rx_copy;
        int err;
        int val;
 
        err = xenbus_gather(XBT_NIL, dev->otherend,
                            "tx-ring-ref", "%lu", &tx_ring_ref,
-                           "rx-ring-ref", "%lu", &rx_ring_ref,
-                           "event-channel", "%u", &evtchn, NULL);
+                           "rx-ring-ref", "%lu", &rx_ring_ref, NULL);
        if (err) {
                xenbus_dev_fatal(dev, err,
-                                "reading %s/ring-ref and event-channel",
+                                "reading %s/ring-ref",
                                 dev->otherend);
                return err;
        }
 
+       /* Try split event channels first, then single event channel. */
+       err = xenbus_gather(XBT_NIL, dev->otherend,
+                           "event-channel-tx", "%u", &tx_evtchn,
+                           "event-channel-rx", "%u", &rx_evtchn, NULL);
+       if (err < 0) {
+               err = xenbus_scanf(XBT_NIL, dev->otherend,
+                                  "event-channel", "%u", &tx_evtchn);
+               if (err < 0) {
+                       xenbus_dev_fatal(dev, err,
+                                        "reading %s/event-channel(-tx/rx)",
+                                        dev->otherend);
+                       return err;
+               }
+               rx_evtchn = tx_evtchn;
+       }
+
        err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
                           &rx_copy);
        if (err == -ENOENT) {
@@ -454,11 +479,13 @@ static int connect_rings(struct backend_info *be)
        vif->csum = !val;
 
        /* Map the shared frame, irq etc. */
-       err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref, evtchn);
+       err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref,
+                            tx_evtchn, rx_evtchn);
        if (err) {
                xenbus_dev_fatal(dev, err,
-                                "mapping shared-frames %lu/%lu port %u",
-                                tx_ring_ref, rx_ring_ref, evtchn);
+                                "mapping shared-frames %lu/%lu port tx %u rx %u",
+                                tx_ring_ref, rx_ring_ref,
+                                tx_evtchn, rx_evtchn);
                return err;
        }
        return 0;
@@ -485,3 +512,8 @@ int xenvif_xenbus_init(void)
 {
        return xenbus_register_backend(&netback_driver);
 }
+
+void xenvif_xenbus_fini(void)
+{
+       return xenbus_unregister_driver(&netback_driver);
+}
index 1db101415069726fc59d26443f773fc0432f52a6..62238a08cb517e6ed30d8df58c33c49dcf95286b 100644 (file)
@@ -85,7 +85,15 @@ struct netfront_info {
 
        struct napi_struct napi;
 
-       unsigned int evtchn;
+       /* Split event channels support, tx_* == rx_* when using
+        * single event channel.
+        */
+       unsigned int tx_evtchn, rx_evtchn;
+       unsigned int tx_irq, rx_irq;
+       /* Only used when split event channels support is enabled */
+       char tx_irq_name[IFNAMSIZ+4]; /* DEVNAME-tx */
+       char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */
+
        struct xenbus_device *xbdev;
 
        spinlock_t   tx_lock;
@@ -330,7 +338,7 @@ no_skb:
  push:
        RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
        if (notify)
-               notify_remote_via_irq(np->netdev->irq);
+               notify_remote_via_irq(np->rx_irq);
 }
 
 static int xennet_open(struct net_device *dev)
@@ -623,7 +631,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify);
        if (notify)
-               notify_remote_via_irq(np->netdev->irq);
+               notify_remote_via_irq(np->tx_irq);
 
        u64_stats_update_begin(&stats->syncp);
        stats->tx_bytes += skb->len;
@@ -1254,23 +1262,35 @@ static int xennet_set_features(struct net_device *dev,
        return 0;
 }
 
-static irqreturn_t xennet_interrupt(int irq, void *dev_id)
+static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id)
 {
-       struct net_device *dev = dev_id;
-       struct netfront_info *np = netdev_priv(dev);
+       struct netfront_info *np = dev_id;
+       struct net_device *dev = np->netdev;
        unsigned long flags;
 
        spin_lock_irqsave(&np->tx_lock, flags);
+       xennet_tx_buf_gc(dev);
+       spin_unlock_irqrestore(&np->tx_lock, flags);
 
-       if (likely(netif_carrier_ok(dev))) {
-               xennet_tx_buf_gc(dev);
-               /* Under tx_lock: protects access to rx shared-ring indexes. */
-               if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id)
+{
+       struct netfront_info *np = dev_id;
+       struct net_device *dev = np->netdev;
+
+       if (likely(netif_carrier_ok(dev) &&
+                  RING_HAS_UNCONSUMED_RESPONSES(&np->rx)))
                        napi_schedule(&np->napi);
-       }
 
-       spin_unlock_irqrestore(&np->tx_lock, flags);
+       return IRQ_HANDLED;
+}
 
+static irqreturn_t xennet_interrupt(int irq, void *dev_id)
+{
+       xennet_tx_interrupt(irq, dev_id);
+       xennet_rx_interrupt(irq, dev_id);
        return IRQ_HANDLED;
 }
 
@@ -1451,9 +1471,14 @@ static void xennet_disconnect_backend(struct netfront_info *info)
        spin_unlock_irq(&info->tx_lock);
        spin_unlock_bh(&info->rx_lock);
 
-       if (info->netdev->irq)
-               unbind_from_irqhandler(info->netdev->irq, info->netdev);
-       info->evtchn = info->netdev->irq = 0;
+       if (info->tx_irq && (info->tx_irq == info->rx_irq))
+               unbind_from_irqhandler(info->tx_irq, info);
+       if (info->tx_irq && (info->tx_irq != info->rx_irq)) {
+               unbind_from_irqhandler(info->tx_irq, info);
+               unbind_from_irqhandler(info->rx_irq, info);
+       }
+       info->tx_evtchn = info->rx_evtchn = 0;
+       info->tx_irq = info->rx_irq = 0;
 
        /* End access and free the pages */
        xennet_end_access(info->tx_ring_ref, info->tx.sring);
@@ -1503,12 +1528,82 @@ static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
        return 0;
 }
 
+static int setup_netfront_single(struct netfront_info *info)
+{
+       int err;
+
+       err = xenbus_alloc_evtchn(info->xbdev, &info->tx_evtchn);
+       if (err < 0)
+               goto fail;
+
+       err = bind_evtchn_to_irqhandler(info->tx_evtchn,
+                                       xennet_interrupt,
+                                       0, info->netdev->name, info);
+       if (err < 0)
+               goto bind_fail;
+       info->rx_evtchn = info->tx_evtchn;
+       info->rx_irq = info->tx_irq = err;
+
+       return 0;
+
+bind_fail:
+       xenbus_free_evtchn(info->xbdev, info->tx_evtchn);
+       info->tx_evtchn = 0;
+fail:
+       return err;
+}
+
+static int setup_netfront_split(struct netfront_info *info)
+{
+       int err;
+
+       err = xenbus_alloc_evtchn(info->xbdev, &info->tx_evtchn);
+       if (err < 0)
+               goto fail;
+       err = xenbus_alloc_evtchn(info->xbdev, &info->rx_evtchn);
+       if (err < 0)
+               goto alloc_rx_evtchn_fail;
+
+       snprintf(info->tx_irq_name, sizeof(info->tx_irq_name),
+                "%s-tx", info->netdev->name);
+       err = bind_evtchn_to_irqhandler(info->tx_evtchn,
+                                       xennet_tx_interrupt,
+                                       0, info->tx_irq_name, info);
+       if (err < 0)
+               goto bind_tx_fail;
+       info->tx_irq = err;
+
+       snprintf(info->rx_irq_name, sizeof(info->rx_irq_name),
+                "%s-rx", info->netdev->name);
+       err = bind_evtchn_to_irqhandler(info->rx_evtchn,
+                                       xennet_rx_interrupt,
+                                       0, info->rx_irq_name, info);
+       if (err < 0)
+               goto bind_rx_fail;
+       info->rx_irq = err;
+
+       return 0;
+
+bind_rx_fail:
+       unbind_from_irqhandler(info->tx_irq, info);
+       info->tx_irq = 0;
+bind_tx_fail:
+       xenbus_free_evtchn(info->xbdev, info->rx_evtchn);
+       info->rx_evtchn = 0;
+alloc_rx_evtchn_fail:
+       xenbus_free_evtchn(info->xbdev, info->tx_evtchn);
+       info->tx_evtchn = 0;
+fail:
+       return err;
+}
+
 static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
 {
        struct xen_netif_tx_sring *txs;
        struct xen_netif_rx_sring *rxs;
        int err;
        struct net_device *netdev = info->netdev;
+       unsigned int feature_split_evtchn;
 
        info->tx_ring_ref = GRANT_INVALID_REF;
        info->rx_ring_ref = GRANT_INVALID_REF;
@@ -1516,6 +1611,12 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
        info->tx.sring = NULL;
        netdev->irq = 0;
 
+       err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+                          "feature-split-event-channels", "%u",
+                          &feature_split_evtchn);
+       if (err < 0)
+               feature_split_evtchn = 0;
+
        err = xen_net_read_mac(dev, netdev->dev_addr);
        if (err) {
                xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
@@ -1532,40 +1633,50 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
        FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
 
        err = xenbus_grant_ring(dev, virt_to_mfn(txs));
-       if (err < 0) {
-               free_page((unsigned long)txs);
-               goto fail;
-       }
+       if (err < 0)
+               goto grant_tx_ring_fail;
 
        info->tx_ring_ref = err;
        rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
        if (!rxs) {
                err = -ENOMEM;
                xenbus_dev_fatal(dev, err, "allocating rx ring page");
-               goto fail;
+               goto alloc_rx_ring_fail;
        }
        SHARED_RING_INIT(rxs);
        FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
 
        err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
-       if (err < 0) {
-               free_page((unsigned long)rxs);
-               goto fail;
-       }
+       if (err < 0)
+               goto grant_rx_ring_fail;
        info->rx_ring_ref = err;
 
-       err = xenbus_alloc_evtchn(dev, &info->evtchn);
+       if (feature_split_evtchn)
+               err = setup_netfront_split(info);
+       /* setup single event channel if
+        *  a) feature-split-event-channels == 0
+        *  b) feature-split-event-channels == 1 but failed to setup
+        */
+       if (!feature_split_evtchn || (feature_split_evtchn && err))
+               err = setup_netfront_single(info);
+
        if (err)
-               goto fail;
+               goto alloc_evtchn_fail;
 
-       err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt,
-                                       0, netdev->name, netdev);
-       if (err < 0)
-               goto fail;
-       netdev->irq = err;
        return 0;
 
- fail:
+       /* If we fail to setup netfront, it is safe to just revoke access to
+        * granted pages because backend is not accessing it at this point.
+        */
+alloc_evtchn_fail:
+       gnttab_end_foreign_access_ref(info->rx_ring_ref, 0);
+grant_rx_ring_fail:
+       free_page((unsigned long)rxs);
+alloc_rx_ring_fail:
+       gnttab_end_foreign_access_ref(info->tx_ring_ref, 0);
+grant_tx_ring_fail:
+       free_page((unsigned long)txs);
+fail:
        return err;
 }
 
@@ -1601,11 +1712,27 @@ again:
                message = "writing rx ring-ref";
                goto abort_transaction;
        }
-       err = xenbus_printf(xbt, dev->nodename,
-                           "event-channel", "%u", info->evtchn);
-       if (err) {
-               message = "writing event-channel";
-               goto abort_transaction;
+
+       if (info->tx_evtchn == info->rx_evtchn) {
+               err = xenbus_printf(xbt, dev->nodename,
+                                   "event-channel", "%u", info->tx_evtchn);
+               if (err) {
+                       message = "writing event-channel";
+                       goto abort_transaction;
+               }
+       } else {
+               err = xenbus_printf(xbt, dev->nodename,
+                                   "event-channel-tx", "%u", info->tx_evtchn);
+               if (err) {
+                       message = "writing event-channel-tx";
+                       goto abort_transaction;
+               }
+               err = xenbus_printf(xbt, dev->nodename,
+                                   "event-channel-rx", "%u", info->rx_evtchn);
+               if (err) {
+                       message = "writing event-channel-rx";
+                       goto abort_transaction;
+               }
        }
 
        err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u",
@@ -1718,7 +1845,9 @@ static int xennet_connect(struct net_device *dev)
         * packets.
         */
        netif_carrier_on(np->netdev);
-       notify_remote_via_irq(np->netdev->irq);
+       notify_remote_via_irq(np->tx_irq);
+       if (np->tx_irq != np->rx_irq)
+               notify_remote_via_irq(np->rx_irq);
        xennet_tx_buf_gc(dev);
        xennet_alloc_rx_buffers(dev);
 
index ffab033d207e199113e4772e345c7968fc027744..ea174c8ee34b56502860f78f94ba61df48fe764e 100644 (file)
@@ -22,6 +22,7 @@ static const char *phy_modes[] = {
        [PHY_INTERFACE_MODE_GMII]       = "gmii",
        [PHY_INTERFACE_MODE_SGMII]      = "sgmii",
        [PHY_INTERFACE_MODE_TBI]        = "tbi",
+       [PHY_INTERFACE_MODE_REVMII]     = "rev-mii",
        [PHY_INTERFACE_MODE_RMII]       = "rmii",
        [PHY_INTERFACE_MODE_RGMII]      = "rgmii",
        [PHY_INTERFACE_MODE_RGMII_ID]   = "rgmii-id",
index 292b24f9bf935f119ab12dbbca96d5a00d16783d..ee721b6cbcdf891c4d08250e68ccfb9e82c6ceb2 100644 (file)
@@ -1975,7 +1975,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 {
        struct fcoe_ctlr_device *cdev;
        struct fc_lport *lport = NULL;
-       struct net_device *netdev = ptr;
+       struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
        struct fcoe_ctlr *ctlr;
        struct fcoe_interface *fcoe;
        struct fcoe_port *port;
index f3a5a53e863133203044814f892286704cf70630..01adbe0ec53b89af776957d1b4cc58038aae818a 100644 (file)
@@ -704,7 +704,7 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
 static int libfcoe_device_notification(struct notifier_block *notifier,
                                    ulong event, void *ptr)
 {
-       struct net_device *netdev = ptr;
+       struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
 
        switch (event) {
        case NETDEV_UNREGISTER:
index a3b23644b0fbb42218285c571656a8db2154517d..e753fbe302a750ffa3aa13d3f5b402ad9240a06d 100644 (file)
@@ -54,7 +54,7 @@ static int hex2sprom(u16 *sprom, const char *dump, size_t len,
        while (cnt < sprom_size_words) {
                memcpy(tmp, dump, 4);
                dump += 4;
-               err = strict_strtoul(tmp, 16, &parsed);
+               err = kstrtoul(tmp, 16, &parsed);
                if (err)
                        return err;
                sprom[cnt++] = swab16((u16)parsed);
index a0177d998978fe25524a333fc557bdada13d2c42..d49cdf84a496d405568024bd39c2f21577cab68f 100644 (file)
@@ -2891,7 +2891,7 @@ void uf_net_get_name(struct net_device *dev, char *name, int len)
  */
 static int
 uf_netdev_event(struct notifier_block *notif, unsigned long event, void* ptr) {
-    struct net_device *netdev = ptr;
+    struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(netdev);
     unifi_priv_t *priv = NULL;
     static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
index 94e426e4d98b0177b72065bf630c4eae1b490925..b2330f1df7e7066ab15aae5707a79f6fc7b32b2e 100644 (file)
@@ -164,7 +164,7 @@ static const struct file_operations ft1000_proc_fops = {
 static int ft1000NotifyProc(struct notifier_block *this, unsigned long event,
                                void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct ft1000_info *info;
 
        info = netdev_priv(dev);
index eca6f0292b4bcc9d2c9829cff401d5e0bd645ab8..5ead942be680c38962c251349033e44faec9c807 100644 (file)
@@ -166,7 +166,7 @@ static const struct file_operations ft1000_proc_fops = {
 static int
 ft1000NotifyProc(struct notifier_block *this, unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct ft1000_info *info;
        struct proc_dir_entry *ft1000_proc_file;
 
index b7e570ccb759dd4514a17206238b87dbe0299282..c8ddb99e852686205538a62dcc6fd3afe9688863 100644 (file)
@@ -133,7 +133,7 @@ static unsigned long str_to_hex(char *p);
 static int bp_device_event(struct notifier_block *unused,
                           unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        static bpctl_dev_t *pbpctl_dev = NULL, *pbpctl_dev_m = NULL;
        int dev_num = 0, ret = 0, ret_d = 0, time_left = 0;
        /* printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); */
index c050dcc322a43e2264bdaf49b3667a0b2e63c6ab..56a6b7fbb3c6f068020e6c37ebd997d8d04917a9 100644 (file)
@@ -58,10 +58,10 @@ extern void bpf_jit_free(struct sk_filter *fp);
 static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
                                u32 pass, void *image)
 {
-       pr_err("flen=%u proglen=%u pass=%u image=%p\n",
+       pr_err("flen=%u proglen=%u pass=%u image=%pK\n",
               flen, proglen, pass, image);
        if (image)
-               print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS,
+               print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_OFFSET,
                               16, 1, image, proglen, false);
 }
 #define SK_RUN_FILTER(FILTER, SKB) (*FILTER->bpf_func)(SKB, FILTER->insns)
index dd3c34ebca9a67e05c2e59649da81486210e802c..8e9a029e093d6522b68c0929aad93704f47c3ad5 100644 (file)
@@ -14,6 +14,8 @@
 #define MARVELL_PHY_ID_88E1149R                0x01410e50
 #define MARVELL_PHY_ID_88E1240         0x01410e30
 #define MARVELL_PHY_ID_88E1318S                0x01410e90
+#define MARVELL_PHY_ID_88E1116R                0x01410e40
+#define MARVELL_PHY_ID_88E1510         0x01410dd0
 
 /* struct phy_device dev_flags definitions */
 #define MARVELL_PHY_M1145_FLAGS_RESISTANCE     0x00000001
index 141d395bbb5f1a215483c90b2a10d5bd0bc58ff7..6e8215b159982378847cc7aacd75747da9c604d6 100644 (file)
@@ -30,6 +30,7 @@ struct mv643xx_eth_shared_platform_data {
 #define MV643XX_ETH_PHY_ADDR(x)                (0x80 | (x))
 #define MV643XX_ETH_PHY_NONE           0xff
 
+struct device_node;
 struct mv643xx_eth_platform_data {
        /*
         * Pointer back to our parent instance, and our port number.
@@ -41,6 +42,7 @@ struct mv643xx_eth_platform_data {
         * Whether a PHY is present, and if yes, at which address.
         */
        int                     phy_addr;
+       struct device_node      *phy_node;
 
        /*
         * Use this MAC address if it is valid, overriding the
index 99c9f0c103c23ccaab15e69fe6f684cd8e21c943..4f27575ce1d67ebe74d1bba4f40a70f6edbdea11 100644 (file)
@@ -79,9 +79,9 @@ enum sock_type {
 #endif /* ARCH_HAS_SOCKET_TYPES */
 
 enum sock_shutdown_cmd {
-       SHUT_RD         = 0,
-       SHUT_WR         = 1,
-       SHUT_RDWR       = 2,
+       SHUT_RD,
+       SHUT_WR,
+       SHUT_RDWR,
 };
 
 struct socket_wq {
index 09906b7ca47d605dec59a9e21232f68660974562..a2a89a5c7be55b15baec6271a8cc4329b6f642bd 100644 (file)
@@ -43,8 +43,9 @@ enum {
        NETIF_F_FSO_BIT,                /* ... FCoE segmentation */
        NETIF_F_GSO_GRE_BIT,            /* ... GRE with TSO */
        NETIF_F_GSO_UDP_TUNNEL_BIT,     /* ... UDP TUNNEL with TSO */
+       NETIF_F_GSO_MPLS_BIT,           /* ... MPLS segmentation */
        /**/NETIF_F_GSO_LAST =          /* last bit, see GSO_MASK */
-               NETIF_F_GSO_UDP_TUNNEL_BIT,
+               NETIF_F_GSO_MPLS_BIT,
 
        NETIF_F_FCOE_CRC_BIT,           /* FCoE CRC32 */
        NETIF_F_SCTP_CSUM_BIT,          /* SCTP checksum offload */
@@ -107,6 +108,7 @@ enum {
 #define NETIF_F_RXALL          __NETIF_F(RXALL)
 #define NETIF_F_GSO_GRE                __NETIF_F(GSO_GRE)
 #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
+#define NETIF_F_GSO_MPLS       __NETIF_F(GSO_MPLS)
 #define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
 #define NETIF_F_HW_VLAN_STAG_RX        __NETIF_F(HW_VLAN_STAG_RX)
 #define NETIF_F_HW_VLAN_STAG_TX        __NETIF_F(HW_VLAN_STAG_TX)
index 60584b185a0c5d4ad61ed0435982ad4287dea8fc..8f967e34142baf961a082ebcd43e1092883b227f 100644 (file)
@@ -1088,6 +1088,8 @@ struct net_device {
         * need to set them appropriately.
         */
        netdev_features_t       hw_enc_features;
+       /* mask of fetures inheritable by MPLS */
+       netdev_features_t       mpls_features;
 
        /* Interface index. Unique device identifier    */
        int                     ifindex;
@@ -1593,9 +1595,34 @@ struct packet_offload {
 #define NETDEV_RELEASE         0x0012
 #define NETDEV_NOTIFY_PEERS    0x0013
 #define NETDEV_JOIN            0x0014
+#define NETDEV_CHANGEUPPER     0x0015
 
 extern int register_netdevice_notifier(struct notifier_block *nb);
 extern int unregister_netdevice_notifier(struct notifier_block *nb);
+
+struct netdev_notifier_info {
+       struct net_device *dev;
+};
+
+struct netdev_notifier_change_info {
+       struct netdev_notifier_info info; /* must be first */
+       unsigned int flags_changed;
+};
+
+static inline void netdev_notifier_info_init(struct netdev_notifier_info *info,
+                                            struct net_device *dev)
+{
+       info->dev = dev;
+}
+
+static inline struct net_device *
+netdev_notifier_info_to_dev(const struct netdev_notifier_info *info)
+{
+       return info->dev;
+}
+
+extern int call_netdevice_notifiers_info(unsigned long val, struct net_device *dev,
+                                        struct netdev_notifier_info *info);
 extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
 
 
@@ -1778,6 +1805,19 @@ static inline int unregister_gifconf(unsigned int family)
        return register_gifconf(family, NULL);
 }
 
+#ifdef CONFIG_NET_FLOW_LIMIT
+#define FLOW_LIMIT_HISTORY     (1 << 8)        /* must be ^2 */
+struct sd_flow_limit {
+       u64                     count;
+       unsigned int            num_buckets;
+       unsigned int            history_head;
+       u16                     history[FLOW_LIMIT_HISTORY];
+       u8                      buckets[];
+};
+
+extern int netdev_flow_limit_table_len;
+#endif /* CONFIG_NET_FLOW_LIMIT */
+
 /*
  * Incoming packets are placed on per-cpu queues
  */
@@ -1807,6 +1847,10 @@ struct softnet_data {
        unsigned int            dropped;
        struct sk_buff_head     input_pkt_queue;
        struct napi_struct      backlog;
+
+#ifdef CONFIG_NET_FLOW_LIMIT
+       struct sd_flow_limit    *flow_limit;
+#endif
 };
 
 static inline void input_queue_head_incr(struct softnet_data *sd)
index fa2cb76a702933c1a6d03cc915e6f63c4a5dc0cf..f3c7c24bec1ca99c89270611d87f9c264c3eb786 100644 (file)
@@ -53,10 +53,10 @@ struct netpoll_info {
 };
 
 #ifdef CONFIG_NETPOLL
-extern int netpoll_rx_disable(struct net_device *dev);
+extern void netpoll_rx_disable(struct net_device *dev);
 extern void netpoll_rx_enable(struct net_device *dev);
 #else
-static inline int netpoll_rx_disable(struct net_device *dev) { return 0; }
+static inline void netpoll_rx_disable(struct net_device *dev) { return; }
 static inline void netpoll_rx_enable(struct net_device *dev) { return; }
 #endif
 
index 9e11039dd7a3b89c40a19d10ebb3c382aed5dd7e..64ab823f7b7451f77aa4b58df22b4a3a54c30db1 100644 (file)
@@ -49,6 +49,7 @@
 
 #define PHY_HAS_INTERRUPT      0x00000001
 #define PHY_HAS_MAGICANEG      0x00000002
+#define PHY_IS_INTERNAL                0x00000004
 
 /* Interface Mode definitions */
 typedef enum {
@@ -57,6 +58,7 @@ typedef enum {
        PHY_INTERFACE_MODE_GMII,
        PHY_INTERFACE_MODE_SGMII,
        PHY_INTERFACE_MODE_TBI,
+       PHY_INTERFACE_MODE_REVMII,
        PHY_INTERFACE_MODE_RMII,
        PHY_INTERFACE_MODE_RGMII,
        PHY_INTERFACE_MODE_RGMII_ID,
@@ -261,6 +263,7 @@ struct phy_c45_device_ids {
  * phy_id: UID for this device found during discovery
  * c45_ids: 802.3-c45 Device Identifers if is_c45.
  * is_c45:  Set to true if this phy uses clause 45 addressing.
+ * is_internal: Set to true if this phy is internal to a MAC.
  * state: state of the PHY for management purposes
  * dev_flags: Device-specific flags used by the PHY driver.
  * addr: Bus address of PHY
@@ -298,6 +301,7 @@ struct phy_device {
 
        struct phy_c45_device_ids c45_ids;
        bool is_c45;
+       bool is_internal;
 
        enum phy_state state;
 
@@ -508,6 +512,27 @@ static inline int phy_write(struct phy_device *phydev, u32 regnum, u16 val)
        return mdiobus_write(phydev->bus, phydev->addr, regnum, val);
 }
 
+/**
+ * phy_interrupt_is_valid - Convenience function for testing a given PHY irq
+ * @phydev: the phy_device struct
+ *
+ * NOTE: must be kept in sync with addition/removal of PHY_POLL and
+ * PHY_IGNORE_INTERRUPT
+ */
+static inline bool phy_interrupt_is_valid(struct phy_device *phydev)
+{
+       return phydev->irq != PHY_POLL && phydev->irq != PHY_IGNORE_INTERRUPT;
+}
+
+/**
+ * phy_is_internal - Convenience function for testing if a PHY is internal
+ * @phydev: the phy_device struct
+ */
+static inline bool phy_is_internal(struct phy_device *phydev)
+{
+       return phydev->is_internal;
+}
+
 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);
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
@@ -545,6 +570,8 @@ void phy_drivers_unregister(struct phy_driver *drv, int n);
 int phy_driver_register(struct phy_driver *new_driver);
 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_stop_machine(struct phy_device *phydev);
index 9c676eae396867fbcc656bc9466fe19459f31b2f..9995834d2cb6b4050c607250870abda56858843b 100644 (file)
@@ -319,6 +319,8 @@ enum {
        SKB_GSO_GRE = 1 << 6,
 
        SKB_GSO_UDP_TUNNEL = 1 << 7,
+
+       SKB_GSO_MPLS = 1 << 8,
 };
 
 #if BITS_PER_LONG > 32
@@ -389,6 +391,7 @@ typedef unsigned char *sk_buff_data_t;
  *     @dropcount: total number of sk_receive_queue overflows
  *     @vlan_proto: vlan encapsulation protocol
  *     @vlan_tci: vlan tag control information
+ *     @inner_protocol: Protocol (encapsulation)
  *     @inner_transport_header: Inner transport layer header (encapsulation)
  *     @inner_network_header: Network layer header (encapsulation)
  *     @inner_mac_header: Link layer header (encapsulation)
@@ -509,12 +512,13 @@ struct sk_buff {
                __u32           reserved_tailroom;
        };
 
-       sk_buff_data_t          inner_transport_header;
-       sk_buff_data_t          inner_network_header;
-       sk_buff_data_t          inner_mac_header;
-       sk_buff_data_t          transport_header;
-       sk_buff_data_t          network_header;
-       sk_buff_data_t          mac_header;
+       __be16                  inner_protocol;
+       __u16                   inner_transport_header;
+       __u16                   inner_network_header;
+       __u16                   inner_mac_header;
+       __u16                   transport_header;
+       __u16                   network_header;
+       __u16                   mac_header;
        /* These elements must be at the end, see alloc_skb() for details.  */
        sk_buff_data_t          tail;
        sk_buff_data_t          end;
@@ -1387,6 +1391,11 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
        skb_reset_tail_pointer(skb);
        skb->tail += offset;
 }
+
+static inline unsigned long skb_tail_offset(const struct sk_buff *skb)
+{
+       return skb->tail;
+}
 #else /* NET_SKBUFF_DATA_USES_OFFSET */
 static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
 {
@@ -1403,6 +1412,10 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
        skb->tail = skb->data + offset;
 }
 
+static inline unsigned long skb_tail_offset(const struct sk_buff *skb)
+{
+       return skb->tail - skb->head;
+}
 #endif /* NET_SKBUFF_DATA_USES_OFFSET */
 
 /*
@@ -1527,7 +1540,6 @@ static inline void skb_reset_mac_len(struct sk_buff *skb)
        skb->mac_len = skb->network_header - skb->mac_header;
 }
 
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
 static inline unsigned char *skb_inner_transport_header(const struct sk_buff
                                                        *skb)
 {
@@ -1581,7 +1593,7 @@ static inline void skb_set_inner_mac_header(struct sk_buff *skb,
 }
 static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
 {
-       return skb->transport_header != ~0U;
+       return skb->transport_header != (typeof(skb->transport_header))~0U;
 }
 
 static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
@@ -1624,7 +1636,7 @@ static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
 
 static inline int skb_mac_header_was_set(const struct sk_buff *skb)
 {
-       return skb->mac_header != ~0U;
+       return skb->mac_header != (typeof(skb->mac_header))~0U;
 }
 
 static inline void skb_reset_mac_header(struct sk_buff *skb)
@@ -1638,112 +1650,6 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
        skb->mac_header += offset;
 }
 
-#else /* NET_SKBUFF_DATA_USES_OFFSET */
-static inline unsigned char *skb_inner_transport_header(const struct sk_buff
-                                                       *skb)
-{
-       return skb->inner_transport_header;
-}
-
-static inline void skb_reset_inner_transport_header(struct sk_buff *skb)
-{
-       skb->inner_transport_header = skb->data;
-}
-
-static inline void skb_set_inner_transport_header(struct sk_buff *skb,
-                                                  const int offset)
-{
-       skb->inner_transport_header = skb->data + offset;
-}
-
-static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
-{
-       return skb->inner_network_header;
-}
-
-static inline void skb_reset_inner_network_header(struct sk_buff *skb)
-{
-       skb->inner_network_header = skb->data;
-}
-
-static inline void skb_set_inner_network_header(struct sk_buff *skb,
-                                               const int offset)
-{
-       skb->inner_network_header = skb->data + offset;
-}
-
-static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
-{
-       return skb->inner_mac_header;
-}
-
-static inline void skb_reset_inner_mac_header(struct sk_buff *skb)
-{
-       skb->inner_mac_header = skb->data;
-}
-
-static inline void skb_set_inner_mac_header(struct sk_buff *skb,
-                                               const int offset)
-{
-       skb->inner_mac_header = skb->data + offset;
-}
-static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
-{
-       return skb->transport_header != NULL;
-}
-
-static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
-{
-       return skb->transport_header;
-}
-
-static inline void skb_reset_transport_header(struct sk_buff *skb)
-{
-       skb->transport_header = skb->data;
-}
-
-static inline void skb_set_transport_header(struct sk_buff *skb,
-                                           const int offset)
-{
-       skb->transport_header = skb->data + offset;
-}
-
-static inline unsigned char *skb_network_header(const struct sk_buff *skb)
-{
-       return skb->network_header;
-}
-
-static inline void skb_reset_network_header(struct sk_buff *skb)
-{
-       skb->network_header = skb->data;
-}
-
-static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
-{
-       skb->network_header = skb->data + offset;
-}
-
-static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
-{
-       return skb->mac_header;
-}
-
-static inline int skb_mac_header_was_set(const struct sk_buff *skb)
-{
-       return skb->mac_header != NULL;
-}
-
-static inline void skb_reset_mac_header(struct sk_buff *skb)
-{
-       skb->mac_header = skb->data;
-}
-
-static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
-{
-       skb->mac_header = skb->data + offset;
-}
-#endif /* NET_SKBUFF_DATA_USES_OFFSET */
-
 static inline void skb_probe_transport_header(struct sk_buff *skb,
                                              const int offset_hint)
 {
index 5adbc33d1ab38c506c541e244024560c02686057..472120b4fac57584f30998d1be87c672607eb643 100644 (file)
@@ -246,7 +246,6 @@ struct tcp_sock {
 
        /* from STCP, retrans queue hinting */
        struct sk_buff* lost_skb_hint;
-       struct sk_buff *scoreboard_skb_hint;
        struct sk_buff *retransmit_skb_hint;
 
        struct sk_buff_head     out_of_order_queue; /* Out of order segments go here */
index 100fb8cec17c0157c331fc12366d22f593368295..e07feb456d19507e94a74921c69287e877214ab3 100644 (file)
@@ -74,6 +74,7 @@ struct inet6_ifaddr {
        bool                    tokenized;
 
        struct rcu_head         rcu;
+       struct in6_addr         peer_addr;
 };
 
 struct ip6_sf_socklist {
@@ -192,7 +193,6 @@ struct inet6_dev {
        struct in6_addr         token;
 
        struct neigh_parms      *nd_parms;
-       struct inet6_dev        *next;
        struct ipv6_devconf     cnf;
        struct ipv6_devstat     stats;
        unsigned long           tstamp; /* ipv6InterfaceTable update timestamp */
index aab73757bc4da4c4b5fce8390ec1234a86ea55c0..3bd22795c3e259e1f1f55176c808c6fdcc994600 100644 (file)
@@ -134,12 +134,14 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb)
 {
        switch (skb->protocol) {
        case cpu_to_be16(ETH_P_IP):
-               if (skb->network_header + sizeof(struct iphdr) <= skb->tail)
+               if (skb_network_header(skb) + sizeof(struct iphdr) <=
+                   skb_tail_pointer(skb))
                        return IP_ECN_set_ce(ip_hdr(skb));
                break;
 
        case cpu_to_be16(ETH_P_IPV6):
-               if (skb->network_header + sizeof(struct ipv6hdr) <= skb->tail)
+               if (skb_network_header(skb) + sizeof(struct ipv6hdr) <=
+                   skb_tail_pointer(skb))
                        return IP6_ECN_set_ce(ipv6_hdr(skb));
                break;
        }
index e49db91593a953422b0ce0a15c0eb0902ee33c56..44424e9dab2a7c74cdd58930bd3efa0ddb6be952 100644 (file)
@@ -51,6 +51,7 @@ struct rtable;
 
 struct fib_nh_exception {
        struct fib_nh_exception __rcu   *fnhe_next;
+       int                             fnhe_genid;
        __be32                          fnhe_daddr;
        u32                             fnhe_pmtu;
        __be32                          fnhe_gw;
index 4b6f0b28f41f097153669aa6194deae952ea58ff..40b4dfce01fc0324e6fda08ac9a6ade1f64e5a09 100644 (file)
@@ -101,7 +101,7 @@ int __net_init ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
 void __net_exit ip_tunnel_delete_net(struct ip_tunnel_net *itn);
 
 void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
-                   const struct iphdr *tnl_params);
+                   const struct iphdr *tnl_params, const u8 protocol);
 int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
 int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
 
index 0810aa57c78015ac35fd8ea9caaddb0c2ab791a3..ab47582f6c0b46fe808e9fc53a104a23de9196b1 100644 (file)
@@ -260,6 +260,12 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl)
 
 extern 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);
+
 extern int                     ip6_ra_control(struct sock *sk, int sel);
 
 extern int                     ipv6_parse_hopopts(struct sk_buff *skb);
index b176978274828206b784e7003e04c871bef582a3..495bc57f292caa6deba113f7fd6ffb5cfd8e3668 100644 (file)
@@ -118,6 +118,7 @@ struct net {
        struct netns_ipvs       *ipvs;
        struct sock             *diag_nlsk;
        atomic_t                rt_genid;
+       atomic_t                fnhe_genid;
 };
 
 /*
@@ -340,4 +341,14 @@ static inline void rt_genid_bump(struct net *net)
        atomic_inc(&net->rt_genid);
 }
 
+static inline int fnhe_genid(struct net *net)
+{
+       return atomic_read(&net->fnhe_genid);
+}
+
+static inline void fnhe_genid_bump(struct net *net)
+{
+       atomic_inc(&net->fnhe_genid);
+}
+
 #endif /* __NET_NET_NAMESPACE_H */
index 682b5ae9af5165dcc71b4f366c81db7a4df20c01..5db0224b73ac47b1513ffb9361e48aa0167bb24d 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef _PING_H
 #define _PING_H
 
+#include <net/icmp.h>
 #include <net/netns/hash.h>
 
 /* PING_HTABLE_SIZE must be power of 2 */
  */
 #define GID_T_MAX (((gid_t)~0U) >> 1)
 
+/* Compatibility glue so we can support IPv6 when it's compiled as a module */
+struct pingv6_ops {
+       int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len);
+       int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg,
+                                    struct sk_buff *skb);
+       int (*icmpv6_err_convert)(u8 type, u8 code, int *err);
+       void (*ipv6_icmp_error)(struct sock *sk, struct sk_buff *skb, int err,
+                               __be16 port, u32 info, u8 *payload);
+       int (*ipv6_chk_addr)(struct net *net, const struct in6_addr *addr,
+                            const struct net_device *dev, int strict);
+};
+
 struct ping_table {
        struct hlist_nulls_head hash[PING_HTABLE_SIZE];
        rwlock_t                lock;
@@ -36,20 +49,66 @@ struct ping_table {
 struct ping_iter_state {
        struct seq_net_private  p;
        int                     bucket;
+       sa_family_t             family;
 };
 
 extern struct proto ping_prot;
+extern struct ping_table ping_table;
+#if IS_ENABLED(CONFIG_IPV6)
+extern struct pingv6_ops pingv6_ops;
+#endif
+
+struct pingfakehdr {
+       struct icmphdr icmph;
+       struct iovec *iov;
+       sa_family_t family;
+       __wsum wcheck;
+};
+
+int  ping_get_port(struct sock *sk, unsigned short ident);
+void ping_hash(struct sock *sk);
+void ping_unhash(struct sock *sk);
 
+int  ping_init_sock(struct sock *sk);
+void ping_close(struct sock *sk, long timeout);
+int  ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len);
+void ping_err(struct sk_buff *skb, int offset, u32 info);
+int  ping_getfrag(void *from, char *to, int offset, int fraglen, int odd,
+                 struct sk_buff *);
 
-extern void ping_rcv(struct sk_buff *);
-extern void ping_err(struct sk_buff *, u32 info);
+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);
+void ping_rcv(struct sk_buff *skb);
 
 #ifdef CONFIG_PROC_FS
+struct ping_seq_afinfo {
+       char                            *name;
+       sa_family_t                     family;
+       const struct file_operations    *seq_fops;
+       const struct seq_operations     seq_ops;
+};
+
+extern const struct file_operations ping_seq_fops;
+
+void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family);
+void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos);
+void ping_seq_stop(struct seq_file *seq, void *v);
+int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo);
+void ping_proc_unregister(struct net *net, struct ping_seq_afinfo *afinfo);
+
 extern int __init ping_proc_init(void);
 extern void ping_proc_exit(void);
 #endif
 
 void __init ping_init(void);
-
+int  __init pingv6_init(void);
+void pingv6_exit(void);
 
 #endif /* _PING_H */
index 5bba80fbd1d9d92738d115cbc870bf0612cb0305..bf1cc3dced5ecdb571cecd9738ea30fc3aef5927 100644 (file)
@@ -1193,7 +1193,6 @@ static inline void tcp_mib_init(struct net *net)
 static inline void tcp_clear_retrans_hints_partial(struct tcp_sock *tp)
 {
        tp->lost_skb_hint = NULL;
-       tp->scoreboard_skb_hint = NULL;
 }
 
 static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp)
@@ -1284,11 +1283,13 @@ static inline struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
 #define tcp_twsk_md5_key(twsk) NULL
 #endif
 
-extern struct tcp_md5sig_pool __percpu *tcp_alloc_md5sig_pool(struct sock *);
-extern void tcp_free_md5sig_pool(void);
+extern bool tcp_alloc_md5sig_pool(void);
 
 extern struct tcp_md5sig_pool  *tcp_get_md5sig_pool(void);
-extern void tcp_put_md5sig_pool(void);
+static inline void tcp_put_md5sig_pool(void)
+{
+       local_bh_enable();
+}
 
 extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, const struct tcphdr *);
 extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *,
index 938b7fd1120477213888f9c7e61f98039bea3e03..48660e50ae90fdeec269fb2a1e5202e408021c3d 100644 (file)
@@ -3,56 +3,57 @@
 
 #include <net/checksum.h>
 
-/*
- *     IPv6 transport protocols
- */
-
+/* IPv6 transport protocols */
 extern struct proto rawv6_prot;
 extern struct proto udpv6_prot;
 extern struct proto udplitev6_prot;
 extern struct proto tcpv6_prot;
+extern struct proto pingv6_prot;
 
 struct flowi6;
 
 /* extension headers */
-extern int                             ipv6_exthdrs_init(void);
-extern void                            ipv6_exthdrs_exit(void);
-extern int                             ipv6_frag_init(void);
-extern void                            ipv6_frag_exit(void);
+int ipv6_exthdrs_init(void);
+void ipv6_exthdrs_exit(void);
+int ipv6_frag_init(void);
+void ipv6_frag_exit(void);
 
 /* transport protocols */
-extern int                             rawv6_init(void);
-extern void                            rawv6_exit(void);
-extern int                             udpv6_init(void);
-extern void                            udpv6_exit(void);
-extern int                             udplitev6_init(void);
-extern void                            udplitev6_exit(void);
-extern int                             tcpv6_init(void);
-extern void                            tcpv6_exit(void);
-
-extern int                             udpv6_connect(struct sock *sk,
-                                                     struct sockaddr *uaddr,
-                                                     int addr_len);
-
-extern int                     ip6_datagram_recv_ctl(struct sock *sk,
-                                                     struct msghdr *msg,
-                                                     struct sk_buff *skb);
-
-extern int                     ip6_datagram_send_ctl(struct net *net,
-                                                     struct sock *sk,
-                                                     struct msghdr *msg,
-                                                     struct flowi6 *fl6,
-                                                     struct ipv6_txoptions *opt,
-                                                     int *hlimit, int *tclass,
-                                                     int *dontfrag);
-
-#define                LOOPBACK4_IPV6          cpu_to_be32(0x7f000006)
-
-/*
- *     address family specific functions
- */
+int pingv6_init(void);
+void pingv6_exit(void);
+int rawv6_init(void);
+void rawv6_exit(void);
+int udpv6_init(void);
+void udpv6_exit(void);
+int udplitev6_init(void);
+void udplitev6_exit(void);
+int tcpv6_init(void);
+void tcpv6_exit(void);
+
+int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
+
+int ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
+                         struct sk_buff *skb);
+
+int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg,
+                         struct flowi6 *fl6, struct ipv6_txoptions *opt,
+                         int *hlimit, int *tclass, int *dontfrag);
+
+void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
+                            __u16 srcp, __u16 destp, int bucket);
+
+#define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006)
+
+/* address family specific functions */
 extern const struct inet_connection_sock_af_ops ipv4_specific;
 
-extern void inet6_destroy_sock(struct sock *sk);
+void inet6_destroy_sock(struct sock *sk);
+
+#define IPV6_SEQ_DGRAM_HEADER                                         \
+       "  sl  "                                                       \
+       "local_address                         "                       \
+       "remote_address                        "                       \
+       "st tx_queue rx_queue tr tm->when retrnsmt"                    \
+       "   uid  timeout inode ref pointer drops\n"
 
 #endif
index 0c9b44871df07b3f7e09de4a2d922f421a4895b5..38dbafaa5341154167a685a245096fbece6a375d 100644 (file)
@@ -993,8 +993,8 @@ enum ethtool_sfeatures_retval_bits {
 #define PORT_OTHER             0xff
 
 /* Which transceiver to use. */
-#define XCVR_INTERNAL          0x00
-#define XCVR_EXTERNAL          0x01
+#define XCVR_INTERNAL          0x00 /* PHY and MAC are in the same package */
+#define XCVR_EXTERNAL          0x01 /* PHY and MAC are in different packages */
 #define XCVR_DUMMY1            0x02
 #define XCVR_DUMMY2            0x03
 #define XCVR_DUMMY3            0x04
index 3ef3fe05ee99c55aa27d7c3eb5f828935b89ed59..eb262e3324d2fca44da8c88bf3127fd4da65b118 100644 (file)
  * that it cannot safely queue packets (as it may not be kicked to send them).
  */
 
+ /*
+ * "feature-split-event-channels" is introduced to separate guest TX
+ * and RX notificaion. Backend either doesn't support this feature or
+ * advertise it via xenstore as 0 (disabled) or 1 (enabled).
+ *
+ * To make use of this feature, frontend should allocate two event
+ * channels for TX and RX, advertise them to backend as
+ * "event-channel-tx" and "event-channel-rx" respectively. If frontend
+ * doesn't want to use this feature, it just writes "event-channel"
+ * node as before.
+ */
+
 /*
  * This is the 'wire' format for packets:
  *  Request 1: xen_netif_tx_request  -- XEN_NETTXF_* (any flags)
index 9424f3718ea703adc1019193a30352ad95981e6a..2fb2d88e8c2e329ec11653c20478bede1c4e5ad8 100644 (file)
@@ -341,7 +341,7 @@ static void __vlan_device_event(struct net_device *dev, unsigned long event)
 static int vlan_device_event(struct notifier_block *unused, unsigned long event,
                             void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct vlan_group *grp;
        struct vlan_info *vlan_info;
        int i, flgs;
index 2ddc9046868e7a19d06841054696773242099ccf..523e43e6da1b9a66449b7e6d0dc5121602741239 100644 (file)
@@ -218,6 +218,7 @@ source "net/batman-adv/Kconfig"
 source "net/openvswitch/Kconfig"
 source "net/vmw_vsock/Kconfig"
 source "net/netlink/Kconfig"
+source "net/mpls/Kconfig"
 
 config RPS
        boolean
@@ -259,6 +260,18 @@ config BPF_JIT
          packet sniffing (libpcap/tcpdump). Note : Admin should enable
          this feature changing /proc/sys/net/core/bpf_jit_enable
 
+config NET_FLOW_LIMIT
+       boolean
+       depends on RPS
+       default y
+       ---help---
+         The network stack has to drop packets when a receive processing CPU's
+         backlog reaches netdev_max_backlog. If a few out of many active flows
+         generate the vast majority of load, drop their traffic earlier to
+         maintain capacity for the other flows. This feature provides servers
+         with many clients some protection against DoS by a single (spoofed)
+         flow that greatly exceeds average workload.
+
 menu "Network testing"
 
 config NET_PKTGEN
index 091e7b04f301539036dca468d045d0615a33f4b4..9492e8cb64e9e467412aaf25a4c677d84ac6ac62 100644 (file)
@@ -70,3 +70,4 @@ obj-$(CONFIG_BATMAN_ADV)      += batman-adv/
 obj-$(CONFIG_NFC)              += nfc/
 obj-$(CONFIG_OPENVSWITCH)      += openvswitch/
 obj-$(CONFIG_VSOCKETS) += vmw_vsock/
+obj-$(CONFIG_NET_MPLS_GSO)     += mpls/
index 173a2e82f486b4ee19411b18842e61f57b05a58c..690356fa52b99a2d66a8522c448c51ba7eedba5f 100644 (file)
@@ -332,7 +332,7 @@ static void aarp_expire_timeout(unsigned long unused)
 static int aarp_device_event(struct notifier_block *this, unsigned long event,
                             void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        int ct;
 
        if (!net_eq(dev_net(dev), &init_net))
index ef12839a7cfe55b6ee99b2be667c0cd9fb829f79..7fee50d637f956240a6146b342e7723a131ce4bd 100644 (file)
@@ -644,7 +644,7 @@ static inline void atalk_dev_down(struct net_device *dev)
 static int ddp_device_event(struct notifier_block *this, unsigned long event,
                            void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (!net_eq(dev_net(dev), &init_net))
                return NOTIFY_DONE;
index 8ae3a7879335f28cc082ea6c2a3bf8da2b8820a3..8215f7cb170b5a21cdb67347f50578f57e515dfb 100644 (file)
@@ -539,9 +539,9 @@ static int clip_create(int number)
 }
 
 static int clip_device_event(struct notifier_block *this, unsigned long event,
-                            void *arg)
+                            void *ptr)
 {
-       struct net_device *dev = arg;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (!net_eq(dev_net(dev), &init_net))
                return NOTIFY_DONE;
@@ -575,6 +575,7 @@ static int clip_inet_event(struct notifier_block *this, unsigned long event,
                           void *ifa)
 {
        struct in_device *in_dev;
+       struct netdev_notifier_info info;
 
        in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
        /*
@@ -583,7 +584,8 @@ static int clip_inet_event(struct notifier_block *this, unsigned long event,
         */
        if (event != NETDEV_UP)
                return NOTIFY_DONE;
-       return clip_device_event(this, NETDEV_CHANGE, in_dev->dev);
+       netdev_notifier_info_init(&info, in_dev->dev);
+       return clip_device_event(this, NETDEV_CHANGE, &info);
 }
 
 static struct notifier_block clip_dev_notifier = {
index d4cc1be5c36469ea2b24b7dbb9375e364e6986b0..3af12755cd04851147b8e4661fd312e29abd0691 100644 (file)
@@ -998,14 +998,12 @@ int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
 }
 
 static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
-                              unsigned long event, void *dev_ptr)
+                              unsigned long event, void *ptr)
 {
-       struct net_device *dev;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct mpoa_client *mpc;
        struct lec_priv *priv;
 
-       dev = dev_ptr;
-
        if (!net_eq(dev_net(dev), &init_net))
                return NOTIFY_DONE;
 
index e277e38f736b93a133a6cd43cc7b264acfbad641..4b4d2b779ec1a08202303863fea1b74c67f04383 100644 (file)
@@ -111,9 +111,9 @@ again:
  *     Handle device status changes.
  */
 static int ax25_device_event(struct notifier_block *this, unsigned long event,
-       void *ptr)
+                            void *ptr)
 {
-       struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (!net_eq(dev_net(dev), &init_net))
                return NOTIFY_DONE;
@@ -1974,7 +1974,7 @@ static struct packet_type ax25_packet_type __read_mostly = {
 };
 
 static struct notifier_block ax25_dev_notifier = {
-       .notifier_call =ax25_device_event,
+       .notifier_call = ax25_device_event,
 };
 
 static int __init ax25_init(void)
index acbac2a9c62fc6e0c70f893f80da00ea5503cdf9..489bb36f1b9464381d2aa83c78740977e3899b77 100644 (file)
@@ -32,7 +32,6 @@ batman-adv-y += icmp_socket.o
 batman-adv-y += main.o
 batman-adv-$(CONFIG_BATMAN_ADV_NC) += network-coding.o
 batman-adv-y += originator.o
-batman-adv-y += ring_buffer.o
 batman-adv-y += routing.o
 batman-adv-y += send.o
 batman-adv-y += soft-interface.o
index 071f288b77a86c8c88b6eadd9634a24cdb209e81..d07323b3e9b8e611e99f44b116934c1bf750a79e 100644 (file)
@@ -19,7 +19,6 @@
 
 #include "main.h"
 #include "translation-table.h"
-#include "ring_buffer.h"
 #include "originator.h"
 #include "routing.h"
 #include "gateway_common.h"
 #include "bat_algo.h"
 #include "network-coding.h"
 
+/**
+ * batadv_ring_buffer_set - update the ring buffer with the given value
+ * @lq_recv: pointer to the ring buffer
+ * @lq_index: index to store the value at
+ * @value: value to store in the ring buffer
+ */
+static void batadv_ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index,
+                                  uint8_t value)
+{
+       lq_recv[*lq_index] = value;
+       *lq_index = (*lq_index + 1) % BATADV_TQ_GLOBAL_WINDOW_SIZE;
+}
+
+/**
+ * batadv_ring_buffer_set - compute the average of all non-zero values stored
+ * in the given ring buffer
+ * @lq_recv: pointer to the ring buffer
+ *
+ * Returns computed average value.
+ */
+static uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[])
+{
+       const uint8_t *ptr;
+       uint16_t count = 0, i = 0, sum = 0;
+
+       ptr = lq_recv;
+
+       while (i < BATADV_TQ_GLOBAL_WINDOW_SIZE) {
+               if (*ptr != 0) {
+                       count++;
+                       sum += *ptr;
+               }
+
+               i++;
+               ptr++;
+       }
+
+       if (count == 0)
+               return 0;
+
+       return (uint8_t)(sum / count);
+}
 static struct batadv_neigh_node *
 batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
                        const uint8_t *neigh_addr,
                        struct batadv_orig_node *orig_node,
-                       struct batadv_orig_node *orig_neigh, __be32 seqno)
+                       struct batadv_orig_node *orig_neigh)
 {
        struct batadv_neigh_node *neigh_node;
 
-       neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr,
-                                          ntohl(seqno));
+       neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr);
        if (!neigh_node)
                goto out;
 
@@ -413,18 +453,16 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
        else
                skb_size = packet_len;
 
-       skb_size += ETH_HLEN + NET_IP_ALIGN;
+       skb_size += ETH_HLEN;
 
-       forw_packet_aggr->skb = dev_alloc_skb(skb_size);
+       forw_packet_aggr->skb = netdev_alloc_skb_ip_align(NULL, skb_size);
        if (!forw_packet_aggr->skb) {
                if (!own_packet)
                        atomic_inc(&bat_priv->batman_queue_left);
                kfree(forw_packet_aggr);
                goto out;
        }
-       skb_reserve(forw_packet_aggr->skb, ETH_HLEN + NET_IP_ALIGN);
-
-       INIT_HLIST_NODE(&forw_packet_aggr->list);
+       skb_reserve(forw_packet_aggr->skb, ETH_HLEN);
 
        skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
        forw_packet_aggr->packet_len = packet_len;
@@ -590,6 +628,41 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
                                if_incoming, 0, batadv_iv_ogm_fwd_send_time());
 }
 
+/**
+ * batadv_iv_ogm_slide_own_bcast_window - bitshift own OGM broadcast windows for
+ * the given interface
+ * @hard_iface: the interface for which the windows have to be shifted
+ */
+static void
+batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
+{
+       struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+       struct batadv_hashtable *hash = bat_priv->orig_hash;
+       struct hlist_head *head;
+       struct batadv_orig_node *orig_node;
+       unsigned long *word;
+       uint32_t i;
+       size_t word_index;
+       uint8_t *w;
+
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
+
+               rcu_read_lock();
+               hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
+                       spin_lock_bh(&orig_node->ogm_cnt_lock);
+                       word_index = hard_iface->if_num * BATADV_NUM_WORDS;
+                       word = &(orig_node->bcast_own[word_index]);
+
+                       batadv_bit_get_packet(bat_priv, word, 1, 0);
+                       w = &orig_node->bcast_own_sum[hard_iface->if_num];
+                       *w = bitmap_weight(word, BATADV_TQ_LOCAL_WINDOW_SIZE);
+                       spin_unlock_bh(&orig_node->ogm_cnt_lock);
+               }
+               rcu_read_unlock();
+       }
+}
+
 static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
@@ -634,7 +707,7 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
                batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS;
        }
 
-       batadv_slide_own_bcast_window(hard_iface);
+       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));
@@ -670,7 +743,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
                if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
                    tmp_neigh_node->if_incoming == if_incoming &&
                    atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
-                       if (neigh_node)
+                       if (WARN(neigh_node, "too many matching neigh_nodes"))
                                batadv_neigh_node_free_ref(neigh_node);
                        neigh_node = tmp_neigh_node;
                        continue;
@@ -696,8 +769,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
 
                neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
                                                     ethhdr->h_source,
-                                                    orig_node, orig_tmp,
-                                                    batadv_ogm_packet->seqno);
+                                                    orig_node, orig_tmp);
 
                batadv_orig_node_free_ref(orig_tmp);
                if (!neigh_node)
@@ -829,8 +901,7 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
                neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
                                                     orig_neigh_node->orig,
                                                     orig_neigh_node,
-                                                    orig_neigh_node,
-                                                    batadv_ogm_packet->seqno);
+                                                    orig_neigh_node);
 
        if (!neigh_node)
                goto out;
@@ -991,7 +1062,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
        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_broadcast = 0, is_bidirect;
+       int is_bidirect;
        bool is_single_hop_neigh = false;
        bool is_from_best_next_hop = false;
        int is_duplicate, sameseq, simlar_ttl;
@@ -1054,19 +1125,9 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
                if (batadv_compare_eth(batadv_ogm_packet->prev_sender,
                                       hard_iface->net_dev->dev_addr))
                        is_my_oldorig = 1;
-
-               if (is_broadcast_ether_addr(ethhdr->h_source))
-                       is_broadcast = 1;
        }
        rcu_read_unlock();
 
-       if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) {
-               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "Drop packet: incompatible batman version (%i)\n",
-                          batadv_ogm_packet->header.version);
-               return;
-       }
-
        if (is_my_addr) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Drop packet: received my own broadcast (sender: %pM)\n",
@@ -1074,13 +1135,6 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
                return;
        }
 
-       if (is_broadcast) {
-               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "Drop packet: ignoring all packets with broadcast source addr (sender: %pM)\n",
-                          ethhdr->h_source);
-               return;
-       }
-
        if (is_my_orig) {
                unsigned long *word;
                int offset;
@@ -1288,7 +1342,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
                           skb->len + ETH_HLEN);
 
        packet_len = skb_headlen(skb);
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
        packet_buff = skb->data;
        batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
 
index 379061c725491ec0801940265aedd21245e4ccf1..e9d8e0b3c3d0961b679f86991960dcf9d9bface2 100644 (file)
@@ -180,7 +180,7 @@ static struct batadv_bla_claim
  */
 static struct batadv_bla_backbone_gw *
 batadv_backbone_hash_find(struct batadv_priv *bat_priv,
-                         uint8_t *addr, short vid)
+                         uint8_t *addr, unsigned short vid)
 {
        struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
        struct hlist_head *head;
@@ -257,7 +257,7 @@ batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw)
  * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...)
  */
 static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
-                                 short vid, int claimtype)
+                                 unsigned short vid, int claimtype)
 {
        struct sk_buff *skb;
        struct ethhdr *ethhdr;
@@ -307,7 +307,8 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
                 */
                memcpy(ethhdr->h_source, mac, ETH_ALEN);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid);
+                          "bla_send_claim(): CLAIM %pM on vid %d\n", mac,
+                          BATADV_PRINT_VID(vid));
                break;
        case BATADV_CLAIM_TYPE_UNCLAIM:
                /* unclaim frame
@@ -316,7 +317,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
                memcpy(hw_src, mac, ETH_ALEN);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
                           "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac,
-                          vid);
+                          BATADV_PRINT_VID(vid));
                break;
        case BATADV_CLAIM_TYPE_ANNOUNCE:
                /* announcement frame
@@ -325,7 +326,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
                memcpy(hw_src, mac, ETH_ALEN);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
                           "bla_send_claim(): ANNOUNCE of %pM on vid %d\n",
-                          ethhdr->h_source, vid);
+                          ethhdr->h_source, BATADV_PRINT_VID(vid));
                break;
        case BATADV_CLAIM_TYPE_REQUEST:
                /* request frame
@@ -335,13 +336,15 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
                memcpy(hw_src, mac, ETH_ALEN);
                memcpy(ethhdr->h_dest, mac, ETH_ALEN);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_send_claim(): REQUEST of %pM to %pMon vid %d\n",
-                          ethhdr->h_source, ethhdr->h_dest, vid);
+                          "bla_send_claim(): REQUEST of %pM to %pM on vid %d\n",
+                          ethhdr->h_source, ethhdr->h_dest,
+                          BATADV_PRINT_VID(vid));
                break;
        }
 
-       if (vid != -1)
-               skb = vlan_insert_tag(skb, htons(ETH_P_8021Q), vid);
+       if (vid & BATADV_VLAN_HAS_TAG)
+               skb = vlan_insert_tag(skb, htons(ETH_P_8021Q),
+                                     vid & VLAN_VID_MASK);
 
        skb_reset_mac_header(skb);
        skb->protocol = eth_type_trans(skb, soft_iface);
@@ -367,7 +370,7 @@ out:
  */
 static struct batadv_bla_backbone_gw *
 batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
-                          short vid, bool own_backbone)
+                          unsigned short vid, bool own_backbone)
 {
        struct batadv_bla_backbone_gw *entry;
        struct batadv_orig_node *orig_node;
@@ -380,7 +383,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
                   "bla_get_backbone_gw(): not found (%pM, %d), creating new entry\n",
-                  orig, vid);
+                  orig, BATADV_PRINT_VID(vid));
 
        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (!entry)
@@ -434,7 +437,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
 static void
 batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
                                  struct batadv_hard_iface *primary_if,
-                                 short vid)
+                                 unsigned short vid)
 {
        struct batadv_bla_backbone_gw *backbone_gw;
 
@@ -456,7 +459,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
  */
 static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
                                      struct batadv_hard_iface *primary_if,
-                                     short vid)
+                                     unsigned short vid)
 {
        struct hlist_head *head;
        struct batadv_hashtable *hash;
@@ -547,7 +550,7 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
  * @backbone_gw: the backbone gateway which claims it
  */
 static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
-                                const uint8_t *mac, const short vid,
+                                const uint8_t *mac, const unsigned short vid,
                                 struct batadv_bla_backbone_gw *backbone_gw)
 {
        struct batadv_bla_claim *claim;
@@ -572,7 +575,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
                atomic_set(&claim->refcount, 2);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
                           "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
-                          mac, vid);
+                          mac, BATADV_PRINT_VID(vid));
                hash_added = batadv_hash_add(bat_priv->bla.claim_hash,
                                             batadv_compare_claim,
                                             batadv_choose_claim, claim,
@@ -591,7 +594,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
 
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
                           "bla_add_claim(): changing ownership for %pM, vid %d\n",
-                          mac, vid);
+                          mac, BATADV_PRINT_VID(vid));
 
                claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
                batadv_backbone_gw_free_ref(claim->backbone_gw);
@@ -611,7 +614,7 @@ claim_free_ref:
  * given mac address and vid.
  */
 static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
-                                const uint8_t *mac, const short vid)
+                                const uint8_t *mac, const unsigned short vid)
 {
        struct batadv_bla_claim search_claim, *claim;
 
@@ -622,7 +625,7 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
                return;
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n",
-                  mac, vid);
+                  mac, BATADV_PRINT_VID(vid));
 
        batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim,
                           batadv_choose_claim, claim);
@@ -637,7 +640,7 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
 /* check for ANNOUNCE frame, return 1 if handled */
 static int batadv_handle_announce(struct batadv_priv *bat_priv,
                                  uint8_t *an_addr, uint8_t *backbone_addr,
-                                 short vid)
+                                 unsigned short vid)
 {
        struct batadv_bla_backbone_gw *backbone_gw;
        uint16_t crc;
@@ -658,12 +661,13 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv,
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
                   "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n",
-                  vid, backbone_gw->orig, crc);
+                  BATADV_PRINT_VID(vid), backbone_gw->orig, crc);
 
        if (backbone_gw->crc != crc) {
                batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
                           "handle_announce(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n",
-                          backbone_gw->orig, backbone_gw->vid,
+                          backbone_gw->orig,
+                          BATADV_PRINT_VID(backbone_gw->vid),
                           backbone_gw->crc, crc);
 
                batadv_bla_send_request(backbone_gw);
@@ -685,7 +689,7 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv,
 static int batadv_handle_request(struct batadv_priv *bat_priv,
                                 struct batadv_hard_iface *primary_if,
                                 uint8_t *backbone_addr,
-                                struct ethhdr *ethhdr, short vid)
+                                struct ethhdr *ethhdr, unsigned short vid)
 {
        /* check for REQUEST frame */
        if (!batadv_compare_eth(backbone_addr, ethhdr->h_dest))
@@ -699,7 +703,7 @@ static int batadv_handle_request(struct batadv_priv *bat_priv,
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
                   "handle_request(): REQUEST vid %d (sent by %pM)...\n",
-                  vid, ethhdr->h_source);
+                  BATADV_PRINT_VID(vid), ethhdr->h_source);
 
        batadv_bla_answer_request(bat_priv, primary_if, vid);
        return 1;
@@ -709,7 +713,7 @@ static int batadv_handle_request(struct batadv_priv *bat_priv,
 static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
                                 struct batadv_hard_iface *primary_if,
                                 uint8_t *backbone_addr,
-                                uint8_t *claim_addr, short vid)
+                                uint8_t *claim_addr, unsigned short vid)
 {
        struct batadv_bla_backbone_gw *backbone_gw;
 
@@ -727,7 +731,7 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
        /* this must be an UNCLAIM frame */
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
                   "handle_unclaim(): UNCLAIM %pM on vid %d (sent by %pM)...\n",
-                  claim_addr, vid, backbone_gw->orig);
+                  claim_addr, BATADV_PRINT_VID(vid), backbone_gw->orig);
 
        batadv_bla_del_claim(bat_priv, claim_addr, vid);
        batadv_backbone_gw_free_ref(backbone_gw);
@@ -738,7 +742,7 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
 static int batadv_handle_claim(struct batadv_priv *bat_priv,
                               struct batadv_hard_iface *primary_if,
                               uint8_t *backbone_addr, uint8_t *claim_addr,
-                              short vid)
+                              unsigned short vid)
 {
        struct batadv_bla_backbone_gw *backbone_gw;
 
@@ -861,14 +865,15 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
        struct batadv_bla_claim_dst *bla_dst;
        uint16_t proto;
        int headlen;
-       short vid = -1;
+       unsigned short vid = BATADV_NO_FLAGS;
        int ret;
 
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
                vhdr = (struct vlan_ethhdr *)ethhdr;
                vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
+               vid |= BATADV_VLAN_HAS_TAG;
                proto = ntohs(vhdr->h_vlan_encapsulated_proto);
                headlen = sizeof(*vhdr);
        } else {
@@ -885,7 +890,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
                return 0;
 
        /* pskb_may_pull() may have modified the pointers, get ethhdr again */
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
        arphdr = (struct arphdr *)((uint8_t *)ethhdr + headlen);
 
        /* Check whether the ARP frame carries a valid
@@ -910,7 +915,8 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
        if (ret == 1)
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
                           "bla_process_claim(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
-                          ethhdr->h_source, vid, hw_src, hw_dst);
+                          ethhdr->h_source, BATADV_PRINT_VID(vid), hw_src,
+                          hw_dst);
 
        if (ret < 2)
                return ret;
@@ -945,7 +951,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
                   "bla_process_claim(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
-                  ethhdr->h_source, vid, hw_src, hw_dst);
+                  ethhdr->h_source, BATADV_PRINT_VID(vid), hw_src, hw_dst);
        return 1;
 }
 
@@ -1358,7 +1364,7 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb,
        struct ethhdr *ethhdr;
        struct vlan_ethhdr *vhdr;
        struct batadv_bla_backbone_gw *backbone_gw;
-       short vid = -1;
+       unsigned short vid = BATADV_NO_FLAGS;
 
        if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
                return 0;
@@ -1375,6 +1381,7 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb,
 
                vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size);
                vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
+               vid |= BATADV_VLAN_HAS_TAG;
        }
 
        /* see if this originator is a backbone gw for this VLAN */
@@ -1424,15 +1431,15 @@ void batadv_bla_free(struct batadv_priv *bat_priv)
  * returns 1, otherwise it returns 0 and the caller shall further
  * process the skb.
  */
-int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
-                 bool is_bcast)
+int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
+                 unsigned short vid, bool is_bcast)
 {
        struct ethhdr *ethhdr;
        struct batadv_bla_claim search_claim, *claim = NULL;
        struct batadv_hard_iface *primary_if;
        int ret;
 
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        primary_if = batadv_primary_if_get_selected(bat_priv);
        if (!primary_if)
@@ -1519,7 +1526,8 @@ out:
  * returns 1, otherwise it returns 0 and the caller shall further
  * process the skb.
  */
-int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid)
+int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
+                 unsigned short vid)
 {
        struct ethhdr *ethhdr;
        struct batadv_bla_claim search_claim, *claim = NULL;
@@ -1539,7 +1547,7 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid)
        if (batadv_bla_process_claim(bat_priv, primary_if, skb))
                goto handled;
 
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
                /* don't allow broadcasts while requests are in flight */
@@ -1623,8 +1631,8 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
                hlist_for_each_entry_rcu(claim, head, hash_entry) {
                        is_own = batadv_compare_eth(claim->backbone_gw->orig,
                                                    primary_addr);
-                       seq_printf(seq, " * %pM on % 5d by %pM [%c] (%#.4x)\n",
-                                  claim->addr, claim->vid,
+                       seq_printf(seq, " * %pM on %5d by %pM [%c] (%#.4x)\n",
+                                  claim->addr, BATADV_PRINT_VID(claim->vid),
                                   claim->backbone_gw->orig,
                                   (is_own ? 'x' : ' '),
                                   claim->backbone_gw->crc);
@@ -1676,10 +1684,10 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
                        if (is_own)
                                continue;
 
-                       seq_printf(seq,
-                                  " * %pM on % 5d % 4i.%03is (%#.4x)\n",
-                                  backbone_gw->orig, backbone_gw->vid,
-                                  secs, msecs, backbone_gw->crc);
+                       seq_printf(seq, " * %pM on %5d %4i.%03is (%#.4x)\n",
+                                  backbone_gw->orig,
+                                  BATADV_PRINT_VID(backbone_gw->vid), secs,
+                                  msecs, backbone_gw->crc);
                }
                rcu_read_unlock();
        }
index dea2fbc5d98d00d020608db19e51e830501c93a7..4b102e71e5bd63c2bee71f14bcdb0b799398ef5e 100644 (file)
 #define _NET_BATMAN_ADV_BLA_H_
 
 #ifdef CONFIG_BATMAN_ADV_BLA
-int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
-                 bool is_bcast);
-int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid);
+int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
+                 unsigned short vid, bool is_bcast);
+int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
+                 unsigned short vid);
 int batadv_bla_is_backbone_gw(struct sk_buff *skb,
                              struct batadv_orig_node *orig_node, int hdr_size);
 int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
@@ -42,13 +43,14 @@ void batadv_bla_free(struct batadv_priv *bat_priv);
 #else /* ifdef CONFIG_BATMAN_ADV_BLA */
 
 static inline int batadv_bla_rx(struct batadv_priv *bat_priv,
-                               struct sk_buff *skb, short vid, bool is_bcast)
+                               struct sk_buff *skb, unsigned short vid,
+                               bool is_bcast)
 {
        return 0;
 }
 
 static inline int batadv_bla_tx(struct batadv_priv *bat_priv,
-                               struct sk_buff *skb, short vid)
+                               struct sk_buff *skb, unsigned short vid)
 {
        return 0;
 }
index 239992021b1d635382dfcec141723696d7cbf564..06345d401588c949762edfa14aaeb3f018a8e294 100644 (file)
@@ -45,9 +45,9 @@ static void batadv_dat_start_timer(struct batadv_priv *bat_priv)
 }
 
 /**
- * batadv_dat_entry_free_ref - decrements the dat_entry refcounter and possibly
+ * batadv_dat_entry_free_ref - decrement the dat_entry refcounter and possibly
  * free it
- * @dat_entry: the oentry to free
+ * @dat_entry: the entry to free
  */
 static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry)
 {
@@ -56,10 +56,10 @@ static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry)
 }
 
 /**
- * batadv_dat_to_purge - checks whether a dat_entry has to be purged or not
+ * batadv_dat_to_purge - check whether a dat_entry has to be purged or not
  * @dat_entry: the entry to check
  *
- * Returns true if the entry has to be purged now, false otherwise
+ * Returns true if the entry has to be purged now, false otherwise.
  */
 static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry)
 {
@@ -75,8 +75,8 @@ static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry)
  *           returns a boolean value: true is the entry has to be deleted,
  *           false otherwise
  *
- * Loops over each entry in the DAT local storage and delete it if and only if
- * the to_purge function passed as argument returns true
+ * Loops over each entry in the DAT local storage and deletes it if and only if
+ * the to_purge function passed as argument returns true.
  */
 static void __batadv_dat_purge(struct batadv_priv *bat_priv,
                               bool (*to_purge)(struct batadv_dat_entry *))
@@ -97,7 +97,7 @@ static void __batadv_dat_purge(struct batadv_priv *bat_priv,
                spin_lock_bh(list_lock);
                hlist_for_each_entry_safe(dat_entry, node_tmp, head,
                                          hash_entry) {
-                       /* if an helper function has been passed as parameter,
+                       /* if a helper function has been passed as parameter,
                         * ask it if the entry has to be purged or not
                         */
                        if (to_purge && !to_purge(dat_entry))
@@ -134,7 +134,7 @@ static void batadv_dat_purge(struct work_struct *work)
  * @node: node in the local table
  * @data2: second object to compare the node to
  *
- * Returns 1 if the two entry are the same, 0 otherwise
+ * Returns 1 if the two entries are the same, 0 otherwise.
  */
 static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
 {
@@ -149,7 +149,7 @@ static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
  * @skb: ARP packet
  * @hdr_size: size of the possible header before the ARP packet
  *
- * Returns the value of the hw_src field in the ARP packet
+ * Returns the value of the hw_src field in the ARP packet.
  */
 static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size)
 {
@@ -166,7 +166,7 @@ static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size)
  * @skb: ARP packet
  * @hdr_size: size of the possible header before the ARP packet
  *
- * Returns the value of the ip_src field in the ARP packet
+ * Returns the value of the ip_src field in the ARP packet.
  */
 static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size)
 {
@@ -178,7 +178,7 @@ static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size)
  * @skb: ARP packet
  * @hdr_size: size of the possible header before the ARP packet
  *
- * Returns the value of the hw_dst field in the ARP packet
+ * Returns the value of the hw_dst field in the ARP packet.
  */
 static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size)
 {
@@ -190,7 +190,7 @@ static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size)
  * @skb: ARP packet
  * @hdr_size: size of the possible header before the ARP packet
  *
- * Returns the value of the ip_dst field in the ARP packet
+ * Returns the value of the ip_dst field in the ARP packet.
  */
 static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
 {
@@ -202,7 +202,7 @@ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
  * @data: data to hash
  * @size: size of the hash table
  *
- * Returns the selected index in the hash table for the given data
+ * Returns the selected index in the hash table for the given data.
  */
 static uint32_t batadv_hash_dat(const void *data, uint32_t size)
 {
@@ -224,12 +224,12 @@ static uint32_t batadv_hash_dat(const void *data, uint32_t size)
 }
 
 /**
- * batadv_dat_entry_hash_find - looks for a given dat_entry in the local hash
+ * batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
  * table
  * @bat_priv: the bat priv with all the soft interface information
  * @ip: search key
  *
- * Returns the dat_entry if found, NULL otherwise
+ * Returns the dat_entry if found, NULL otherwise.
  */
 static struct batadv_dat_entry *
 batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
@@ -343,9 +343,6 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
        if (hdr_size == 0)
                return;
 
-       /* if the ARP packet is encapsulated in a batman packet, let's print
-        * some debug messages
-        */
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
        switch (unicast_4addr_packet->u.header.packet_type) {
@@ -409,7 +406,8 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
  * @candidate: orig_node under evaluation
  * @max_orig_node: last selected candidate
  *
- * Returns true if the node has been elected as next candidate or false othrwise
+ * Returns true if the node has been elected as next candidate or false
+ * otherwise.
  */
 static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
                                         int select, batadv_dat_addr_t tmp_max,
@@ -472,7 +470,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
         */
        cands[select].type = BATADV_DAT_CANDIDATE_NOT_FOUND;
 
-       /* iterate over the originator list and find the node with closest
+       /* iterate over the originator list and find the node with the closest
         * dat_address which has not been selected yet
         */
        for (i = 0; i < hash->size; i++) {
@@ -480,7 +478,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
 
                rcu_read_lock();
                hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
-                       /* the dht space is a ring and addresses are unsigned */
+                       /* the dht space is a ring using unsigned addresses */
                        tmp_max = BATADV_DAT_ADDR_MAX - orig_node->dat_addr +
                                  ip_key;
 
@@ -512,7 +510,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
 }
 
 /**
- * batadv_dat_select_candidates - selects the nodes which the DHT message has to
+ * batadv_dat_select_candidates - select the nodes which the DHT message has to
  * be sent to
  * @bat_priv: the bat priv with all the soft interface information
  * @ip_dst: ipv4 to look up in the DHT
@@ -521,7 +519,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
  * closest values (from the LEFT, with wrap around if needed) then the hash
  * value of the key. ip_dst is the key.
  *
- * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM
+ * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM.
  */
 static struct batadv_dat_candidate *
 batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
@@ -558,10 +556,11 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
  * @ip: the DHT key
  * @packet_subtype: unicast4addr packet subtype to use
  *
- * In this function the skb is copied by means of pskb_copy() and is sent as
- * unicast packet to each of the selected candidates
+ * This function copies the skb with pskb_copy() and is sent as unicast packet
+ * to each of the selected candidates.
  *
- * Returns true if the packet is sent to at least one candidate, false otherwise
+ * Returns true if the packet is sent to at least one candidate, false
+ * otherwise.
  */
 static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
                                 struct sk_buff *skb, __be32 ip,
@@ -727,7 +726,7 @@ out:
  * @skb: packet to analyse
  * @hdr_size: size of the possible header before the ARP packet in the skb
  *
- * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise
+ * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise.
  */
 static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
                                    struct sk_buff *skb, int hdr_size)
@@ -754,9 +753,7 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
 
        arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN);
 
-       /* Check whether the ARP packet carries a valid
-        * IP information
-        */
+       /* check whether the ARP packet carries a valid IP information */
        if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
                goto out;
 
@@ -784,7 +781,7 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
        if (is_zero_ether_addr(hw_src) || is_multicast_ether_addr(hw_src))
                goto out;
 
-       /* we don't care about the destination MAC address in ARP requests */
+       /* don't care about the destination MAC address in ARP requests */
        if (arphdr->ar_op != htons(ARPOP_REQUEST)) {
                hw_dst = batadv_arp_hw_dst(skb, hdr_size);
                if (is_zero_ether_addr(hw_dst) ||
@@ -804,8 +801,8 @@ out:
  * @skb: packet to check
  *
  * Returns true if the message has been sent to the dht candidates, false
- * otherwise. In case of true the message has to be enqueued to permit the
- * fallback
+ * otherwise. In case of a positive return value the message has to be enqueued
+ * to permit the fallback.
  */
 bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
                                           struct sk_buff *skb)
@@ -867,7 +864,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
                batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n");
                ret = true;
        } else {
-               /* Send the request on the DHT */
+               /* Send the request to the DHT */
                ret = batadv_dat_send_data(bat_priv, skb, ip_dst,
                                           BATADV_P_DAT_DHT_GET);
        }
@@ -884,7 +881,7 @@ out:
  * @skb: packet to check
  * @hdr_size: size of the encapsulation header
  *
- * Returns true if the request has been answered, false otherwise
+ * Returns true if the request has been answered, false otherwise.
  */
 bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
                                           struct sk_buff *skb, int hdr_size)
@@ -924,10 +921,9 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
        if (!skb_new)
                goto out;
 
-       /* to preserve backwards compatibility, here the node has to answer
-        * using the same packet type it received for the request. This is due
-        * to that if a node is not using the 4addr packet format it may not
-        * support it.
+       /* To preserve backwards compatibility, the node has choose the outgoing
+        * format based on the incoming request packet type. The assumption is
+        * that a node not using the 4addr packet format doesn't support it.
         */
        if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
                err = batadv_unicast_4addr_send_skb(bat_priv, skb_new,
@@ -977,7 +973,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
        batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
 
        /* Send the ARP reply to the candidates for both the IP addresses that
-        * the node got within the ARP reply
+        * the node obtained from the ARP reply
         */
        batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT);
        batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT);
@@ -987,7 +983,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
  * DAT storage only
  * @bat_priv: the bat priv with all the soft interface information
  * @skb: packet to check
- * @hdr_size: siaze of the encapsulation header
+ * @hdr_size: size of the encapsulation header
  */
 bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
                                         struct sk_buff *skb, int hdr_size)
@@ -1031,11 +1027,11 @@ out:
 
 /**
  * batadv_dat_drop_broadcast_packet - check if an ARP request has to be dropped
- * (because the node has already got the reply via DAT) or not
+ * (because the node has already obtained the reply via DAT) or not
  * @bat_priv: the bat priv with all the soft interface information
  * @forw_packet: the broadcast packet
  *
- * Returns true if the node can drop the packet, false otherwise
+ * Returns true if the node can drop the packet, false otherwise.
  */
 bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
                                      struct batadv_forw_packet *forw_packet)
index 522243aff2f3b4a45895efea0752405bbee95fa9..c478e6bcf89b8bd570a54a9a811b4309c7a2e5f0 100644 (file)
@@ -117,6 +117,58 @@ static int batadv_is_valid_iface(const struct net_device *net_dev)
        return 1;
 }
 
+/**
+ * batadv_is_wifi_netdev - check if the given net_device struct is a wifi
+ *  interface
+ * @net_device: the device to check
+ *
+ * Returns true if the net device is a 802.11 wireless device, false otherwise.
+ */
+static bool batadv_is_wifi_netdev(struct net_device *net_device)
+{
+#ifdef CONFIG_WIRELESS_EXT
+       /* pre-cfg80211 drivers have to implement WEXT, so it is possible to
+        * check for wireless_handlers != NULL
+        */
+       if (net_device->wireless_handlers)
+               return true;
+#endif
+
+       /* cfg80211 drivers have to set ieee80211_ptr */
+       if (net_device->ieee80211_ptr)
+               return true;
+
+       return false;
+}
+
+/**
+ * batadv_is_wifi_iface - check if the given interface represented by ifindex
+ *  is a wifi interface
+ * @ifindex: interface index to check
+ *
+ * Returns true if the interface represented by ifindex is a 802.11 wireless
+ * device, false otherwise.
+ */
+bool batadv_is_wifi_iface(int ifindex)
+{
+       struct net_device *net_device = NULL;
+       bool ret = false;
+
+       if (ifindex == BATADV_NULL_IFINDEX)
+               goto out;
+
+       net_device = dev_get_by_index(&init_net, ifindex);
+       if (!net_device)
+               goto out;
+
+       ret = batadv_is_wifi_netdev(net_device);
+
+out:
+       if (net_device)
+               dev_put(net_device);
+       return ret;
+}
+
 static struct batadv_hard_iface *
 batadv_hardif_get_active(const struct net_device *soft_iface)
 {
@@ -525,7 +577,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
 
        dev_hold(net_dev);
 
-       hard_iface = kmalloc(sizeof(*hard_iface), GFP_ATOMIC);
+       hard_iface = kzalloc(sizeof(*hard_iface), GFP_ATOMIC);
        if (!hard_iface)
                goto release_dev;
 
@@ -541,18 +593,16 @@ batadv_hardif_add_interface(struct net_device *net_dev)
        INIT_WORK(&hard_iface->cleanup_work,
                  batadv_hardif_remove_interface_finish);
 
+       hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
+       if (batadv_is_wifi_netdev(net_dev))
+               hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
+
        /* extra reference for return */
        atomic_set(&hard_iface->refcount, 2);
 
        batadv_check_known_mac_addr(hard_iface->net_dev);
        list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
 
-       /* This can't be called via a bat_priv callback because
-        * we have no bat_priv yet.
-        */
-       atomic_set(&hard_iface->bat_iv.ogm_seqno, 1);
-       hard_iface->bat_iv.ogm_buff = NULL;
-
        return hard_iface;
 
 free_if:
@@ -595,7 +645,7 @@ void batadv_hardif_remove_interfaces(void)
 static int batadv_hard_if_event(struct notifier_block *this,
                                unsigned long event, void *ptr)
 {
-       struct net_device *net_dev = ptr;
+       struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
        struct batadv_hard_iface *hard_iface;
        struct batadv_hard_iface *primary_if = NULL;
        struct batadv_priv *bat_priv;
@@ -657,38 +707,6 @@ out:
        return NOTIFY_DONE;
 }
 
-/* This function returns true if the interface represented by ifindex is a
- * 802.11 wireless device
- */
-bool batadv_is_wifi_iface(int ifindex)
-{
-       struct net_device *net_device = NULL;
-       bool ret = false;
-
-       if (ifindex == BATADV_NULL_IFINDEX)
-               goto out;
-
-       net_device = dev_get_by_index(&init_net, ifindex);
-       if (!net_device)
-               goto out;
-
-#ifdef CONFIG_WIRELESS_EXT
-       /* pre-cfg80211 drivers have to implement WEXT, so it is possible to
-        * check for wireless_handlers != NULL
-        */
-       if (net_device->wireless_handlers)
-               ret = true;
-       else
-#endif
-               /* cfg80211 drivers have to set ieee80211_ptr */
-               if (net_device->ieee80211_ptr)
-                       ret = true;
-out:
-       if (net_device)
-               dev_put(net_device);
-       return ret;
-}
-
 struct notifier_block batadv_hard_if_notifier = {
        .notifier_call = batadv_hard_if_event,
 };
index 0ba6c899b2d3512b9dd0bc0c4292fcf08d1f0154..b27508b8085cd84727bf89c434b0b56adcdcd87f 100644 (file)
@@ -177,13 +177,13 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
        if (len >= sizeof(struct batadv_icmp_packet_rr))
                packet_len = sizeof(struct batadv_icmp_packet_rr);
 
-       skb = dev_alloc_skb(packet_len + ETH_HLEN + NET_IP_ALIGN);
+       skb = netdev_alloc_skb_ip_align(NULL, packet_len + ETH_HLEN);
        if (!skb) {
                len = -ENOMEM;
                goto out;
        }
 
-       skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+       skb_reserve(skb, ETH_HLEN);
        icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len);
 
        if (copy_from_user(icmp_packet, buff, packet_len)) {
index 59a0d6af15c88aca2f05c0883fc2fdfeadea66f4..5e9aebb7d56b5c117ebc80a893145a1cb9b975ab 100644 (file)
@@ -26,7 +26,7 @@
 #define BATADV_DRIVER_DEVICE "batman-adv"
 
 #ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2013.2.0"
+#define BATADV_SOURCE_VERSION "2013.3.0"
 #endif
 
 /* B.A.T.M.A.N. parameters */
 
 #define BATADV_LOG_BUF_LEN 8192          /* has to be a power of 2 */
 
+/* number of packets to send for broadcasts on different interface types */
+#define BATADV_NUM_BCASTS_DEFAULT 1
+#define BATADV_NUM_BCASTS_WIRELESS 3
+#define BATADV_NUM_BCASTS_MAX 3
+
 /* msecs after which an ARP_REQUEST is sent in broadcast as fallback */
 #define ARP_REQ_DELAY 250
 /* numbers of originator to contact for any PUT/GET DHT operation */
@@ -157,6 +162,17 @@ enum batadv_uev_type {
 #include <linux/seq_file.h>
 #include "types.h"
 
+/**
+ * batadv_vlan_flags - flags for the four MSB of any vlan ID field
+ * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not
+ */
+enum batadv_vlan_flags {
+       BATADV_VLAN_HAS_TAG     = BIT(15),
+};
+
+#define BATADV_PRINT_VID(vid) (vid & BATADV_VLAN_HAS_TAG ? \
+                              (int)(vid & VLAN_VID_MASK) : -1)
+
 extern char batadv_routing_algo[];
 extern struct list_head batadv_hardif_list;
 
index e84629ece9b7cfb0a06a0baf856474173f02a144..a487d46e0aeccdb72ab4ad6e361dd0b4b87a7c05 100644 (file)
@@ -1245,7 +1245,7 @@ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv,
                return;
 
        /* Set the mac header as if we actually sent the packet uncoded */
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
        memcpy(ethhdr->h_source, ethhdr->h_dest, ETH_ALEN);
        memcpy(ethhdr->h_dest, eth_dst_new, ETH_ALEN);
 
@@ -1359,18 +1359,17 @@ static bool batadv_nc_skb_add_to_path(struct sk_buff *skb,
  *  buffer
  * @skb: data skb to forward
  * @neigh_node: next hop to forward packet to
- * @ethhdr: pointer to the ethernet header inside the skb
  *
  * Returns true if the skb was consumed (encoded packet sent) or false otherwise
  */
 bool batadv_nc_skb_forward(struct sk_buff *skb,
-                          struct batadv_neigh_node *neigh_node,
-                          struct ethhdr *ethhdr)
+                          struct batadv_neigh_node *neigh_node)
 {
        const struct net_device *netdev = neigh_node->if_incoming->soft_iface;
        struct batadv_priv *bat_priv = netdev_priv(netdev);
        struct batadv_unicast_packet *packet;
        struct batadv_nc_path *nc_path;
+       struct ethhdr *ethhdr = eth_hdr(skb);
        __be32 packet_id;
        u8 *payload;
 
@@ -1423,7 +1422,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
 {
        struct batadv_unicast_packet *packet;
        struct batadv_nc_path *nc_path;
-       struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       struct ethhdr *ethhdr = eth_hdr(skb);
        __be32 packet_id;
        u8 *payload;
 
@@ -1482,7 +1481,7 @@ out:
 void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
                                         struct sk_buff *skb)
 {
-       struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       struct ethhdr *ethhdr = eth_hdr(skb);
 
        if (batadv_is_my_mac(bat_priv, ethhdr->h_dest))
                return;
@@ -1533,7 +1532,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
        skb_reset_network_header(skb);
 
        /* Reconstruct original mac header */
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
        memcpy(ethhdr, &ethhdr_tmp, sizeof(*ethhdr));
 
        /* Select the correct unicast header information based on the location
@@ -1677,7 +1676,7 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
                return NET_RX_DROP;
 
        coded_packet = (struct batadv_coded_packet *)skb->data;
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        /* Verify frame is destined for us */
        if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest) &&
@@ -1763,6 +1762,13 @@ int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset)
                /* For each orig_node in this bin */
                rcu_read_lock();
                hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
+                       /* no need to print the orig node if it does not have
+                        * network coding neighbors
+                        */
+                       if (list_empty(&orig_node->in_coding_list) &&
+                           list_empty(&orig_node->out_coding_list))
+                               continue;
+
                        seq_printf(seq, "Node:      %pM\n", orig_node->orig);
 
                        seq_puts(seq, " Ingoing:  ");
index 4fa6d0caddbd394b69c46081c56f155c9665577f..85a4ec81ad50bda26449cfdadbcaf28e62391b8b 100644 (file)
@@ -36,8 +36,7 @@ void batadv_nc_purge_orig(struct batadv_priv *bat_priv,
 void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv);
 void batadv_nc_init_orig(struct batadv_orig_node *orig_node);
 bool batadv_nc_skb_forward(struct sk_buff *skb,
-                          struct batadv_neigh_node *neigh_node,
-                          struct ethhdr *ethhdr);
+                          struct batadv_neigh_node *neigh_node);
 void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
                                      struct sk_buff *skb);
 void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
@@ -87,8 +86,7 @@ static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
 }
 
 static inline bool batadv_nc_skb_forward(struct sk_buff *skb,
-                                        struct batadv_neigh_node *neigh_node,
-                                        struct ethhdr *ethhdr)
+                                        struct batadv_neigh_node *neigh_node)
 {
        return false;
 }
index fad1a2093e15fee8889bb190fac96868143bd0f5..f50553a7de629a411d94d307ba2ea54327e7b28f 100644 (file)
@@ -92,7 +92,7 @@ batadv_orig_node_get_router(struct batadv_orig_node *orig_node)
 
 struct batadv_neigh_node *
 batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
-                     const uint8_t *neigh_addr, uint32_t seqno)
+                     const uint8_t *neigh_addr)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
        struct batadv_neigh_node *neigh_node;
@@ -110,8 +110,8 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
        atomic_set(&neigh_node->refcount, 2);
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                  "Creating new neighbor %pM, initial seqno %d\n",
-                  neigh_addr, seqno);
+                  "Creating new neighbor %pM on interface %s\n", neigh_addr,
+                  hard_iface->net_dev->name);
 
 out:
        return neigh_node;
index 734e5a3d8a5b29fdf389b04db14e3a37504cf3cb..7887b84a9af43adbff91cb8e3695b7f29c36a399 100644 (file)
@@ -31,7 +31,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
                                              const uint8_t *addr);
 struct batadv_neigh_node *
 batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
-                     const uint8_t *neigh_addr, uint32_t seqno);
+                     const uint8_t *neigh_addr);
 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);
diff --git a/net/batman-adv/ring_buffer.c b/net/batman-adv/ring_buffer.c
deleted file mode 100644 (file)
index ccab0bb..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
- *
- * Marek Lindner
- *
- * 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-1301, USA
- */
-
-#include "main.h"
-#include "ring_buffer.h"
-
-void batadv_ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index,
-                           uint8_t value)
-{
-       lq_recv[*lq_index] = value;
-       *lq_index = (*lq_index + 1) % BATADV_TQ_GLOBAL_WINDOW_SIZE;
-}
-
-uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[])
-{
-       const uint8_t *ptr;
-       uint16_t count = 0, i = 0, sum = 0;
-
-       ptr = lq_recv;
-
-       while (i < BATADV_TQ_GLOBAL_WINDOW_SIZE) {
-               if (*ptr != 0) {
-                       count++;
-                       sum += *ptr;
-               }
-
-               i++;
-               ptr++;
-       }
-
-       if (count == 0)
-               return 0;
-
-       return (uint8_t)(sum / count);
-}
diff --git a/net/batman-adv/ring_buffer.h b/net/batman-adv/ring_buffer.h
deleted file mode 100644 (file)
index 3f92ae2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
- *
- * Marek Lindner
- *
- * 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-1301, USA
- */
-
-#ifndef _NET_BATMAN_ADV_RING_BUFFER_H_
-#define _NET_BATMAN_ADV_RING_BUFFER_H_
-
-void batadv_ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index,
-                           uint8_t value);
-uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[]);
-
-#endif /* _NET_BATMAN_ADV_RING_BUFFER_H_ */
index b27a4d792d1537fe2f53a492b6f3b19992e5dbc0..2f0bd3ffe6e8588cb1bf3f75d1dbc3d6b427f331 100644 (file)
 static int batadv_route_unicast_packet(struct sk_buff *skb,
                                       struct batadv_hard_iface *recv_if);
 
-void batadv_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
-{
-       struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
-       struct batadv_hashtable *hash = bat_priv->orig_hash;
-       struct hlist_head *head;
-       struct batadv_orig_node *orig_node;
-       unsigned long *word;
-       uint32_t i;
-       size_t word_index;
-       uint8_t *w;
-
-       for (i = 0; i < hash->size; i++) {
-               head = &hash->table[i];
-
-               rcu_read_lock();
-               hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
-                       spin_lock_bh(&orig_node->ogm_cnt_lock);
-                       word_index = hard_iface->if_num * BATADV_NUM_WORDS;
-                       word = &(orig_node->bcast_own[word_index]);
-
-                       batadv_bit_get_packet(bat_priv, word, 1, 0);
-                       w = &orig_node->bcast_own_sum[hard_iface->if_num];
-                       *w = bitmap_weight(word, BATADV_TQ_LOCAL_WINDOW_SIZE);
-                       spin_unlock_bh(&orig_node->ogm_cnt_lock);
-               }
-               rcu_read_unlock();
-       }
-}
-
 static void _batadv_update_route(struct batadv_priv *bat_priv,
                                 struct batadv_orig_node *orig_node,
                                 struct batadv_neigh_node *neigh_node)
@@ -256,7 +227,7 @@ bool batadv_check_management_packet(struct sk_buff *skb,
        if (unlikely(!pskb_may_pull(skb, header_len)))
                return false;
 
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        /* packet with broadcast indication but unicast recipient */
        if (!is_broadcast_ether_addr(ethhdr->h_dest))
@@ -314,7 +285,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
        icmp_packet->msg_type = BATADV_ECHO_REPLY;
        icmp_packet->header.ttl = BATADV_TTL;
 
-       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = NET_RX_SUCCESS;
 
 out:
@@ -362,7 +333,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
        icmp_packet->header.ttl = BATADV_TTL;
 
-       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = NET_RX_SUCCESS;
 
 out:
@@ -392,7 +363,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        if (unlikely(!pskb_may_pull(skb, hdr_size)))
                goto out;
 
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        /* packet with unicast indication but broadcast recipient */
        if (is_broadcast_ether_addr(ethhdr->h_dest))
@@ -439,7 +410,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        icmp_packet->header.ttl--;
 
        /* route it */
-       if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+       if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
                ret = NET_RX_SUCCESS;
 
 out:
@@ -569,7 +540,7 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
        if (unlikely(!pskb_may_pull(skb, hdr_size)))
                return -ENODATA;
 
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        /* packet with unicast indication but broadcast recipient */
        if (is_broadcast_ether_addr(ethhdr->h_dest))
@@ -803,8 +774,8 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
        struct batadv_orig_node *orig_node = NULL;
        struct batadv_neigh_node *neigh_node = NULL;
        struct batadv_unicast_packet *unicast_packet;
-       struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
-       int ret = NET_RX_DROP;
+       struct ethhdr *ethhdr = eth_hdr(skb);
+       int res, ret = NET_RX_DROP;
        struct sk_buff *new_skb;
 
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
@@ -864,16 +835,19 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
        /* decrement ttl */
        unicast_packet->header.ttl--;
 
-       /* network code packet if possible */
-       if (batadv_nc_skb_forward(skb, neigh_node, ethhdr)) {
-               ret = NET_RX_SUCCESS;
-       } else if (batadv_send_skb_to_orig(skb, orig_node, recv_if)) {
-               ret = NET_RX_SUCCESS;
+       res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
 
-               /* Update stats counter */
+       /* translate transmit result into receive result */
+       if (res == NET_XMIT_SUCCESS) {
+               /* skb was transmitted and consumed */
                batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
                batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
                                   skb->len + ETH_HLEN);
+
+               ret = NET_RX_SUCCESS;
+       } else if (res == NET_XMIT_POLICED) {
+               /* skb was buffered and consumed */
+               ret = NET_RX_SUCCESS;
        }
 
 out:
@@ -1165,7 +1139,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
        if (unlikely(!pskb_may_pull(skb, hdr_size)))
                goto out;
 
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        /* packet with broadcast indication but unicast recipient */
        if (!is_broadcast_ether_addr(ethhdr->h_dest))
@@ -1265,7 +1239,7 @@ int batadv_recv_vis_packet(struct sk_buff *skb,
                return NET_RX_DROP;
 
        vis_packet = (struct batadv_vis_packet *)skb->data;
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        /* not for me */
        if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
index 99eeafaba4075a37df1562e7e1b890b6a717fb71..72a29bde201022300194422a9caff389ab409731 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef _NET_BATMAN_ADV_ROUTING_H_
 #define _NET_BATMAN_ADV_ROUTING_H_
 
-void batadv_slide_own_bcast_window(struct batadv_hard_iface *hard_iface);
 bool batadv_check_management_packet(struct sk_buff *skb,
                                    struct batadv_hard_iface *hard_iface,
                                    int header_len);
index 263cfd1ccee78dfdf66c0f102d66301b8700a46d..e9ff8d801201279eaf91f347c730dbdd9e17f13d 100644 (file)
@@ -61,7 +61,7 @@ int batadv_send_skb_packet(struct sk_buff *skb,
 
        skb_reset_mac_header(skb);
 
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
        memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN);
        memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
        ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
@@ -96,26 +96,37 @@ send_skb_err:
  * host, NULL can be passed as recv_if and no interface alternating is
  * attempted.
  *
- * Returns TRUE on success; FALSE otherwise.
+ * Returns NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or
+ * NET_XMIT_POLICED if the skb is buffered for later transmit.
  */
-bool batadv_send_skb_to_orig(struct sk_buff *skb,
-                            struct batadv_orig_node *orig_node,
-                            struct batadv_hard_iface *recv_if)
+int batadv_send_skb_to_orig(struct sk_buff *skb,
+                           struct batadv_orig_node *orig_node,
+                           struct batadv_hard_iface *recv_if)
 {
        struct batadv_priv *bat_priv = orig_node->bat_priv;
        struct batadv_neigh_node *neigh_node;
+       int ret = NET_XMIT_DROP;
 
        /* batadv_find_router() increases neigh_nodes refcount if found. */
        neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
        if (!neigh_node)
-               return false;
+               return ret;
 
-       /* route it */
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+       /* try to network code the packet, if it is received on an interface
+        * (i.e. being forwarded). If the packet originates from this node or if
+        * network coding fails, then send the packet as usual.
+        */
+       if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) {
+               ret = NET_XMIT_POLICED;
+       } else {
+               batadv_send_skb_packet(skb, neigh_node->if_incoming,
+                                      neigh_node->addr);
+               ret = NET_XMIT_SUCCESS;
+       }
 
        batadv_neigh_node_free_ref(neigh_node);
 
-       return true;
+       return ret;
 }
 
 void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
@@ -152,8 +163,6 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
                                 struct batadv_forw_packet *forw_packet,
                                 unsigned long send_time)
 {
-       INIT_HLIST_NODE(&forw_packet->list);
-
        /* add new packet to packet list */
        spin_lock_bh(&bat_priv->forw_bcast_list_lock);
        hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list);
@@ -260,6 +269,9 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
                if (hard_iface->soft_iface != soft_iface)
                        continue;
 
+               if (forw_packet->num_packets >= hard_iface->num_bcasts)
+                       continue;
+
                /* send a copy of the saved skb */
                skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
                if (skb1)
@@ -271,7 +283,7 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
        forw_packet->num_packets++;
 
        /* if we still have some more bcasts to send */
-       if (forw_packet->num_packets < 3) {
+       if (forw_packet->num_packets < BATADV_NUM_BCASTS_MAX) {
                _batadv_add_bcast_packet_to_list(bat_priv, forw_packet,
                                                 msecs_to_jiffies(5));
                return;
index 38e662f619ac6e45bebed3b982f444396ea94bd8..e7b17880fca4f46ef77783034e58ae1eeb00b641 100644 (file)
@@ -23,9 +23,9 @@
 int batadv_send_skb_packet(struct sk_buff *skb,
                           struct batadv_hard_iface *hard_iface,
                           const uint8_t *dst_addr);
-bool batadv_send_skb_to_orig(struct sk_buff *skb,
-                            struct batadv_orig_node *orig_node,
-                            struct batadv_hard_iface *recv_if);
+int batadv_send_skb_to_orig(struct sk_buff *skb,
+                           struct batadv_orig_node *orig_node,
+                           struct batadv_hard_iface *recv_if);
 void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface);
 int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
                                    const struct sk_buff *skb,
index 819dfb006cdfafbcd3c63d12c5f7e76c0588ed43..700d0b49742da54d0a1280b84c87416977d7d721 100644 (file)
@@ -154,7 +154,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
                                                    0x00, 0x00};
        unsigned int header_len = 0;
        int data_len = skb->len, ret;
-       short vid __maybe_unused = -1;
+       unsigned short vid __maybe_unused = BATADV_NO_FLAGS;
        bool do_bcast = false;
        uint32_t seqno;
        unsigned long brd_delay = 1;
@@ -303,7 +303,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
        struct ethhdr *ethhdr;
        struct vlan_ethhdr *vhdr;
        struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
-       short vid __maybe_unused = -1;
+       unsigned short vid __maybe_unused = BATADV_NO_FLAGS;
        __be16 ethertype = __constant_htons(ETH_P_BATMAN);
        bool is_bcast;
 
@@ -316,7 +316,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
        skb_pull_rcsum(skb, hdr_size);
        skb_reset_mac_header(skb);
 
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
+       ethhdr = eth_hdr(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
        case ETH_P_8021Q:
index 9e87485758455743984bf51bf783c7bf61cee348..429aeef3d8b2d98e86e5e0772496d6796dc86798 100644 (file)
@@ -163,10 +163,19 @@ batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
        call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
 }
 
+/**
+ * batadv_tt_local_event - store a local TT event (ADD/DEL)
+ * @bat_priv: the bat priv with all the soft interface information
+ * @tt_local_entry: the TT entry involved in the event
+ * @event_flags: flags to store in the event structure
+ */
 static void batadv_tt_local_event(struct batadv_priv *bat_priv,
-                                 const uint8_t *addr, uint8_t flags)
+                                 struct batadv_tt_local_entry *tt_local_entry,
+                                 uint8_t event_flags)
 {
        struct batadv_tt_change_node *tt_change_node, *entry, *safe;
+       struct batadv_tt_common_entry *common = &tt_local_entry->common;
+       uint8_t flags = common->flags | event_flags;
        bool event_removed = false;
        bool del_op_requested, del_op_entry;
 
@@ -176,7 +185,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
                return;
 
        tt_change_node->change.flags = flags;
-       memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
+       memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
 
        del_op_requested = flags & BATADV_TT_CLIENT_DEL;
 
@@ -184,7 +193,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
        spin_lock_bh(&bat_priv->tt.changes_list_lock);
        list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
                                 list) {
-               if (!batadv_compare_eth(entry->change.addr, addr))
+               if (!batadv_compare_eth(entry->change.addr, common->addr))
                        continue;
 
                /* DEL+ADD in the same orig interval have no effect and can be
@@ -332,7 +341,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
        }
 
 add_event:
-       batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
+       batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
 
 check_roaming:
        /* Check whether it is a roaming, but don't do anything if the roaming
@@ -529,8 +538,7 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
                            struct batadv_tt_local_entry *tt_local_entry,
                            uint16_t flags, const char *message)
 {
-       batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
-                             tt_local_entry->common.flags | flags);
+       batadv_tt_local_event(bat_priv, tt_local_entry, flags);
 
        /* The local client has to be marked as "pending to be removed" but has
         * to be kept in the table in order to send it in a full table
@@ -584,8 +592,7 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
        /* if this client has been added right now, it is possible to
         * immediately purge it
         */
-       batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
-                             curr_flags | BATADV_TT_CLIENT_DEL);
+       batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
        hlist_del_rcu(&tt_local_entry->common.hash_entry);
        batadv_tt_local_entry_free_ref(tt_local_entry);
 
@@ -791,10 +798,25 @@ out:
                batadv_tt_orig_list_entry_free_ref(orig_entry);
 }
 
-/* caller must hold orig_node refcount */
+/**
+ * batadv_tt_global_add - add a new TT global entry or update an existing one
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: the originator announcing the client
+ * @tt_addr: the mac address of the non-mesh client
+ * @flags: TT flags that have to be set for this non-mesh client
+ * @ttvn: the tt version number ever announcing this non-mesh client
+ *
+ * Add a new TT global entry for the given originator. If the entry already
+ * exists add a new reference to the given originator (a global entry can have
+ * references to multiple originators) and adjust the flags attribute to reflect
+ * the function argument.
+ * If a TT local entry exists for this non-mesh client remove it.
+ *
+ * The caller must hold orig_node refcount.
+ */
 int batadv_tt_global_add(struct batadv_priv *bat_priv,
                         struct batadv_orig_node *orig_node,
-                        const unsigned char *tt_addr, uint8_t flags,
+                        const unsigned char *tt_addr, uint16_t flags,
                         uint8_t ttvn)
 {
        struct batadv_tt_global_entry *tt_global_entry;
@@ -1600,11 +1622,11 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
        tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
        len = tt_query_size + tt_len;
-       skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
+       skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
        if (!skb)
                goto out;
 
-       skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+       skb_reserve(skb, ETH_HLEN);
        tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
        tt_response->ttvn = ttvn;
 
@@ -1665,11 +1687,11 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
        if (!tt_req_node)
                goto out;
 
-       skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN);
+       skb = netdev_alloc_skb_ip_align(NULL, sizeof(*tt_request) + ETH_HLEN);
        if (!skb)
                goto out;
 
-       skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+       skb_reserve(skb, ETH_HLEN);
 
        tt_req_len = sizeof(*tt_request);
        tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
@@ -1691,7 +1713,7 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
 
-       if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL))
+       if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL) != NET_XMIT_DROP)
                ret = 0;
 
 out:
@@ -1715,7 +1737,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
        struct batadv_orig_node *req_dst_orig_node;
        struct batadv_orig_node *res_dst_orig_node = NULL;
        uint8_t orig_ttvn, req_ttvn, ttvn;
-       int ret = false;
+       int res, ret = false;
        unsigned char *tt_buff;
        bool full_table;
        uint16_t tt_len, tt_tot;
@@ -1762,11 +1784,11 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
                tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
                len = sizeof(*tt_response) + tt_len;
-               skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
+               skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
                if (!skb)
                        goto unlock;
 
-               skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+               skb_reserve(skb, ETH_HLEN);
                packet_pos = skb_put(skb, len);
                tt_response = (struct batadv_tt_query_packet *)packet_pos;
                tt_response->ttvn = req_ttvn;
@@ -1810,8 +1832,10 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
 
-       if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL))
+       res = batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL);
+       if (res != NET_XMIT_DROP)
                ret = true;
+
        goto out;
 
 unlock:
@@ -1878,11 +1902,11 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
                tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
                len = sizeof(*tt_response) + tt_len;
-               skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
+               skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
                if (!skb)
                        goto unlock;
 
-               skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+               skb_reserve(skb, ETH_HLEN);
                packet_pos = skb_put(skb, len);
                tt_response = (struct batadv_tt_query_packet *)packet_pos;
                tt_response->ttvn = req_ttvn;
@@ -1925,7 +1949,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
 
-       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = true;
        goto out;
 
@@ -2212,11 +2236,11 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
        if (!batadv_tt_check_roam_count(bat_priv, client))
                goto out;
 
-       skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN);
+       skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
        if (!skb)
                goto out;
 
-       skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+       skb_reserve(skb, ETH_HLEN);
 
        roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
 
@@ -2238,7 +2262,7 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
 
-       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = 0;
 
 out:
index ab8e683b402f0686a6e1ffe4168f99961c898bc4..659a3bb759ce87087c4d5697239f4724c815971c 100644 (file)
@@ -33,7 +33,7 @@ void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
                               const unsigned char *tt_buff, int tt_buff_len);
 int batadv_tt_global_add(struct batadv_priv *bat_priv,
                         struct batadv_orig_node *orig_node,
-                        const unsigned char *addr, uint8_t flags,
+                        const unsigned char *addr, uint16_t flags,
                         uint8_t ttvn);
 int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
 void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
index aba8364c368991935ab5f9899266a6662f925618..b2c94e1393191e00165e42e117ded3dd2374f70f 100644 (file)
@@ -61,6 +61,7 @@ struct batadv_hard_iface_bat_iv {
  * @if_status: status of the interface for batman-adv
  * @net_dev: pointer to the net_device
  * @frag_seqno: last fragment sequence number sent by this interface
+ * @num_bcasts: number of payload re-broadcasts on this interface (ARQ)
  * @hardif_obj: kobject of the per interface sysfs "mesh" directory
  * @refcount: number of contexts the object is used
  * @batman_adv_ptype: packet type describing packets that should be processed by
@@ -76,6 +77,7 @@ struct batadv_hard_iface {
        char if_status;
        struct net_device *net_dev;
        atomic_t frag_seqno;
+       uint8_t num_bcasts;
        struct kobject *hardif_obj;
        atomic_t refcount;
        struct packet_type batman_adv_ptype;
@@ -640,7 +642,7 @@ struct batadv_socket_packet {
 #ifdef CONFIG_BATMAN_ADV_BLA
 struct batadv_bla_backbone_gw {
        uint8_t orig[ETH_ALEN];
-       short vid;
+       unsigned short vid;
        struct hlist_node hash_entry;
        struct batadv_priv *bat_priv;
        unsigned long lasttime;
@@ -663,7 +665,7 @@ struct batadv_bla_backbone_gw {
  */
 struct batadv_bla_claim {
        uint8_t addr[ETH_ALEN];
-       short vid;
+       unsigned short vid;
        struct batadv_bla_backbone_gw *backbone_gw;
        unsigned long lasttime;
        struct hlist_node hash_entry;
index 0bb3b5982f94c9480741ad224594e7b0a9143e0f..dc8b5d4dd636d3d5ed982a5d93c2783f203ac4f5 100644 (file)
@@ -464,7 +464,7 @@ find_router:
                goto out;
        }
 
-       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = 0;
 
 out:
index 1625e5793a895d02aec97966f901ccfb8a29e4ab..4983340f1943c5a0cc491785bf835981e7c44a1a 100644 (file)
@@ -392,12 +392,12 @@ batadv_add_packet(struct batadv_priv *bat_priv,
                return NULL;
 
        len = sizeof(*packet) + vis_info_len;
-       info->skb_packet = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
+       info->skb_packet = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
        if (!info->skb_packet) {
                kfree(info);
                return NULL;
        }
-       skb_reserve(info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
+       skb_reserve(info->skb_packet, ETH_HLEN);
        packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len);
 
        kref_init(&info->refcount);
@@ -697,7 +697,7 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
        struct batadv_orig_node *orig_node;
        struct batadv_vis_packet *packet;
        struct sk_buff *skb;
-       uint32_t i;
+       uint32_t i, res;
 
 
        packet = (struct batadv_vis_packet *)info->skb_packet->data;
@@ -724,7 +724,8 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
                        if (!skb)
                                continue;
 
-                       if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
+                       res = batadv_send_skb_to_orig(skb, orig_node, NULL);
+                       if (res == NET_XMIT_DROP)
                                kfree_skb(skb);
                }
                rcu_read_unlock();
@@ -748,7 +749,7 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
        if (!skb)
                goto out;
 
-       if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL) == NET_XMIT_DROP)
                kfree_skb(skb);
 
 out:
@@ -854,13 +855,13 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
        if (!bat_priv->vis.my_info)
                goto err;
 
-       len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE;
-       len += ETH_HLEN + NET_IP_ALIGN;
-       bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len);
+       len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
+       bat_priv->vis.my_info->skb_packet = netdev_alloc_skb_ip_align(NULL,
+                                                                     len);
        if (!bat_priv->vis.my_info->skb_packet)
                goto free_info;
 
-       skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
+       skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
        tmp_skb = bat_priv->vis.my_info->skb_packet;
        packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
 
index 967312803e4130f4e27712daed6d9dd9e2a1a9d6..75f3239130f8d8dd9082eac302aafd08c1beeeb7 100644 (file)
@@ -22,6 +22,9 @@
 #include <asm/uaccess.h>
 #include "br_private.h"
 
+#define COMMON_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | \
+                        NETIF_F_GSO_MASK | NETIF_F_HW_CSUM)
+
 /* net device transmit always called with BH disabled */
 netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
@@ -346,12 +349,10 @@ void br_dev_setup(struct net_device *dev)
        dev->tx_queue_len = 0;
        dev->priv_flags = IFF_EBRIDGE;
 
-       dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
-                       NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | NETIF_F_LLTX |
-                       NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_CTAG_TX;
-       dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
-                          NETIF_F_GSO_MASK | NETIF_F_HW_CSUM |
-                          NETIF_F_HW_VLAN_CTAG_TX;
+       dev->features = COMMON_FEATURES | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL |
+                       NETIF_F_HW_VLAN_CTAG_TX;
+       dev->hw_features = COMMON_FEATURES | NETIF_F_HW_VLAN_CTAG_TX;
+       dev->vlan_features = COMMON_FEATURES;
 
        br->dev = dev;
        spin_lock_init(&br->lock);
index 81f2389f78eb884e80cafbd624d3029aa48e3ed1..37a467697967699e976cd481fe98ef25de5e36c2 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
+#include <linux/inetdevice.h>
 #include <net/ip.h>
 #if IS_ENABLED(CONFIG_IPV6)
 #include <net/ipv6.h>
@@ -381,7 +382,8 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
        iph->frag_off = htons(IP_DF);
        iph->ttl = 1;
        iph->protocol = IPPROTO_IGMP;
-       iph->saddr = 0;
+       iph->saddr = br->multicast_query_use_ifaddr ?
+                    inet_select_addr(br->dev, 0, RT_SCOPE_LINK) : 0;
        iph->daddr = htonl(INADDR_ALLHOSTS_GROUP);
        ((u8 *)&iph[1])[0] = IPOPT_RA;
        ((u8 *)&iph[1])[1] = 4;
@@ -615,8 +617,6 @@ rehash:
 
        mp->br = br;
        mp->addr = *group;
-       setup_timer(&mp->timer, br_multicast_group_expired,
-                   (unsigned long)mp);
 
        hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]);
        mdb->size++;
@@ -654,7 +654,6 @@ static int br_multicast_add_group(struct net_bridge *br,
        struct net_bridge_mdb_entry *mp;
        struct net_bridge_port_group *p;
        struct net_bridge_port_group __rcu **pp;
-       unsigned long now = jiffies;
        int err;
 
        spin_lock(&br->multicast_lock);
@@ -669,7 +668,6 @@ static int br_multicast_add_group(struct net_bridge *br,
 
        if (!port) {
                mp->mglist = true;
-               mod_timer(&mp->timer, now + br->multicast_membership_interval);
                goto out;
        }
 
@@ -677,7 +675,7 @@ static int br_multicast_add_group(struct net_bridge *br,
             (p = mlock_dereference(*pp, br)) != NULL;
             pp = &p->next) {
                if (p->port == port)
-                       goto found;
+                       goto out;
                if ((unsigned long)p->port < (unsigned long)port)
                        break;
        }
@@ -688,8 +686,6 @@ static int br_multicast_add_group(struct net_bridge *br,
        rcu_assign_pointer(*pp, p);
        br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
 
-found:
-       mod_timer(&p->timer, now + br->multicast_membership_interval);
 out:
        err = 0;
 
@@ -1129,6 +1125,10 @@ static int br_ip4_multicast_query(struct net_bridge *br,
        if (!mp)
                goto out;
 
+       setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp);
+       mod_timer(&mp->timer, now + br->multicast_membership_interval);
+       mp->timer_armed = true;
+
        max_delay *= br->multicast_last_member_count;
 
        if (mp->mglist &&
@@ -1203,6 +1203,10 @@ static int br_ip6_multicast_query(struct net_bridge *br,
        if (!mp)
                goto out;
 
+       setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp);
+       mod_timer(&mp->timer, now + br->multicast_membership_interval);
+       mp->timer_armed = true;
+
        max_delay *= br->multicast_last_member_count;
        if (mp->mglist &&
            (timer_pending(&mp->timer) ?
@@ -1246,6 +1250,32 @@ static void br_multicast_leave_group(struct net_bridge *br,
        if (!mp)
                goto out;
 
+       if (br->multicast_querier &&
+           !timer_pending(&br->multicast_querier_timer)) {
+               __br_multicast_send_query(br, port, &mp->addr);
+
+               time = jiffies + br->multicast_last_member_count *
+                                br->multicast_last_member_interval;
+               mod_timer(port ? &port->multicast_query_timer :
+                                &br->multicast_query_timer, time);
+
+               for (p = mlock_dereference(mp->ports, br);
+                    p != NULL;
+                    p = mlock_dereference(p->next, br)) {
+                       if (p->port != port)
+                               continue;
+
+                       if (!hlist_unhashed(&p->mglist) &&
+                           (timer_pending(&p->timer) ?
+                            time_after(p->timer.expires, time) :
+                            try_to_del_timer_sync(&p->timer) >= 0)) {
+                               mod_timer(&p->timer, time);
+                       }
+
+                       break;
+               }
+       }
+
        if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
                struct net_bridge_port_group __rcu **pp;
 
@@ -1261,7 +1291,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
                        call_rcu_bh(&p->rcu, br_multicast_free_pg);
                        br_mdb_notify(br->dev, port, group, RTM_DELMDB);
 
-                       if (!mp->ports && !mp->mglist &&
+                       if (!mp->ports && !mp->mglist && mp->timer_armed &&
                            netif_running(br->dev))
                                mod_timer(&mp->timer, jiffies);
                }
@@ -1273,30 +1303,12 @@ static void br_multicast_leave_group(struct net_bridge *br,
                     br->multicast_last_member_interval;
 
        if (!port) {
-               if (mp->mglist &&
+               if (mp->mglist && mp->timer_armed &&
                    (timer_pending(&mp->timer) ?
                     time_after(mp->timer.expires, time) :
                     try_to_del_timer_sync(&mp->timer) >= 0)) {
                        mod_timer(&mp->timer, time);
                }
-
-               goto out;
-       }
-
-       for (p = mlock_dereference(mp->ports, br);
-            p != NULL;
-            p = mlock_dereference(p->next, br)) {
-               if (p->port != port)
-                       continue;
-
-               if (!hlist_unhashed(&p->mglist) &&
-                   (timer_pending(&p->timer) ?
-                    time_after(p->timer.expires, time) :
-                    try_to_del_timer_sync(&p->timer) >= 0)) {
-                       mod_timer(&p->timer, time);
-               }
-
-               break;
        }
 
 out:
@@ -1618,6 +1630,7 @@ void br_multicast_init(struct net_bridge *br)
 
        br->multicast_router = 1;
        br->multicast_querier = 0;
+       br->multicast_query_use_ifaddr = 0;
        br->multicast_last_member_count = 2;
        br->multicast_startup_query_count = 2;
 
@@ -1671,6 +1684,7 @@ void br_multicast_stop(struct net_bridge *br)
                hlist_for_each_entry_safe(mp, n, &mdb->mhash[i],
                                          hlist[ver]) {
                        del_timer(&mp->timer);
+                       mp->timer_armed = false;
                        call_rcu_bh(&mp->rcu, br_multicast_free_group);
                }
        }
index 1644b3e1f947a554f944b3e6cf655a0346d7dc66..3a3f371b28415c110e4db6a21069f9153dafe904 100644 (file)
@@ -31,7 +31,7 @@ struct notifier_block br_device_notifier = {
  */
 static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net_bridge_port *p;
        struct net_bridge *br;
        bool changed_addr;
index d2c043a857b6a0fd3bfd208f018179b96c42dacd..1b0ac95a5c37dfd31893c1d330331a6ef318ec04 100644 (file)
@@ -112,6 +112,7 @@ struct net_bridge_mdb_entry
        struct timer_list               timer;
        struct br_ip                    addr;
        bool                            mglist;
+       bool                            timer_armed;
 };
 
 struct net_bridge_mdb_htable
@@ -249,6 +250,7 @@ struct net_bridge
 
        u8                              multicast_disabled:1;
        u8                              multicast_querier:1;
+       u8                              multicast_query_use_ifaddr:1;
 
        u32                             hash_elasticity;
        u32                             hash_max;
index 8baa9c08e1a4b1442d4d99e4d448f25b03685e47..394bb96b608707aa1ab943f66bc52fa173859706 100644 (file)
@@ -375,6 +375,31 @@ static ssize_t store_multicast_snooping(struct device *d,
 static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR,
                   show_multicast_snooping, store_multicast_snooping);
 
+static ssize_t show_multicast_query_use_ifaddr(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);
+}
+
+static int set_query_use_ifaddr(struct net_bridge *br, unsigned long val)
+{
+       br->multicast_query_use_ifaddr = !!val;
+       return 0;
+}
+
+static ssize_t
+store_multicast_query_use_ifaddr(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 ssize_t show_multicast_querier(struct device *d,
                                      struct device_attribute *attr,
                                      char *buf)
@@ -734,6 +759,7 @@ static struct attribute *bridge_attrs[] = {
        &dev_attr_multicast_router.attr,
        &dev_attr_multicast_snooping.attr,
        &dev_attr_multicast_querier.attr,
+       &dev_attr_multicast_query_use_ifaddr.attr,
        &dev_attr_hash_elasticity.attr,
        &dev_attr_hash_max.attr,
        &dev_attr_multicast_last_member_count.attr,
index 1f9ece1a9c344655708c7d0e015ed0a46dd56a03..4dca159435cfe17dcc09fadccfebee7ca49b1075 100644 (file)
@@ -352,9 +352,9 @@ EXPORT_SYMBOL(caif_enroll_dev);
 
 /* notify Caif of device events */
 static int caif_device_notify(struct notifier_block *me, unsigned long what,
-                             void *arg)
+                             void *ptr)
 {
-       struct net_device *dev = arg;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct caif_device_entry *caifd = NULL;
        struct caif_dev_common *caifdev;
        struct cfcnfg *cfg;
index 942e00a425fd9b015118cb7a0982209c1989003b..75ed04b78fa4090f69329cccd0cebd04bc516290 100644 (file)
@@ -121,9 +121,9 @@ static struct packet_type caif_usb_type __read_mostly = {
 };
 
 static int cfusbl_device_notify(struct notifier_block *me, unsigned long what,
-                               void *arg)
+                               void *ptr)
 {
-       struct net_device *dev = arg;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct caif_dev_common common;
        struct cflayer *layer, *link_support;
        struct usbnet *usbnet;
index c4e50852c9f4aa8e195ed57e711890210cea1e1c..3ab8dd2e12828fea31d97b59dbeb3fe7521e953b 100644 (file)
@@ -794,9 +794,9 @@ EXPORT_SYMBOL(can_proto_unregister);
  * af_can notifier to create/remove CAN netdevice specific structs
  */
 static int can_notifier(struct notifier_block *nb, unsigned long msg,
-                       void *data)
+                       void *ptr)
 {
-       struct net_device *dev = (struct net_device *)data;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct dev_rcv_lists *d;
 
        if (!net_eq(dev_net(dev), &init_net))
index 8f113e6ff32750d3809c3ab38117d6ad1ebc8f38..46f20bfafc0ed510421cf743ad3674efce803018 100644 (file)
@@ -1350,9 +1350,9 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock,
  * notification handler for netdevice status changes
  */
 static int bcm_notifier(struct notifier_block *nb, unsigned long msg,
-                       void *data)
+                       void *ptr)
 {
-       struct net_device *dev = (struct net_device *)data;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct bcm_sock *bo = container_of(nb, struct bcm_sock, notifier);
        struct sock *sk = &bo->sk;
        struct bcm_op *op;
index 3ee690e8c7d32354a525ad398291b7b7c5155215..2f291f961a170018f1464fb50f4faa272887a50d 100644 (file)
@@ -445,9 +445,9 @@ static inline void cgw_unregister_filter(struct cgw_job *gwj)
 }
 
 static int cgw_notifier(struct notifier_block *nb,
-                       unsigned long msg, void *data)
+                       unsigned long msg, void *ptr)
 {
-       struct net_device *dev = (struct net_device *)data;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (!net_eq(dev_net(dev), &init_net))
                return NOTIFY_DONE;
index 1085e65f848eab9a3a634ad16b37d70bd80830b5..641e1c895123ac114330635c43d0b2ed778c2ae7 100644 (file)
@@ -239,9 +239,9 @@ static int raw_enable_allfilters(struct net_device *dev, struct sock *sk)
 }
 
 static int raw_notifier(struct notifier_block *nb,
-                       unsigned long msg, void *data)
+                       unsigned long msg, void *ptr)
 {
-       struct net_device *dev = (struct net_device *)data;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct raw_sock *ro = container_of(nb, struct raw_sock, notifier);
        struct sock *sk = &ro->sk;
 
index fc1e289397f5895f3d2191ee78c9b450cc33e5cf..9c18557f93c6e6aee110a9160f4fe02fe240c4f9 100644 (file)
@@ -1198,9 +1198,7 @@ static int __dev_open(struct net_device *dev)
         * If we don't do this there is a chance ndo_poll_controller
         * or ndo_poll may be running while we open the device
         */
-       ret = netpoll_rx_disable(dev);
-       if (ret)
-               return ret;
+       netpoll_rx_disable(dev);
 
        ret = call_netdevice_notifiers(NETDEV_PRE_UP, dev);
        ret = notifier_to_errno(ret);
@@ -1309,9 +1307,7 @@ static int __dev_close(struct net_device *dev)
        LIST_HEAD(single);
 
        /* Temporarily disable netpoll until the interface is down */
-       retval = netpoll_rx_disable(dev);
-       if (retval)
-               return retval;
+       netpoll_rx_disable(dev);
 
        list_add(&dev->unreg_list, &single);
        retval = __dev_close_many(&single);
@@ -1353,14 +1349,11 @@ static int dev_close_many(struct list_head *head)
  */
 int dev_close(struct net_device *dev)
 {
-       int ret = 0;
        if (dev->flags & IFF_UP) {
                LIST_HEAD(single);
 
                /* Block netpoll rx while the interface is going down */
-               ret = netpoll_rx_disable(dev);
-               if (ret)
-                       return ret;
+               netpoll_rx_disable(dev);
 
                list_add(&dev->unreg_list, &single);
                dev_close_many(&single);
@@ -1368,7 +1361,7 @@ int dev_close(struct net_device *dev)
 
                netpoll_rx_enable(dev);
        }
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(dev_close);
 
@@ -1398,6 +1391,14 @@ void dev_disable_lro(struct net_device *dev)
 }
 EXPORT_SYMBOL(dev_disable_lro);
 
+static int call_netdevice_notifier(struct notifier_block *nb, unsigned long val,
+                                  struct net_device *dev)
+{
+       struct netdev_notifier_info info;
+
+       netdev_notifier_info_init(&info, dev);
+       return nb->notifier_call(nb, val, &info);
+}
 
 static int dev_boot_phase = 1;
 
@@ -1430,7 +1431,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
                goto unlock;
        for_each_net(net) {
                for_each_netdev(net, dev) {
-                       err = nb->notifier_call(nb, NETDEV_REGISTER, dev);
+                       err = call_netdevice_notifier(nb, NETDEV_REGISTER, dev);
                        err = notifier_to_errno(err);
                        if (err)
                                goto rollback;
@@ -1438,7 +1439,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
                        if (!(dev->flags & IFF_UP))
                                continue;
 
-                       nb->notifier_call(nb, NETDEV_UP, dev);
+                       call_netdevice_notifier(nb, NETDEV_UP, dev);
                }
        }
 
@@ -1454,10 +1455,11 @@ rollback:
                                goto outroll;
 
                        if (dev->flags & IFF_UP) {
-                               nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
-                               nb->notifier_call(nb, NETDEV_DOWN, dev);
+                               call_netdevice_notifier(nb, NETDEV_GOING_DOWN,
+                                                       dev);
+                               call_netdevice_notifier(nb, NETDEV_DOWN, dev);
                        }
-                       nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+                       call_netdevice_notifier(nb, NETDEV_UNREGISTER, dev);
                }
        }
 
@@ -1495,10 +1497,11 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
        for_each_net(net) {
                for_each_netdev(net, dev) {
                        if (dev->flags & IFF_UP) {
-                               nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
-                               nb->notifier_call(nb, NETDEV_DOWN, dev);
+                               call_netdevice_notifier(nb, NETDEV_GOING_DOWN,
+                                                       dev);
+                               call_netdevice_notifier(nb, NETDEV_DOWN, dev);
                        }
-                       nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+                       call_netdevice_notifier(nb, NETDEV_UNREGISTER, dev);
                }
        }
 unlock:
@@ -1507,6 +1510,25 @@ unlock:
 }
 EXPORT_SYMBOL(unregister_netdevice_notifier);
 
+/**
+ *     call_netdevice_notifiers_info - call all network notifier blocks
+ *     @val: value passed unmodified to notifier function
+ *     @dev: net_device pointer passed unmodified to notifier function
+ *     @info: notifier information data
+ *
+ *     Call all network notifier blocks.  Parameters and return value
+ *     are as for raw_notifier_call_chain().
+ */
+
+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
  *      @val: value passed unmodified to notifier function
@@ -1518,8 +1540,9 @@ EXPORT_SYMBOL(unregister_netdevice_notifier);
 
 int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
 {
-       ASSERT_RTNL();
-       return raw_notifier_call_chain(&netdev_chain, val, dev);
+       struct netdev_notifier_info info;
+
+       return call_netdevice_notifiers_info(val, dev, &info);
 }
 EXPORT_SYMBOL(call_netdevice_notifiers);
 
@@ -1629,7 +1652,6 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
                return NET_RX_DROP;
        }
        skb->skb_iif = 0;
-       skb->dev = dev;
        skb_dst_drop(skb);
        skb->tstamp.tv64 = 0;
        skb->pkt_type = PACKET_HOST;
@@ -1702,7 +1724,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
                        skb_reset_mac_header(skb2);
 
                        if (skb_network_header(skb2) < skb2->data ||
-                           skb2->network_header > skb2->tail) {
+                           skb_network_header(skb2) > skb_tail_pointer(skb2)) {
                                net_crit_ratelimited("protocol %04x is buggy, dev %s\n",
                                                     ntohs(skb2->protocol),
                                                     dev->name);
@@ -3065,6 +3087,46 @@ static int rps_ipi_queued(struct softnet_data *sd)
        return 0;
 }
 
+#ifdef CONFIG_NET_FLOW_LIMIT
+int netdev_flow_limit_table_len __read_mostly = (1 << 12);
+#endif
+
+static bool skb_flow_limit(struct sk_buff *skb, unsigned int qlen)
+{
+#ifdef CONFIG_NET_FLOW_LIMIT
+       struct sd_flow_limit *fl;
+       struct softnet_data *sd;
+       unsigned int old_flow, new_flow;
+
+       if (qlen < (netdev_max_backlog >> 1))
+               return false;
+
+       sd = &__get_cpu_var(softnet_data);
+
+       rcu_read_lock();
+       fl = rcu_dereference(sd->flow_limit);
+       if (fl) {
+               new_flow = skb_get_rxhash(skb) & (fl->num_buckets - 1);
+               old_flow = fl->history[fl->history_head];
+               fl->history[fl->history_head] = new_flow;
+
+               fl->history_head++;
+               fl->history_head &= FLOW_LIMIT_HISTORY - 1;
+
+               if (likely(fl->buckets[old_flow]))
+                       fl->buckets[old_flow]--;
+
+               if (++fl->buckets[new_flow] > (FLOW_LIMIT_HISTORY >> 1)) {
+                       fl->count++;
+                       rcu_read_unlock();
+                       return true;
+               }
+       }
+       rcu_read_unlock();
+#endif
+       return false;
+}
+
 /*
  * enqueue_to_backlog is called to queue an skb to a per CPU backlog
  * queue (may be a remote CPU queue).
@@ -3074,13 +3136,15 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
 {
        struct softnet_data *sd;
        unsigned long flags;
+       unsigned int qlen;
 
        sd = &per_cpu(softnet_data, cpu);
 
        local_irq_save(flags);
 
        rps_lock(sd);
-       if (skb_queue_len(&sd->input_pkt_queue) <= netdev_max_backlog) {
+       qlen = skb_queue_len(&sd->input_pkt_queue);
+       if (qlen <= netdev_max_backlog && !skb_flow_limit(skb, qlen)) {
                if (skb_queue_len(&sd->input_pkt_queue)) {
 enqueue:
                        __skb_queue_tail(&sd->input_pkt_queue, skb);
@@ -3828,7 +3892,7 @@ static void skb_gro_reset_offset(struct sk_buff *skb)
        NAPI_GRO_CB(skb)->frag0 = NULL;
        NAPI_GRO_CB(skb)->frag0_len = 0;
 
-       if (skb->mac_header == skb->tail &&
+       if (skb_mac_header(skb) == skb_tail_pointer(skb) &&
            pinfo->nr_frags &&
            !PageHighMem(skb_frag_page(frag0))) {
                NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
@@ -4370,7 +4434,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
        else
                list_add_tail_rcu(&upper->list, &dev->upper_dev_list);
        dev_hold(upper_dev);
-
+       call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
        return 0;
 }
 
@@ -4430,6 +4494,7 @@ void netdev_upper_dev_unlink(struct net_device *dev,
        list_del_rcu(&upper->list);
        dev_put(upper_dev);
        kfree_rcu(upper, rcu);
+       call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
 }
 EXPORT_SYMBOL(netdev_upper_dev_unlink);
 
@@ -4700,8 +4765,13 @@ void __dev_notify_flags(struct net_device *dev, unsigned int old_flags)
        }
 
        if (dev->flags & IFF_UP &&
-           (changes & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE)))
-               call_netdevice_notifiers(NETDEV_CHANGE, dev);
+           (changes & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE))) {
+               struct netdev_notifier_change_info change_info;
+
+               change_info.flags_changed = changes;
+               call_netdevice_notifiers_info(NETDEV_CHANGE, dev,
+                                             &change_info.info);
+       }
 }
 
 /**
@@ -5235,6 +5305,10 @@ int register_netdevice(struct net_device *dev)
         */
        dev->hw_enc_features |= NETIF_F_SG;
 
+       /* Make NETIF_F_SG inheritable to MPLS.
+        */
+       dev->mpls_features |= NETIF_F_SG;
+
        ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
        ret = notifier_to_errno(ret);
        if (ret)
@@ -6014,7 +6088,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all,
 }
 EXPORT_SYMBOL(netdev_increment_features);
 
-static struct hlist_head *netdev_create_hash(void)
+static struct hlist_head * __net_init netdev_create_hash(void)
 {
        int i;
        struct hlist_head *hash;
@@ -6270,6 +6344,10 @@ static int __init net_dev_init(void)
                sd->backlog.weight = weight_p;
                sd->backlog.gro_list = NULL;
                sd->backlog.gro_count = 0;
+
+#ifdef CONFIG_NET_FLOW_LIMIT
+               sd->flow_limit = NULL;
+#endif
        }
 
        dev_boot_phase = 0;
index d23b6682f4e95cfd029cd19db31252184ec03d2d..5e78d44333b9bc39fdb56fdd489d0ac4f7f5d4e8 100644 (file)
@@ -295,9 +295,9 @@ static int net_dm_cmd_trace(struct sk_buff *skb,
 }
 
 static int dropmon_net_event(struct notifier_block *ev_block,
-                       unsigned long event, void *ptr)
+                            unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct dm_hw_stat_delta *new_stat = NULL;
        struct dm_hw_stat_delta *tmp;
 
index df9cc810ec8e3a78bbdb3b4480deeb8fd35df721..ca4231ec734787be93c9ebc1e6c69d4a30bf24a5 100644 (file)
@@ -372,7 +372,7 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 static int dst_dev_event(struct notifier_block *this, unsigned long event,
                         void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct dst_entry *dst, *last = NULL;
 
        switch (event) {
index 22efdaa76ebf9909db7a69d59d54de191fd00d69..cd23d314d68ad2f23752034bdbd230b960e79d70 100644 (file)
@@ -82,6 +82,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
        [NETIF_F_FSO_BIT] =              "tx-fcoe-segmentation",
        [NETIF_F_GSO_GRE_BIT] =          "tx-gre-segmentation",
        [NETIF_F_GSO_UDP_TUNNEL_BIT] =   "tx-udp_tnl-segmentation",
+       [NETIF_F_GSO_MPLS_BIT] =         "tx-mpls-segmentation",
 
        [NETIF_F_FCOE_CRC_BIT] =         "tx-checksum-fcoe-crc",
        [NETIF_F_SCTP_CSUM_BIT] =        "tx-checksum-sctp",
@@ -1413,7 +1414,7 @@ static int ethtool_get_module_eeprom(struct net_device *dev,
                                      modinfo.eeprom_len);
 }
 
-/* The main entry point in this file.  Called from net/core/dev.c */
+/* The main entry point in this file.  Called from net/core/dev_ioctl.c */
 
 int dev_ethtool(struct net *net, struct ifreq *ifr)
 {
index d5a9f8ead0d864305110f2ca6f1dc70fca5b84cd..21735440c44a85b611308e6b3c97bef77452c9a1 100644 (file)
@@ -705,9 +705,9 @@ static void detach_rules(struct list_head *rules, struct net_device *dev)
 
 
 static int fib_rules_event(struct notifier_block *this, unsigned long event,
-                           void *ptr)
+                          void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
        struct fib_rules_ops *ops;
 
index 569d355fec3e8adac815c1819e43abbac98fcf39..2bf83299600a4ac8eb56069295bbc755709642b1 100644 (file)
@@ -146,11 +146,23 @@ static void softnet_seq_stop(struct seq_file *seq, void *v)
 static int softnet_seq_show(struct seq_file *seq, void *v)
 {
        struct softnet_data *sd = v;
+       unsigned int flow_limit_count = 0;
 
-       seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
+#ifdef CONFIG_NET_FLOW_LIMIT
+       struct sd_flow_limit *fl;
+
+       rcu_read_lock();
+       fl = rcu_dereference(sd->flow_limit);
+       if (fl)
+               flow_limit_count = fl->count;
+       rcu_read_unlock();
+#endif
+
+       seq_printf(seq,
+                  "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
                   sd->processed, sd->dropped, sd->time_squeeze, 0,
                   0, 0, 0, 0, /* was fastroute */
-                  sd->cpu_collision, sd->received_rps);
+                  sd->cpu_collision, sd->received_rps, flow_limit_count);
        return 0;
 }
 
index cec074be8c4378b56a01889165d55cc282808208..03c8ec3edc7208715f76ab06c68154de30d089af 100644 (file)
@@ -247,7 +247,7 @@ static void netpoll_poll_dev(struct net_device *dev)
        zap_completion_queue();
 }
 
-int netpoll_rx_disable(struct net_device *dev)
+void netpoll_rx_disable(struct net_device *dev)
 {
        struct netpoll_info *ni;
        int idx;
@@ -257,7 +257,6 @@ int netpoll_rx_disable(struct net_device *dev)
        if (ni)
                down(&ni->dev_lock);
        srcu_read_unlock(&netpoll_srcu, idx);
-       return 0;
 }
 EXPORT_SYMBOL(netpoll_rx_disable);
 
@@ -690,25 +689,20 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
                        send_skb->dev = skb->dev;
 
                        skb_reset_network_header(send_skb);
-                       skb_put(send_skb, sizeof(struct ipv6hdr));
-                       hdr = ipv6_hdr(send_skb);
-
+                       hdr = (struct ipv6hdr *) skb_put(send_skb, sizeof(struct ipv6hdr));
                        *(__be32*)hdr = htonl(0x60000000);
-
                        hdr->payload_len = htons(size);
                        hdr->nexthdr = IPPROTO_ICMPV6;
                        hdr->hop_limit = 255;
                        hdr->saddr = *saddr;
                        hdr->daddr = *daddr;
 
-                       send_skb->transport_header = send_skb->tail;
-                       skb_put(send_skb, size);
-
-                       icmp6h = (struct icmp6hdr *)skb_transport_header(skb);
+                       icmp6h = (struct icmp6hdr *) skb_put(send_skb, sizeof(struct icmp6hdr));
                        icmp6h->icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
                        icmp6h->icmp6_router = 0;
                        icmp6h->icmp6_solicited = 1;
-                       target = (struct in6_addr *)(skb_transport_header(send_skb) + sizeof(struct icmp6hdr));
+
+                       target = (struct in6_addr *) skb_put(send_skb, sizeof(struct in6_addr));
                        *target = msg->target;
                        icmp6h->icmp6_cksum = csum_ipv6_magic(saddr, daddr, size,
                                                              IPPROTO_ICMPV6,
index 0777d0aa18c3814a42a338a25d3508d9654c5797..e533259dce3ccad8a04cc095fa0056b8693fde70 100644 (file)
@@ -261,7 +261,7 @@ struct cgroup_subsys net_prio_subsys = {
 static int netprio_device_event(struct notifier_block *unused,
                                unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct netprio_map *old;
 
        /*
index 11f2704c3810d54b3539daddea36d50ef230636f..303412d8332b3c92a66d97d4c947051cf7fd8d6d 100644 (file)
@@ -1921,7 +1921,7 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d
 static int pktgen_device_event(struct notifier_block *unused,
                               unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct pktgen_net *pn = net_generic(dev_net(dev), pg_net_id);
 
        if (pn->pktgen_exiting)
@@ -2708,15 +2708,15 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
                *vlan_encapsulated_proto = htons(ETH_P_IP);
        }
 
-       skb->network_header = skb->tail;
-       skb->transport_header = skb->network_header + sizeof(struct iphdr);
-       skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr));
+       skb_set_mac_header(skb, 0);
+       skb_set_network_header(skb, skb->len);
+       iph = (struct iphdr *) skb_put(skb, sizeof(struct iphdr));
+
+       skb_set_transport_header(skb, skb->len);
+       udph = (struct udphdr *) skb_put(skb, sizeof(struct udphdr));
        skb_set_queue_mapping(skb, queue_map);
        skb->priority = pkt_dev->skb_priority;
 
-       iph = ip_hdr(skb);
-       udph = udp_hdr(skb);
-
        memcpy(eth, pkt_dev->hh, 12);
        *(__be16 *) & eth[12] = protocol;
 
@@ -2746,8 +2746,6 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        iph->check = 0;
        iph->check = ip_fast_csum((void *)iph, iph->ihl);
        skb->protocol = protocol;
-       skb->mac_header = (skb->network_header - ETH_HLEN -
-                          pkt_dev->pkt_overhead);
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
        pktgen_finalize_skb(pkt_dev, skb, datalen);
@@ -2822,13 +2820,14 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
                *vlan_encapsulated_proto = htons(ETH_P_IPV6);
        }
 
-       skb->network_header = skb->tail;
-       skb->transport_header = skb->network_header + sizeof(struct ipv6hdr);
-       skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr));
+       skb_set_mac_header(skb, 0);
+       skb_set_network_header(skb, skb->len);
+       iph = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr));
+
+       skb_set_transport_header(skb, skb->len);
+       udph = (struct udphdr *) skb_put(skb, sizeof(struct udphdr));
        skb_set_queue_mapping(skb, queue_map);
        skb->priority = pkt_dev->skb_priority;
-       iph = ipv6_hdr(skb);
-       udph = udp_hdr(skb);
 
        memcpy(eth, pkt_dev->hh, 12);
        *(__be16 *) &eth[12] = protocol;
@@ -2863,8 +2862,6 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        iph->daddr = pkt_dev->cur_in6_daddr;
        iph->saddr = pkt_dev->cur_in6_saddr;
 
-       skb->mac_header = (skb->network_header - ETH_HLEN -
-                          pkt_dev->pkt_overhead);
        skb->protocol = protocol;
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
index a08bd2b7fe3f06901d6c75e82df5e51e1aa2234f..49c14451d8ab81b9f9ebd75238e5374d4067c397 100644 (file)
@@ -2667,7 +2667,7 @@ static void rtnetlink_rcv(struct sk_buff *skb)
 
 static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        switch (event) {
        case NETDEV_UP:
index cfd777bd6bd0cea8023cfe32e431488727982225..73f57a0e15234a99a3dc64094ff56b28200de57d 100644 (file)
@@ -199,9 +199,7 @@ struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node)
        skb->truesize = sizeof(struct sk_buff);
        atomic_set(&skb->users, 1);
 
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-       skb->mac_header = ~0U;
-#endif
+       skb->mac_header = (typeof(skb->mac_header))~0U;
 out:
        return skb;
 }
@@ -275,10 +273,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
        skb->data = data;
        skb_reset_tail_pointer(skb);
        skb->end = skb->tail + size;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-       skb->mac_header = ~0U;
-       skb->transport_header = ~0U;
-#endif
+       skb->mac_header = (typeof(skb->mac_header))~0U;
+       skb->transport_header = (typeof(skb->transport_header))~0U;
 
        /* make sure we initialize shinfo sequentially */
        shinfo = skb_shinfo(skb);
@@ -344,10 +340,8 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size)
        skb->data = data;
        skb_reset_tail_pointer(skb);
        skb->end = skb->tail + size;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-       skb->mac_header = ~0U;
-       skb->transport_header = ~0U;
-#endif
+       skb->mac_header = (typeof(skb->mac_header))~0U;
+       skb->transport_header = (typeof(skb->transport_header))~0U;
 
        /* make sure we initialize shinfo sequentially */
        shinfo = skb_shinfo(skb);
@@ -2853,7 +2847,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
                                                 doffset + tnl_hlen);
 
                if (fskb != skb_shinfo(skb)->frag_list)
-                       continue;
+                       goto perform_csum_check;
 
                if (!sg) {
                        nskb->ip_summed = CHECKSUM_NONE;
@@ -2917,6 +2911,7 @@ skip_fraglist:
                nskb->len += nskb->data_len;
                nskb->truesize += nskb->data_len;
 
+perform_csum_check:
                if (!csum) {
                        nskb->csum = skb_checksum(nskb, doffset,
                                                  nskb->len - doffset, 0);
index cfdb46ab3a7f866dd77957abc2f202d673c99bd5..741db5fc78066dd7938a57718eacb27330de2548 100644 (file)
@@ -87,6 +87,96 @@ static int rps_sock_flow_sysctl(ctl_table *table, int write,
 }
 #endif /* CONFIG_RPS */
 
+#ifdef CONFIG_NET_FLOW_LIMIT
+static DEFINE_MUTEX(flow_limit_update_mutex);
+
+static int flow_limit_cpu_sysctl(ctl_table *table, int write,
+                                void __user *buffer, size_t *lenp,
+                                loff_t *ppos)
+{
+       struct sd_flow_limit *cur;
+       struct softnet_data *sd;
+       cpumask_var_t mask;
+       int i, len, ret = 0;
+
+       if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+               return -ENOMEM;
+
+       if (write) {
+               ret = cpumask_parse_user(buffer, *lenp, mask);
+               if (ret)
+                       goto done;
+
+               mutex_lock(&flow_limit_update_mutex);
+               len = sizeof(*cur) + netdev_flow_limit_table_len;
+               for_each_possible_cpu(i) {
+                       sd = &per_cpu(softnet_data, i);
+                       cur = rcu_dereference_protected(sd->flow_limit,
+                                    lockdep_is_held(&flow_limit_update_mutex));
+                       if (cur && !cpumask_test_cpu(i, mask)) {
+                               RCU_INIT_POINTER(sd->flow_limit, NULL);
+                               synchronize_rcu();
+                               kfree(cur);
+                       } else if (!cur && cpumask_test_cpu(i, mask)) {
+                               cur = kzalloc(len, GFP_KERNEL);
+                               if (!cur) {
+                                       /* not unwinding previous changes */
+                                       ret = -ENOMEM;
+                                       goto write_unlock;
+                               }
+                               cur->num_buckets = netdev_flow_limit_table_len;
+                               rcu_assign_pointer(sd->flow_limit, cur);
+                       }
+               }
+write_unlock:
+               mutex_unlock(&flow_limit_update_mutex);
+       } else {
+               if (*ppos || !*lenp) {
+                       *lenp = 0;
+                       goto done;
+               }
+
+               cpumask_clear(mask);
+               rcu_read_lock();
+               for_each_possible_cpu(i) {
+                       sd = &per_cpu(softnet_data, i);
+                       if (rcu_dereference(sd->flow_limit))
+                               cpumask_set_cpu(i, mask);
+               }
+               rcu_read_unlock();
+
+               len = cpumask_scnprintf(buffer, *lenp, mask);
+               *lenp = len + 1;
+               *ppos += len + 1;
+       }
+
+done:
+       free_cpumask_var(mask);
+       return ret;
+}
+
+static int flow_limit_table_len_sysctl(ctl_table *table, int write,
+                                      void __user *buffer, size_t *lenp,
+                                      loff_t *ppos)
+{
+       unsigned int old, *ptr;
+       int ret;
+
+       mutex_lock(&flow_limit_update_mutex);
+
+       ptr = table->data;
+       old = *ptr;
+       ret = proc_dointvec(table, write, buffer, lenp, ppos);
+       if (!ret && write && !is_power_of_2(*ptr)) {
+               *ptr = old;
+               ret = -EINVAL;
+       }
+
+       mutex_unlock(&flow_limit_update_mutex);
+       return ret;
+}
+#endif /* CONFIG_NET_FLOW_LIMIT */
+
 static struct ctl_table net_core_table[] = {
 #ifdef CONFIG_NET
        {
@@ -180,6 +270,20 @@ static struct ctl_table net_core_table[] = {
                .proc_handler   = rps_sock_flow_sysctl
        },
 #endif
+#ifdef CONFIG_NET_FLOW_LIMIT
+       {
+               .procname       = "flow_limit_cpu_bitmap",
+               .mode           = 0644,
+               .proc_handler   = flow_limit_cpu_sysctl
+       },
+       {
+               .procname       = "flow_limit_table_len",
+               .data           = &netdev_flow_limit_table_len,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = flow_limit_table_len_sysctl
+       },
+#endif /* CONFIG_NET_FLOW_LIMIT */
 #endif /* CONFIG_NET */
        {
                .procname       = "netdev_budget",
index c21f200eed9342c6ab34ee665fd5cc72c34f9cd0..dd4d506ef92395a9124a73391dd69beb92ed0388 100644 (file)
@@ -2078,9 +2078,9 @@ out_err:
 }
 
 static int dn_device_event(struct notifier_block *this, unsigned long event,
-                       void *ptr)
+                          void *ptr)
 {
-       struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (!net_eq(dev_net(dev), &init_net))
                return NOTIFY_DONE;
index 55e1fd5b3e56d4ede22c2a05a6f72cc3b4bffa44..3b9d5f20bd1c695de768db960b190beb4370fa35 100644 (file)
@@ -1352,10 +1352,9 @@ static inline void lowpan_netlink_fini(void)
 }
 
 static int lowpan_device_event(struct notifier_block *unused,
-                               unsigned long event,
-                               void *ptr)
+                              unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        LIST_HEAD(del_list);
        struct lowpan_dev_record *entry, *tmp;
 
index 8603ca82710415b24e8ff85cbce1e45ba34491d2..37cf1a6ea3ad23662ea39d236aae62c0fdebed05 100644 (file)
@@ -9,10 +9,7 @@ config IP_MULTICAST
          intend to participate in the MBONE, a high bandwidth network on top
          of the Internet which carries audio and video broadcasts. More
          information about the MBONE is on the WWW at
-         <http://www.savetz.com/mbone/>. Information about the multicast
-         capabilities of the various network cards is contained in
-         <file:Documentation/networking/multicast.txt>. For most people, it's
-         safe to say N.
+         <http://www.savetz.com/mbone/>. For most people, it's safe to say N.
 
 config IP_ADVANCED_ROUTER
        bool "IP: advanced router"
@@ -223,10 +220,8 @@ config IP_MROUTE
          packets that have several destination addresses. It is needed on the
          MBONE, a high bandwidth network on top of the Internet which carries
          audio and video broadcasts. In order to do that, you would most
-         likely run the program mrouted. Information about the multicast
-         capabilities of the various network cards is contained in
-         <file:Documentation/networking/multicast.txt>. If you haven't heard
-         about it, you don't need it.
+         likely run the program mrouted. If you haven't heard about it, you
+         don't need it.
 
 config IP_MROUTE_MULTIPLE_TABLES
        bool "IP: multicast policy routing"
index d01be2a3ae53170c1075a57a32f2b11e1e75885b..9c090c7daea1d12a1a5babbca388f4f7741948b6 100644 (file)
@@ -1295,6 +1295,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
                       SKB_GSO_GRE |
                       SKB_GSO_TCPV6 |
                       SKB_GSO_UDP_TUNNEL |
+                      SKB_GSO_MPLS |
                       0)))
                goto out;
 
@@ -1384,7 +1385,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
                goto out_unlock;
 
        id = ntohl(*(__be32 *)&iph->id);
-       flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id IP_DF));
+       flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF));
        id >>= 16;
 
        for (p = *head; p; p = p->next) {
@@ -1406,6 +1407,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
                NAPI_GRO_CB(p)->flush |=
                        (iph->ttl ^ iph2->ttl) |
                        (iph->tos ^ iph2->tos) |
+                       ((iph->frag_off ^ iph2->frag_off) & htons(IP_DF)) |
                        ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id);
 
                NAPI_GRO_CB(p)->flush |= flush;
index 2e7f1948216fe8ade7d57aa3baa652d14d6b9b7b..717902669d2f2ef34714c215c4695ffe59ddd283 100644 (file)
@@ -419,12 +419,9 @@ static void ah4_err(struct sk_buff *skb, u32 info)
        if (!x)
                return;
 
-       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
-               atomic_inc(&flow_cache_genid);
-               rt_genid_bump(net);
-
+       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
                ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0);
-       else
+       else
                ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0);
        xfrm_state_put(x);
 }
index 247ec1951c35bed69d2182c6119085b9a7b2da96..4429b013f26946e03b687c25158267494542de9c 100644 (file)
@@ -1234,13 +1234,19 @@ out:
 static int arp_netdev_event(struct notifier_block *this, unsigned long event,
                            void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct netdev_notifier_change_info *change_info;
 
        switch (event) {
        case NETDEV_CHANGEADDR:
                neigh_changeaddr(&arp_tbl, dev);
                rt_cache_flush(dev_net(dev));
                break;
+       case NETDEV_CHANGE:
+               change_info = ptr;
+               if (change_info->flags_changed & IFF_NOARP)
+                       neigh_changeaddr(&arp_tbl, dev);
+               break;
        default:
                break;
        }
index dfc39d4d48b7471fc83035746026fa14d1dcf497..b047e2d8a614f2ee561f0741687d058b0deafa06 100644 (file)
@@ -1333,7 +1333,7 @@ static void inetdev_send_gratuitous_arp(struct net_device *dev,
 static int inetdev_event(struct notifier_block *this, unsigned long event,
                         void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct in_device *in_dev = __in_dev_get_rtnl(dev);
 
        ASSERT_RTNL();
index 4cfe34d4cc967a94ed15f2deef3d249d2429e846..ab3d814bc80af8f377da971af189a49ae4f2f094 100644 (file)
@@ -502,12 +502,9 @@ static void esp4_err(struct sk_buff *skb, u32 info)
        if (!x)
                return;
 
-       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
-               atomic_inc(&flow_cache_genid);
-               rt_genid_bump(net);
-
+       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
                ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0);
-       else
+       else
                ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0);
        xfrm_state_put(x);
 }
index c7629a209f9d84538b8048de89ce66aa3776a9bb..05a4888dede9868681651ddacffd68664d5933c6 100644 (file)
@@ -1038,7 +1038,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
 
 static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct in_device *in_dev;
        struct net *net = dev_net(dev);
 
index 76e10b47e053fd7fc2cbc7fa8d231f54704d1b25..5f7d11a458713f9c755dd1a1a40289b180a3e041 100644 (file)
@@ -482,7 +482,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 {
        struct iphdr *iph;
        int room;
-       struct icmp_bxm icmp_param;
+       struct icmp_bxm *icmp_param;
        struct rtable *rt = skb_rtable(skb_in);
        struct ipcm_cookie ipc;
        struct flowi4 fl4;
@@ -503,7 +503,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
        iph = ip_hdr(skb_in);
 
        if ((u8 *)iph < skb_in->head ||
-           (skb_in->network_header + sizeof(*iph)) > skb_in->tail)
+           (skb_network_header(skb_in) + sizeof(*iph)) >
+           skb_tail_pointer(skb_in))
                goto out;
 
        /*
@@ -557,9 +558,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
                }
        }
 
+       icmp_param = kmalloc(sizeof(*icmp_param), GFP_ATOMIC);
+       if (!icmp_param)
+               return;
+
        sk = icmp_xmit_lock(net);
        if (sk == NULL)
-               return;
+               goto out_free;
 
        /*
         *      Construct source address and options.
@@ -585,7 +590,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
                                           IPTOS_PREC_INTERNETCONTROL) :
                                          iph->tos;
 
-       if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in))
+       if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb_in))
                goto out_unlock;
 
 
@@ -593,19 +598,19 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
         *      Prepare data for ICMP header.
         */
 
-       icmp_param.data.icmph.type       = type;
-       icmp_param.data.icmph.code       = code;
-       icmp_param.data.icmph.un.gateway = info;
-       icmp_param.data.icmph.checksum   = 0;
-       icmp_param.skb    = skb_in;
-       icmp_param.offset = skb_network_offset(skb_in);
+       icmp_param->data.icmph.type      = type;
+       icmp_param->data.icmph.code      = code;
+       icmp_param->data.icmph.un.gateway = info;
+       icmp_param->data.icmph.checksum  = 0;
+       icmp_param->skb   = skb_in;
+       icmp_param->offset = skb_network_offset(skb_in);
        inet_sk(sk)->tos = tos;
        ipc.addr = iph->saddr;
-       ipc.opt = &icmp_param.replyopts.opt;
+       ipc.opt = &icmp_param->replyopts.opt;
        ipc.tx_flags = 0;
 
        rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos,
-                              type, code, &icmp_param);
+                              type, code, icmp_param);
        if (IS_ERR(rt))
                goto out_unlock;
 
@@ -617,19 +622,21 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
        room = dst_mtu(&rt->dst);
        if (room > 576)
                room = 576;
-       room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen;
+       room -= sizeof(struct iphdr) + icmp_param->replyopts.opt.opt.optlen;
        room -= sizeof(struct icmphdr);
 
-       icmp_param.data_len = skb_in->len - icmp_param.offset;
-       if (icmp_param.data_len > room)
-               icmp_param.data_len = room;
-       icmp_param.head_len = sizeof(struct icmphdr);
+       icmp_param->data_len = skb_in->len - icmp_param->offset;
+       if (icmp_param->data_len > room)
+               icmp_param->data_len = room;
+       icmp_param->head_len = sizeof(struct icmphdr);
 
-       icmp_push_reply(&icmp_param, &fl4, &ipc, &rt);
+       icmp_push_reply(icmp_param, &fl4, &ipc, &rt);
 ende:
        ip_rt_put(rt);
 out_unlock:
        icmp_xmit_unlock(sk);
+out_free:
+       kfree(icmp_param);
 out:;
 }
 EXPORT_SYMBOL(icmp_send);
@@ -657,7 +664,8 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
 }
 
 /*
- *     Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH.
+ *     Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, ICMP_QUENCH, and
+ *     ICMP_PARAMETERPROB.
  */
 
 static void icmp_unreach(struct sk_buff *skb)
@@ -939,7 +947,8 @@ error:
 void icmp_err(struct sk_buff *skb, u32 info)
 {
        struct iphdr *iph = (struct iphdr *)skb->data;
-       struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2));
+       int offset = iph->ihl<<2;
+       struct icmphdr *icmph = (struct icmphdr *)(skb->data + offset);
        int type = icmp_hdr(skb)->type;
        int code = icmp_hdr(skb)->code;
        struct net *net = dev_net(skb->dev);
@@ -949,7 +958,7 @@ void icmp_err(struct sk_buff *skb, u32 info)
         * triggered by ICMP_ECHOREPLY which sent from kernel.
         */
        if (icmph->type != ICMP_ECHOREPLY) {
-               ping_err(skb, info);
+               ping_err(skb, offset, info);
                return;
        }
 
index d8c232794bcb4bc995f850cabf42ac7bc8eac37a..450f625361e4bf181f2ffab6137a57668e8d9eea 100644 (file)
@@ -363,7 +363,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
 static int igmpv3_sendpack(struct sk_buff *skb)
 {
        struct igmphdr *pig = igmp_hdr(skb);
-       const int igmplen = skb->tail - skb->transport_header;
+       const int igmplen = skb_tail_pointer(skb) - skb_transport_header(skb);
 
        pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen);
 
index 2a83591492dd6f3e8b7470c3e9b897dad7625a49..a982657d05e7ee8c3f396a557c6ddf3b639c72a1 100644 (file)
@@ -429,7 +429,7 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
                return;
        }
 
-       ip_tunnel_xmit(skb, dev, tnl_params);
+       ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
 }
 
 static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
index be2f8da0ae8ebc4b94a257dd50914db14212a451..7c79cf8ad449c5a91235704f9a9d82ab4e6bc769 100644 (file)
@@ -487,7 +487,7 @@ drop:
 EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
 
 void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
-                   const struct iphdr *tnl_params)
+                   const struct iphdr *tnl_params, const u8 protocol)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        const struct iphdr *inner_iph;
@@ -670,7 +670,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        iph->version    =       4;
        iph->ihl        =       sizeof(struct iphdr) >> 2;
        iph->frag_off   =       df;
-       iph->protocol   =       tnl_params->protocol;
+       iph->protocol   =       protocol;
        iph->tos        =       ip_tunnel_ecn_encap(tos, inner_iph, skb);
        iph->daddr      =       fl4.daddr;
        iph->saddr      =       fl4.saddr;
index 59cb8c7690561f3fc44ecc382557408af53cb5fb..826be4cb482a29b401f2314da6581e1127a7a731 100644 (file)
@@ -47,12 +47,9 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
        if (!x)
                return;
 
-       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
-               atomic_inc(&flow_cache_genid);
-               rt_genid_bump(net);
-
+       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
                ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0);
-       else
+       else
                ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0);
        xfrm_state_put(x);
 }
index 77bfcce64fe568b3a162a9d36324061553275a5e..9df7ecd393f20246d5fcb0246cdf5c35323eb4be 100644 (file)
@@ -222,7 +222,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
                skb->encapsulation = 1;
        }
 
-       ip_tunnel_xmit(skb, dev, tiph);
+       ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
        return NETDEV_TX_OK;
 
 tx_error:
index 9d9610ae78553895e9f6ccb0ea8260fa4a66ac17..df97f0ac1a1cec50085977ce21196d990e221ce2 100644 (file)
@@ -945,6 +945,7 @@ static int ipmr_cache_report(struct mr_table *mrt,
        struct igmpmsg *msg;
        struct sock *mroute_sk;
        int ret;
+       unsigned long tail_offset;
 
 #ifdef CONFIG_IP_PIMSM
        if (assert == IGMPMSG_WHOLEPKT)
@@ -980,7 +981,12 @@ static int ipmr_cache_report(struct mr_table *mrt,
 
        /* Copy the IP header */
 
-       skb->network_header = skb->tail;
+       tail_offset = skb_tail_offset(skb);
+       if (tail_offset > 0xffff) {
+               kfree_skb(skb);
+               return -EINVAL;
+       }
+       skb_set_network_header(skb, tail_offset);
        skb_put(skb, ihl);
        skb_copy_to_linear_data(skb, pkt->data, ihl);
        ip_hdr(skb)->protocol = 0;      /* Flag to the kernel this is a route add */
@@ -1609,7 +1615,7 @@ int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
 
 static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
        struct mr_table *mrt;
        struct vif_device *v;
index 5d5d4d1be9c2c7c2c951943e5a7d7ce7a4b940d4..30e4de94056722535ee5304e93b49bfb6c5cf889 100644 (file)
@@ -108,7 +108,7 @@ static int masq_device_event(struct notifier_block *this,
                             unsigned long event,
                             void *ptr)
 {
-       const struct net_device *dev = ptr;
+       const struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
 
        if (event == NETDEV_DOWN) {
@@ -129,7 +129,10 @@ static int masq_inet_event(struct notifier_block *this,
                           void *ptr)
 {
        struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
-       return masq_device_event(this, event, dev);
+       struct netdev_notifier_info info;
+
+       netdev_notifier_info_init(&info, dev);
+       return masq_device_event(this, event, &info);
 }
 
 static struct notifier_block masq_dev_notifier = {
index 7d93d62cd5fdae9f7f8a3f2e5c35f2a203df92e0..1f1b2dd90277a0a64907c4f564c1b42d65ea5af7 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/netdevice.h>
 #include <net/snmp.h>
 #include <net/ip.h>
-#include <net/ipv6.h>
 #include <net/icmp.h>
 #include <net/protocol.h>
 #include <linux/skbuff.h>
 #include <net/inet_common.h>
 #include <net/checksum.h>
 
+#if IS_ENABLED(CONFIG_IPV6)
+#include <linux/in6.h>
+#include <linux/icmpv6.h>
+#include <net/addrconf.h>
+#include <net/ipv6.h>
+#include <net/transp_v6.h>
+#endif
 
-static struct ping_table ping_table;
+
+struct ping_table ping_table;
+struct pingv6_ops pingv6_ops;
+EXPORT_SYMBOL_GPL(pingv6_ops);
 
 static u16 ping_port_rover;
 
@@ -58,6 +67,7 @@ static inline int ping_hashfn(struct net *net, unsigned int num, unsigned int ma
        pr_debug("hash(%d) = %d\n", num, res);
        return res;
 }
+EXPORT_SYMBOL_GPL(ping_hash);
 
 static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table,
                                             struct net *net, unsigned int num)
@@ -65,7 +75,7 @@ static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table,
        return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)];
 }
 
-static int ping_v4_get_port(struct sock *sk, unsigned short ident)
+int ping_get_port(struct sock *sk, unsigned short ident)
 {
        struct hlist_nulls_node *node;
        struct hlist_nulls_head *hlist;
@@ -103,6 +113,10 @@ next_port:
                ping_portaddr_for_each_entry(sk2, node, hlist) {
                        isk2 = inet_sk(sk2);
 
+                       /* BUG? Why is this reuse and not reuseaddr? ping.c
+                        * doesn't turn off SO_REUSEADDR, and it doesn't expect
+                        * that other ping processes can steal its packets.
+                        */
                        if ((isk2->inet_num == ident) &&
                            (sk2 != sk) &&
                            (!sk2->sk_reuse || !sk->sk_reuse))
@@ -125,17 +139,18 @@ fail:
        write_unlock_bh(&ping_table.lock);
        return 1;
 }
+EXPORT_SYMBOL_GPL(ping_get_port);
 
-static void ping_v4_hash(struct sock *sk)
+void ping_hash(struct sock *sk)
 {
-       pr_debug("ping_v4_hash(sk->port=%u)\n", inet_sk(sk)->inet_num);
+       pr_debug("ping_hash(sk->port=%u)\n", inet_sk(sk)->inet_num);
        BUG(); /* "Please do not press this button again." */
 }
 
-static void ping_v4_unhash(struct sock *sk)
+void ping_unhash(struct sock *sk)
 {
        struct inet_sock *isk = inet_sk(sk);
-       pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
+       pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
        if (sk_hashed(sk)) {
                write_lock_bh(&ping_table.lock);
                hlist_nulls_del(&sk->sk_nulls_node);
@@ -146,31 +161,61 @@ static void ping_v4_unhash(struct sock *sk)
                write_unlock_bh(&ping_table.lock);
        }
 }
+EXPORT_SYMBOL_GPL(ping_unhash);
 
-static struct sock *ping_v4_lookup(struct net *net, __be32 saddr, __be32 daddr,
-                                  u16 ident, int dif)
+static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident)
 {
        struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident);
        struct sock *sk = NULL;
        struct inet_sock *isk;
        struct hlist_nulls_node *hnode;
+       int dif = skb->dev->ifindex;
+
+       if (skb->protocol == htons(ETH_P_IP)) {
+               pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n",
+                        (int)ident, &ip_hdr(skb)->daddr, dif);
+#if IS_ENABLED(CONFIG_IPV6)
+       } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               pr_debug("try to find: num = %d, daddr = %pI6c, dif = %d\n",
+                        (int)ident, &ipv6_hdr(skb)->daddr, dif);
+#endif
+       }
 
-       pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n",
-                (int)ident, &daddr, dif);
        read_lock_bh(&ping_table.lock);
 
        ping_portaddr_for_each_entry(sk, hnode, hslot) {
                isk = inet_sk(sk);
 
-               pr_debug("found: %p: num = %d, daddr = %pI4, dif = %d\n", sk,
-                        (int)isk->inet_num, &isk->inet_rcv_saddr,
-                        sk->sk_bound_dev_if);
-
                pr_debug("iterate\n");
                if (isk->inet_num != ident)
                        continue;
-               if (isk->inet_rcv_saddr && isk->inet_rcv_saddr != daddr)
-                       continue;
+
+               if (skb->protocol == htons(ETH_P_IP) &&
+                   sk->sk_family == AF_INET) {
+                       pr_debug("found: %p: num=%d, daddr=%pI4, dif=%d\n", sk,
+                                (int) isk->inet_num, &isk->inet_rcv_saddr,
+                                sk->sk_bound_dev_if);
+
+                       if (isk->inet_rcv_saddr &&
+                           isk->inet_rcv_saddr != ip_hdr(skb)->daddr)
+                               continue;
+#if IS_ENABLED(CONFIG_IPV6)
+               } else if (skb->protocol == htons(ETH_P_IPV6) &&
+                          sk->sk_family == AF_INET6) {
+                       struct ipv6_pinfo *np = inet6_sk(sk);
+
+                       pr_debug("found: %p: num=%d, daddr=%pI6c, dif=%d\n", sk,
+                                (int) isk->inet_num,
+                                &inet6_sk(sk)->rcv_saddr,
+                                sk->sk_bound_dev_if);
+
+                       if (!ipv6_addr_any(&np->rcv_saddr) &&
+                           !ipv6_addr_equal(&np->rcv_saddr,
+                                            &ipv6_hdr(skb)->daddr))
+                               continue;
+#endif
+               }
+
                if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
                        continue;
 
@@ -200,7 +245,7 @@ static void inet_get_ping_group_range_net(struct net *net, kgid_t *low,
 }
 
 
-static int ping_init_sock(struct sock *sk)
+int ping_init_sock(struct sock *sk)
 {
        struct net *net = sock_net(sk);
        kgid_t group = current_egid();
@@ -225,8 +270,9 @@ static int ping_init_sock(struct sock *sk)
 
        return -EACCES;
 }
+EXPORT_SYMBOL_GPL(ping_init_sock);
 
-static void ping_close(struct sock *sk, long timeout)
+void ping_close(struct sock *sk, long timeout)
 {
        pr_debug("ping_close(sk=%p,sk->num=%u)\n",
                 inet_sk(sk), inet_sk(sk)->inet_num);
@@ -234,36 +280,122 @@ static void ping_close(struct sock *sk, long timeout)
 
        sk_common_release(sk);
 }
+EXPORT_SYMBOL_GPL(ping_close);
+
+/* Checks the bind address and possibly modifies sk->sk_bound_dev_if. */
+int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
+                        struct sockaddr *uaddr, int addr_len) {
+       struct net *net = sock_net(sk);
+       if (sk->sk_family == AF_INET) {
+               struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
+               int chk_addr_ret;
+
+               if (addr_len < sizeof(*addr))
+                       return -EINVAL;
+
+               pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n",
+                        sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port));
+
+               chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr);
+
+               if (addr->sin_addr.s_addr == htonl(INADDR_ANY))
+                       chk_addr_ret = RTN_LOCAL;
+
+               if ((sysctl_ip_nonlocal_bind == 0 &&
+                   isk->freebind == 0 && isk->transparent == 0 &&
+                    chk_addr_ret != RTN_LOCAL) ||
+                   chk_addr_ret == RTN_MULTICAST ||
+                   chk_addr_ret == RTN_BROADCAST)
+                       return -EADDRNOTAVAIL;
+
+#if IS_ENABLED(CONFIG_IPV6)
+       } else if (sk->sk_family == AF_INET6) {
+               struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr;
+               int addr_type, scoped, has_addr;
+               struct net_device *dev = NULL;
+
+               if (addr_len < sizeof(*addr))
+                       return -EINVAL;
+
+               pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n",
+                        sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port));
+
+               addr_type = ipv6_addr_type(&addr->sin6_addr);
+               scoped = __ipv6_addr_needs_scope_id(addr_type);
+               if ((addr_type != IPV6_ADDR_ANY &&
+                    !(addr_type & IPV6_ADDR_UNICAST)) ||
+                   (scoped && !addr->sin6_scope_id))
+                       return -EINVAL;
+
+               rcu_read_lock();
+               if (addr->sin6_scope_id) {
+                       dev = dev_get_by_index_rcu(net, addr->sin6_scope_id);
+                       if (!dev) {
+                               rcu_read_unlock();
+                               return -ENODEV;
+                       }
+               }
+               has_addr = pingv6_ops.ipv6_chk_addr(net, &addr->sin6_addr, dev,
+                                                   scoped);
+               rcu_read_unlock();
+
+               if (!(isk->freebind || isk->transparent || has_addr ||
+                     addr_type == IPV6_ADDR_ANY))
+                       return -EADDRNOTAVAIL;
+
+               if (scoped)
+                       sk->sk_bound_dev_if = addr->sin6_scope_id;
+#endif
+       } else {
+               return -EAFNOSUPPORT;
+       }
+       return 0;
+}
+
+void ping_set_saddr(struct sock *sk, struct sockaddr *saddr)
+{
+       if (saddr->sa_family == AF_INET) {
+               struct inet_sock *isk = inet_sk(sk);
+               struct sockaddr_in *addr = (struct sockaddr_in *) saddr;
+               isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr;
+#if IS_ENABLED(CONFIG_IPV6)
+       } else if (saddr->sa_family == AF_INET6) {
+               struct sockaddr_in6 *addr = (struct sockaddr_in6 *) saddr;
+               struct ipv6_pinfo *np = inet6_sk(sk);
+               np->rcv_saddr = np->saddr = addr->sin6_addr;
+#endif
+       }
+}
 
+void ping_clear_saddr(struct sock *sk, int dif)
+{
+       sk->sk_bound_dev_if = dif;
+       if (sk->sk_family == AF_INET) {
+               struct inet_sock *isk = inet_sk(sk);
+               isk->inet_rcv_saddr = isk->inet_saddr = 0;
+#if IS_ENABLED(CONFIG_IPV6)
+       } else if (sk->sk_family == AF_INET6) {
+               struct ipv6_pinfo *np = inet6_sk(sk);
+               memset(&np->rcv_saddr, 0, sizeof(np->rcv_saddr));
+               memset(&np->saddr, 0, sizeof(np->saddr));
+#endif
+       }
+}
 /*
  * We need our own bind because there are no privileged id's == local ports.
  * Moreover, we don't allow binding to multi- and broadcast addresses.
  */
 
-static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
-       struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
        struct inet_sock *isk = inet_sk(sk);
        unsigned short snum;
-       int chk_addr_ret;
        int err;
+       int dif = sk->sk_bound_dev_if;
 
-       if (addr_len < sizeof(struct sockaddr_in))
-               return -EINVAL;
-
-       pr_debug("ping_v4_bind(sk=%p,sa_addr=%08x,sa_port=%d)\n",
-                sk, addr->sin_addr.s_addr, ntohs(addr->sin_port));
-
-       chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
-       if (addr->sin_addr.s_addr == htonl(INADDR_ANY))
-               chk_addr_ret = RTN_LOCAL;
-
-       if ((sysctl_ip_nonlocal_bind == 0 &&
-           isk->freebind == 0 && isk->transparent == 0 &&
-            chk_addr_ret != RTN_LOCAL) ||
-           chk_addr_ret == RTN_MULTICAST ||
-           chk_addr_ret == RTN_BROADCAST)
-               return -EADDRNOTAVAIL;
+       err = ping_check_bind_addr(sk, isk, uaddr, addr_len);
+       if (err)
+               return err;
 
        lock_sock(sk);
 
@@ -272,42 +404,50 @@ static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                goto out;
 
        err = -EADDRINUSE;
-       isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr;
-       snum = ntohs(addr->sin_port);
-       if (ping_v4_get_port(sk, snum) != 0) {
-               isk->inet_saddr = isk->inet_rcv_saddr = 0;
+       ping_set_saddr(sk, uaddr);
+       snum = ntohs(((struct sockaddr_in *)uaddr)->sin_port);
+       if (ping_get_port(sk, snum) != 0) {
+               ping_clear_saddr(sk, dif);
                goto out;
        }
 
-       pr_debug("after bind(): num = %d, daddr = %pI4, dif = %d\n",
+       pr_debug("after bind(): num = %d, dif = %d\n",
                 (int)isk->inet_num,
-                &isk->inet_rcv_saddr,
                 (int)sk->sk_bound_dev_if);
 
        err = 0;
-       if (isk->inet_rcv_saddr)
+       if ((sk->sk_family == AF_INET && isk->inet_rcv_saddr) ||
+           (sk->sk_family == AF_INET6 &&
+            !ipv6_addr_any(&inet6_sk(sk)->rcv_saddr)))
                sk->sk_userlocks |= SOCK_BINDADDR_LOCK;
+
        if (snum)
                sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
        isk->inet_sport = htons(isk->inet_num);
        isk->inet_daddr = 0;
        isk->inet_dport = 0;
+
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == AF_INET6)
+               memset(&inet6_sk(sk)->daddr, 0, sizeof(inet6_sk(sk)->daddr));
+#endif
+
        sk_dst_reset(sk);
 out:
        release_sock(sk);
        pr_debug("ping_v4_bind -> %d\n", err);
        return err;
 }
+EXPORT_SYMBOL_GPL(ping_bind);
 
 /*
  * Is this a supported type of ICMP message?
  */
 
-static inline int ping_supported(int type, int code)
+static inline int ping_supported(int family, int type, int code)
 {
-       if (type == ICMP_ECHO && code == 0)
-               return 1;
-       return 0;
+       return (family == AF_INET && type == ICMP_ECHO && code == 0) ||
+              (family == AF_INET6 && type == ICMPV6_ECHO_REQUEST && code == 0);
 }
 
 /*
@@ -315,30 +455,42 @@ static inline int ping_supported(int type, int code)
  * sort of error condition.
  */
 
-static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
-
-void ping_err(struct sk_buff *skb, u32 info)
+void ping_err(struct sk_buff *skb, int offset, u32 info)
 {
-       struct iphdr *iph = (struct iphdr *)skb->data;
-       struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2));
+       int family;
+       struct icmphdr *icmph;
        struct inet_sock *inet_sock;
-       int type = icmp_hdr(skb)->type;
-       int code = icmp_hdr(skb)->code;
+       int type;
+       int code;
        struct net *net = dev_net(skb->dev);
        struct sock *sk;
        int harderr;
        int err;
 
+       if (skb->protocol == htons(ETH_P_IP)) {
+               family = AF_INET;
+               type = icmp_hdr(skb)->type;
+               code = icmp_hdr(skb)->code;
+               icmph = (struct icmphdr *)(skb->data + offset);
+       } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               family = AF_INET6;
+               type = icmp6_hdr(skb)->icmp6_type;
+               code = icmp6_hdr(skb)->icmp6_code;
+               icmph = (struct icmphdr *) (skb->data + offset);
+       } else {
+               BUG();
+       }
+
        /* We assume the packet has already been checked by icmp_unreach */
 
-       if (!ping_supported(icmph->type, icmph->code))
+       if (!ping_supported(family, icmph->type, icmph->code))
                return;
 
-       pr_debug("ping_err(type=%04x,code=%04x,id=%04x,seq=%04x)\n", type,
-                code, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence));
+       pr_debug("ping_err(proto=0x%x,type=%d,code=%d,id=%04x,seq=%04x)\n",
+                skb->protocol, type, code, ntohs(icmph->un.echo.id),
+                ntohs(icmph->un.echo.sequence));
 
-       sk = ping_v4_lookup(net, iph->daddr, iph->saddr,
-                           ntohs(icmph->un.echo.id), skb->dev->ifindex);
+       sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id));
        if (sk == NULL) {
                pr_debug("no socket, dropping\n");
                return; /* No socket for error */
@@ -349,72 +501,83 @@ void ping_err(struct sk_buff *skb, u32 info)
        harderr = 0;
        inet_sock = inet_sk(sk);
 
-       switch (type) {
-       default:
-       case ICMP_TIME_EXCEEDED:
-               err = EHOSTUNREACH;
-               break;
-       case ICMP_SOURCE_QUENCH:
-               /* This is not a real error but ping wants to see it.
-                * Report it with some fake errno. */
-               err = EREMOTEIO;
-               break;
-       case ICMP_PARAMETERPROB:
-               err = EPROTO;
-               harderr = 1;
-               break;
-       case ICMP_DEST_UNREACH:
-               if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */
-                       ipv4_sk_update_pmtu(skb, sk, info);
-                       if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) {
-                               err = EMSGSIZE;
-                               harderr = 1;
-                               break;
+       if (skb->protocol == htons(ETH_P_IP)) {
+               switch (type) {
+               default:
+               case ICMP_TIME_EXCEEDED:
+                       err = EHOSTUNREACH;
+                       break;
+               case ICMP_SOURCE_QUENCH:
+                       /* This is not a real error but ping wants to see it.
+                        * Report it with some fake errno.
+                        */
+                       err = EREMOTEIO;
+                       break;
+               case ICMP_PARAMETERPROB:
+                       err = EPROTO;
+                       harderr = 1;
+                       break;
+               case ICMP_DEST_UNREACH:
+                       if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */
+                               ipv4_sk_update_pmtu(skb, sk, info);
+                               if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) {
+                                       err = EMSGSIZE;
+                                       harderr = 1;
+                                       break;
+                               }
+                               goto out;
                        }
-                       goto out;
-               }
-               err = EHOSTUNREACH;
-               if (code <= NR_ICMP_UNREACH) {
-                       harderr = icmp_err_convert[code].fatal;
-                       err = icmp_err_convert[code].errno;
+                       err = EHOSTUNREACH;
+                       if (code <= NR_ICMP_UNREACH) {
+                               harderr = icmp_err_convert[code].fatal;
+                               err = icmp_err_convert[code].errno;
+                       }
+                       break;
+               case ICMP_REDIRECT:
+                       /* See ICMP_SOURCE_QUENCH */
+                       ipv4_sk_redirect(skb, sk);
+                       err = EREMOTEIO;
+                       break;
                }
-               break;
-       case ICMP_REDIRECT:
-               /* See ICMP_SOURCE_QUENCH */
-               ipv4_sk_redirect(skb, sk);
-               err = EREMOTEIO;
-               break;
+#if IS_ENABLED(CONFIG_IPV6)
+       } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               harderr = pingv6_ops.icmpv6_err_convert(type, code, &err);
+#endif
        }
 
        /*
         *      RFC1122: OK.  Passes ICMP errors back to application, as per
         *      4.1.3.3.
         */
-       if (!inet_sock->recverr) {
+       if ((family == AF_INET && !inet_sock->recverr) ||
+           (family == AF_INET6 && !inet6_sk(sk)->recverr)) {
                if (!harderr || sk->sk_state != TCP_ESTABLISHED)
                        goto out;
        } else {
-               ip_icmp_error(sk, skb, err, 0 /* no remote port */,
-                        info, (u8 *)icmph);
+               if (family == AF_INET) {
+                       ip_icmp_error(sk, skb, err, 0 /* no remote port */,
+                                     info, (u8 *)icmph);
+#if IS_ENABLED(CONFIG_IPV6)
+               } else if (family == AF_INET6) {
+                       pingv6_ops.ipv6_icmp_error(sk, skb, err, 0,
+                                                  info, (u8 *)icmph);
+#endif
+               }
        }
        sk->sk_err = err;
        sk->sk_error_report(sk);
 out:
        sock_put(sk);
 }
+EXPORT_SYMBOL_GPL(ping_err);
 
 /*
- *     Copy and checksum an ICMP Echo packet from user space into a buffer.
+ *     Copy and checksum an ICMP Echo packet from user space into a buffer
+ *     starting from the payload.
  */
 
-struct pingfakehdr {
-       struct icmphdr icmph;
-       struct iovec *iov;
-       __wsum wcheck;
-};
-
-static int ping_getfrag(void *from, char *to,
-                       int offset, int fraglen, int odd, struct sk_buff *skb)
+int ping_getfrag(void *from, char *to,
+                int offset, int fraglen, int odd, struct sk_buff *skb)
 {
        struct pingfakehdr *pfh = (struct pingfakehdr *)from;
 
@@ -425,20 +588,33 @@ static int ping_getfrag(void *from, char *to,
                            pfh->iov, 0, fraglen - sizeof(struct icmphdr),
                            &pfh->wcheck))
                        return -EFAULT;
+       } else if (offset < sizeof(struct icmphdr)) {
+                       BUG();
+       } else {
+               if (csum_partial_copy_fromiovecend
+                               (to, pfh->iov, offset - sizeof(struct icmphdr),
+                                fraglen, &pfh->wcheck))
+                       return -EFAULT;
+       }
 
-               return 0;
+#if IS_ENABLED(CONFIG_IPV6)
+       /* For IPv6, checksum each skb as we go along, as expected by
+        * icmpv6_push_pending_frames. For IPv4, accumulate the checksum in
+        * wcheck, it will be finalized in ping_v4_push_pending_frames.
+        */
+       if (pfh->family == AF_INET6) {
+               skb->csum = pfh->wcheck;
+               skb->ip_summed = CHECKSUM_NONE;
+               pfh->wcheck = 0;
        }
-       if (offset < sizeof(struct icmphdr))
-               BUG();
-       if (csum_partial_copy_fromiovecend
-                       (to, pfh->iov, offset - sizeof(struct icmphdr),
-                        fraglen, &pfh->wcheck))
-               return -EFAULT;
+#endif
+
        return 0;
 }
+EXPORT_SYMBOL_GPL(ping_getfrag);
 
-static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh,
-                                   struct flowi4 *fl4)
+static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh,
+                                      struct flowi4 *fl4)
 {
        struct sk_buff *skb = skb_peek(&sk->sk_write_queue);
 
@@ -450,24 +626,9 @@ static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh,
        return ip_push_pending_frames(sk, fl4);
 }
 
-static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
-                       size_t len)
-{
-       struct net *net = sock_net(sk);
-       struct flowi4 fl4;
-       struct inet_sock *inet = inet_sk(sk);
-       struct ipcm_cookie ipc;
-       struct icmphdr user_icmph;
-       struct pingfakehdr pfh;
-       struct rtable *rt = NULL;
-       struct ip_options_data opt_copy;
-       int free = 0;
-       __be32 saddr, daddr, faddr;
-       u8  tos;
-       int err;
-
-       pr_debug("ping_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num);
-
+int ping_common_sendmsg(int family, struct msghdr *msg, size_t len,
+                       void *user_icmph, size_t icmph_len) {
+       u8 type, code;
 
        if (len > 0xFFFF)
                return -EMSGSIZE;
@@ -482,15 +643,53 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        /*
         *      Fetch the ICMP header provided by the userland.
-        *      iovec is modified!
+        *      iovec is modified! The ICMP header is consumed.
         */
-
-       if (memcpy_fromiovec((u8 *)&user_icmph, msg->msg_iov,
-                            sizeof(struct icmphdr)))
+       if (memcpy_fromiovec(user_icmph, msg->msg_iov, icmph_len))
                return -EFAULT;
-       if (!ping_supported(user_icmph.type, user_icmph.code))
+
+       if (family == AF_INET) {
+               type = ((struct icmphdr *) user_icmph)->type;
+               code = ((struct icmphdr *) user_icmph)->code;
+#if IS_ENABLED(CONFIG_IPV6)
+       } else if (family == AF_INET6) {
+               type = ((struct icmp6hdr *) user_icmph)->icmp6_type;
+               code = ((struct icmp6hdr *) user_icmph)->icmp6_code;
+#endif
+       } else {
+               BUG();
+       }
+
+       if (!ping_supported(family, type, code))
                return -EINVAL;
 
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ping_common_sendmsg);
+
+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;
+       struct inet_sock *inet = inet_sk(sk);
+       struct ipcm_cookie ipc;
+       struct icmphdr user_icmph;
+       struct pingfakehdr pfh;
+       struct rtable *rt = NULL;
+       struct ip_options_data opt_copy;
+       int free = 0;
+       __be32 saddr, daddr, faddr;
+       u8  tos;
+       int err;
+
+       pr_debug("ping_v4_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num);
+
+       err = ping_common_sendmsg(AF_INET, msg, len, &user_icmph,
+                                 sizeof(user_icmph));
+       if (err)
+               return err;
+
        /*
         *      Get and verify the address.
         */
@@ -595,13 +794,14 @@ back_from_confirm:
        pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence;
        pfh.iov = msg->msg_iov;
        pfh.wcheck = 0;
+       pfh.family = AF_INET;
 
        err = ip_append_data(sk, &fl4, ping_getfrag, &pfh, len,
                        0, &ipc, &rt, msg->msg_flags);
        if (err)
                ip_flush_pending_frames(sk);
        else
-               err = ping_push_pending_frames(sk, &pfh, &fl4);
+               err = ping_v4_push_pending_frames(sk, &pfh, &fl4);
        release_sock(sk);
 
 out:
@@ -622,11 +822,13 @@ do_confirm:
        goto out;
 }
 
-static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
-                       size_t len, int noblock, int flags, int *addr_len)
+int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+                size_t len, int noblock, int flags, int *addr_len)
 {
        struct inet_sock *isk = inet_sk(sk);
-       struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
+       int family = sk->sk_family;
+       struct sockaddr_in *sin;
+       struct sockaddr_in6 *sin6;
        struct sk_buff *skb;
        int copied, err;
 
@@ -636,11 +838,22 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        if (flags & MSG_OOB)
                goto out;
 
-       if (addr_len)
-               *addr_len = sizeof(*sin);
+       if (addr_len) {
+               if (family == AF_INET)
+                       *addr_len = sizeof(*sin);
+               else if (family == AF_INET6 && addr_len)
+                       *addr_len = sizeof(*sin6);
+       }
 
-       if (flags & MSG_ERRQUEUE)
-               return ip_recv_error(sk, msg, len);
+       if (flags & MSG_ERRQUEUE) {
+               if (family == AF_INET) {
+                       return ip_recv_error(sk, msg, len);
+#if IS_ENABLED(CONFIG_IPV6)
+               } else if (family == AF_INET6) {
+                       return pingv6_ops.ipv6_recv_error(sk, msg, len);
+#endif
+               }
+       }
 
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
@@ -659,15 +872,40 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        sock_recv_timestamp(msg, sk, skb);
 
-       /* Copy the address. */
-       if (sin) {
+       /* Copy the address and add cmsg data. */
+       if (family == AF_INET) {
+               sin = (struct sockaddr_in *) msg->msg_name;
                sin->sin_family = AF_INET;
                sin->sin_port = 0 /* skb->h.uh->source */;
                sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
                memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+
+               if (isk->cmsg_flags)
+                       ip_cmsg_recv(msg, skb);
+
+#if IS_ENABLED(CONFIG_IPV6)
+       } else if (family == AF_INET6) {
+               struct ipv6_pinfo *np = inet6_sk(sk);
+               struct ipv6hdr *ip6 = ipv6_hdr(skb);
+               sin6 = (struct sockaddr_in6 *) msg->msg_name;
+               sin6->sin6_family = AF_INET6;
+               sin6->sin6_port = 0;
+               sin6->sin6_addr = ip6->saddr;
+
+               sin6->sin6_flowinfo = 0;
+               if (np->sndflow)
+                       sin6->sin6_flowinfo = ip6_flowinfo(ip6);
+
+               sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr,
+                                                         IP6CB(skb)->iif);
+
+               if (inet6_sk(sk)->rxopt.all)
+                       pingv6_ops.ip6_datagram_recv_ctl(sk, msg, skb);
+#endif
+       } else {
+               BUG();
        }
-       if (isk->cmsg_flags)
-               ip_cmsg_recv(msg, skb);
+
        err = copied;
 
 done:
@@ -676,8 +914,9 @@ out:
        pr_debug("ping_recvmsg -> %d\n", err);
        return err;
 }
+EXPORT_SYMBOL_GPL(ping_recvmsg);
 
-static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n",
                 inet_sk(sk), inet_sk(sk)->inet_num, skb);
@@ -688,6 +927,7 @@ static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
        }
        return 0;
 }
+EXPORT_SYMBOL_GPL(ping_queue_rcv_skb);
 
 
 /*
@@ -698,10 +938,7 @@ void ping_rcv(struct sk_buff *skb)
 {
        struct sock *sk;
        struct net *net = dev_net(skb->dev);
-       struct iphdr *iph = ip_hdr(skb);
        struct icmphdr *icmph = icmp_hdr(skb);
-       __be32 saddr = iph->saddr;
-       __be32 daddr = iph->daddr;
 
        /* We assume the packet has already been checked by icmp_rcv */
 
@@ -711,8 +948,7 @@ void ping_rcv(struct sk_buff *skb)
        /* Push ICMP header back */
        skb_push(skb, skb->data - (u8 *)icmph);
 
-       sk = ping_v4_lookup(net, saddr, daddr, ntohs(icmph->un.echo.id),
-                           skb->dev->ifindex);
+       sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id));
        if (sk != NULL) {
                pr_debug("rcv on socket %p\n", sk);
                ping_queue_rcv_skb(sk, skb_get(skb));
@@ -723,6 +959,7 @@ void ping_rcv(struct sk_buff *skb)
 
        /* We're called from icmp_rcv(). kfree_skb() is done there. */
 }
+EXPORT_SYMBOL_GPL(ping_rcv);
 
 struct proto ping_prot = {
        .name =         "PING",
@@ -733,14 +970,14 @@ struct proto ping_prot = {
        .disconnect =   udp_disconnect,
        .setsockopt =   ip_setsockopt,
        .getsockopt =   ip_getsockopt,
-       .sendmsg =      ping_sendmsg,
+       .sendmsg =      ping_v4_sendmsg,
        .recvmsg =      ping_recvmsg,
        .bind =         ping_bind,
        .backlog_rcv =  ping_queue_rcv_skb,
        .release_cb =   ip4_datagram_release_cb,
-       .hash =         ping_v4_hash,
-       .unhash =       ping_v4_unhash,
-       .get_port =     ping_v4_get_port,
+       .hash =         ping_hash,
+       .unhash =       ping_unhash,
+       .get_port =     ping_get_port,
        .obj_size =     sizeof(struct inet_sock),
 };
 EXPORT_SYMBOL(ping_prot);
@@ -764,7 +1001,8 @@ static struct sock *ping_get_first(struct seq_file *seq, int start)
                        continue;
 
                sk_nulls_for_each(sk, node, hslot) {
-                       if (net_eq(sock_net(sk), net))
+                       if (net_eq(sock_net(sk), net) &&
+                           sk->sk_family == state->family)
                                goto found;
                }
        }
@@ -797,17 +1035,24 @@ static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos)
        return pos ? NULL : sk;
 }
 
-static void *ping_seq_start(struct seq_file *seq, loff_t *pos)
+void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family)
 {
        struct ping_iter_state *state = seq->private;
        state->bucket = 0;
+       state->family = family;
 
        read_lock_bh(&ping_table.lock);
 
        return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN;
 }
+EXPORT_SYMBOL_GPL(ping_seq_start);
+
+static void *ping_v4_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       return ping_seq_start(seq, pos, AF_INET);
+}
 
-static void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        struct sock *sk;
 
@@ -819,13 +1064,15 @@ static void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        ++*pos;
        return sk;
 }
+EXPORT_SYMBOL_GPL(ping_seq_next);
 
-static void ping_seq_stop(struct seq_file *seq, void *v)
+void ping_seq_stop(struct seq_file *seq, void *v)
 {
        read_unlock_bh(&ping_table.lock);
 }
+EXPORT_SYMBOL_GPL(ping_seq_stop);
 
-static void ping_format_sock(struct sock *sp, struct seq_file *f,
+static void ping_v4_format_sock(struct sock *sp, struct seq_file *f,
                int bucket, int *len)
 {
        struct inet_sock *inet = inet_sk(sp);
@@ -846,7 +1093,7 @@ static void ping_format_sock(struct sock *sp, struct seq_file *f,
                atomic_read(&sp->sk_drops), len);
 }
 
-static int ping_seq_show(struct seq_file *seq, void *v)
+static int ping_v4_seq_show(struct seq_file *seq, void *v)
 {
        if (v == SEQ_START_TOKEN)
                seq_printf(seq, "%-127s\n",
@@ -857,72 +1104,86 @@ static int ping_seq_show(struct seq_file *seq, void *v)
                struct ping_iter_state *state = seq->private;
                int len;
 
-               ping_format_sock(v, seq, state->bucket, &len);
+               ping_v4_format_sock(v, seq, state->bucket, &len);
                seq_printf(seq, "%*s\n", 127 - len, "");
        }
        return 0;
 }
 
-static const struct seq_operations ping_seq_ops = {
-       .show           = ping_seq_show,
-       .start          = ping_seq_start,
+static const struct seq_operations ping_v4_seq_ops = {
+       .show           = ping_v4_seq_show,
+       .start          = ping_v4_seq_start,
        .next           = ping_seq_next,
        .stop           = ping_seq_stop,
 };
 
 static int ping_seq_open(struct inode *inode, struct file *file)
 {
-       return seq_open_net(inode, file, &ping_seq_ops,
+       struct ping_seq_afinfo *afinfo = PDE_DATA(inode);
+       return seq_open_net(inode, file, &afinfo->seq_ops,
                           sizeof(struct ping_iter_state));
 }
 
-static const struct file_operations ping_seq_fops = {
+const struct file_operations ping_seq_fops = {
        .open           = ping_seq_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release_net,
 };
+EXPORT_SYMBOL_GPL(ping_seq_fops);
+
+static struct ping_seq_afinfo ping_v4_seq_afinfo = {
+       .name           = "icmp",
+       .family         = AF_INET,
+       .seq_fops       = &ping_seq_fops,
+       .seq_ops        = {
+               .start          = ping_v4_seq_start,
+               .show           = ping_v4_seq_show,
+               .next           = ping_seq_next,
+               .stop           = ping_seq_stop,
+       },
+};
 
-static int ping_proc_register(struct net *net)
+int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo)
 {
        struct proc_dir_entry *p;
-       int rc = 0;
-
-       p = proc_create("icmp", S_IRUGO, net->proc_net, &ping_seq_fops);
+       p = proc_create_data(afinfo->name, S_IRUGO, net->proc_net,
+                            afinfo->seq_fops, afinfo);
        if (!p)
-               rc = -ENOMEM;
-       return rc;
+               return -ENOMEM;
+       return 0;
 }
+EXPORT_SYMBOL_GPL(ping_proc_register);
 
-static void ping_proc_unregister(struct net *net)
+void ping_proc_unregister(struct net *net, struct ping_seq_afinfo *afinfo)
 {
-       remove_proc_entry("icmp", net->proc_net);
+       remove_proc_entry(afinfo->name, net->proc_net);
 }
+EXPORT_SYMBOL_GPL(ping_proc_unregister);
 
-
-static int __net_init ping_proc_init_net(struct net *net)
+static int __net_init ping_v4_proc_init_net(struct net *net)
 {
-       return ping_proc_register(net);
+       return ping_proc_register(net, &ping_v4_seq_afinfo);
 }
 
-static void __net_exit ping_proc_exit_net(struct net *net)
+static void __net_exit ping_v4_proc_exit_net(struct net *net)
 {
-       ping_proc_unregister(net);
+       ping_proc_unregister(net, &ping_v4_seq_afinfo);
 }
 
-static struct pernet_operations ping_net_ops = {
-       .init = ping_proc_init_net,
-       .exit = ping_proc_exit_net,
+static struct pernet_operations ping_v4_net_ops = {
+       .init = ping_v4_proc_init_net,
+       .exit = ping_v4_proc_exit_net,
 };
 
 int __init ping_proc_init(void)
 {
-       return register_pernet_subsys(&ping_net_ops);
+       return register_pernet_subsys(&ping_v4_net_ops);
 }
 
 void ping_proc_exit(void)
 {
-       unregister_pernet_subsys(&ping_net_ops);
+       unregister_pernet_subsys(&ping_v4_net_ops);
 }
 
 #endif
index d35bbf0cf4045d04f67d30e31f15c5271058dd5a..198ea596f2d9a783f9d19bbd6be5924f81afb4c6 100644 (file)
@@ -594,11 +594,25 @@ static inline u32 fnhe_hashfun(__be32 daddr)
        return hval & (FNHE_HASH_SIZE - 1);
 }
 
+static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnhe)
+{
+       rt->rt_pmtu = fnhe->fnhe_pmtu;
+       rt->dst.expires = fnhe->fnhe_expires;
+
+       if (fnhe->fnhe_gw) {
+               rt->rt_flags |= RTCF_REDIRECTED;
+               rt->rt_gateway = fnhe->fnhe_gw;
+               rt->rt_uses_gateway = 1;
+       }
+}
+
 static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
                                  u32 pmtu, unsigned long expires)
 {
        struct fnhe_hash_bucket *hash;
        struct fib_nh_exception *fnhe;
+       struct rtable *rt;
+       unsigned int i;
        int depth;
        u32 hval = fnhe_hashfun(daddr);
 
@@ -627,8 +641,12 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
                        fnhe->fnhe_gw = gw;
                if (pmtu) {
                        fnhe->fnhe_pmtu = pmtu;
-                       fnhe->fnhe_expires = expires;
+                       fnhe->fnhe_expires = max(1UL, expires);
                }
+               /* Update all cached dsts too */
+               rt = rcu_dereference(fnhe->fnhe_rth);
+               if (rt)
+                       fill_route_from_fnhe(rt, fnhe);
        } else {
                if (depth > FNHE_RECLAIM_DEPTH)
                        fnhe = fnhe_oldest(hash);
@@ -640,10 +658,23 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
                        fnhe->fnhe_next = hash->chain;
                        rcu_assign_pointer(hash->chain, fnhe);
                }
+               fnhe->fnhe_genid = fnhe_genid(dev_net(nh->nh_dev));
                fnhe->fnhe_daddr = daddr;
                fnhe->fnhe_gw = gw;
                fnhe->fnhe_pmtu = pmtu;
                fnhe->fnhe_expires = expires;
+
+               /* Exception created; mark the cached routes for the nexthop
+                * stale, so anyone caching it rechecks if this exception
+                * applies to them.
+                */
+               for_each_possible_cpu(i) {
+                       struct rtable __rcu **prt;
+                       prt = per_cpu_ptr(nh->nh_pcpu_rth_output, i);
+                       rt = rcu_dereference(*prt);
+                       if (rt)
+                               rt->dst.obsolete = DST_OBSOLETE_KILL;
+               }
        }
 
        fnhe->fnhe_stamp = jiffies;
@@ -922,12 +953,9 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
        if (mtu < ip_rt_min_pmtu)
                mtu = ip_rt_min_pmtu;
 
-       if (!rt->rt_pmtu) {
-               dst->obsolete = DST_OBSOLETE_KILL;
-       } else {
-               rt->rt_pmtu = mtu;
-               dst->expires = max(1UL, jiffies + ip_rt_mtu_expires);
-       }
+       if (rt->rt_pmtu == mtu &&
+           time_before(jiffies, dst->expires - ip_rt_mtu_expires / 2))
+               return;
 
        rcu_read_lock();
        if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) {
@@ -1068,11 +1096,11 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
         * DST_OBSOLETE_FORCE_CHK which forces validation calls down
         * into this function always.
         *
-        * When a PMTU/redirect information update invalidates a
-        * route, this is indicated by setting obsolete to
-        * DST_OBSOLETE_KILL.
+        * When a PMTU/redirect information update invalidates a route,
+        * this is indicated by setting obsolete to DST_OBSOLETE_KILL or
+        * DST_OBSOLETE_DEAD by dst_free().
         */
-       if (dst->obsolete == DST_OBSOLETE_KILL || rt_is_expired(rt))
+       if (dst->obsolete != DST_OBSOLETE_FORCE_CHK || rt_is_expired(rt))
                return NULL;
        return dst;
 }
@@ -1214,26 +1242,17 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
        spin_lock_bh(&fnhe_lock);
 
        if (daddr == fnhe->fnhe_daddr) {
+               int genid = fnhe_genid(dev_net(rt->dst.dev));
                struct rtable *orig = rcu_dereference(fnhe->fnhe_rth);
-               if (orig && rt_is_expired(orig)) {
+
+               if (fnhe->fnhe_genid != genid) {
+                       fnhe->fnhe_genid = genid;
                        fnhe->fnhe_gw = 0;
                        fnhe->fnhe_pmtu = 0;
                        fnhe->fnhe_expires = 0;
                }
-               if (fnhe->fnhe_pmtu) {
-                       unsigned long expires = fnhe->fnhe_expires;
-                       unsigned long diff = expires - jiffies;
-
-                       if (time_before(jiffies, expires)) {
-                               rt->rt_pmtu = fnhe->fnhe_pmtu;
-                               dst_set_expires(&rt->dst, diff);
-                       }
-               }
-               if (fnhe->fnhe_gw) {
-                       rt->rt_flags |= RTCF_REDIRECTED;
-                       rt->rt_gateway = fnhe->fnhe_gw;
-                       rt->rt_uses_gateway = 1;
-               } else if (!rt->rt_gateway)
+               fill_route_from_fnhe(rt, fnhe);
+               if (!rt->rt_gateway)
                        rt->rt_gateway = daddr;
 
                rcu_assign_pointer(fnhe->fnhe_rth, rt);
@@ -2433,8 +2452,11 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
                                        void __user *buffer,
                                        size_t *lenp, loff_t *ppos)
 {
+       struct net *net = (struct net *)__ctl->extra1;
+
        if (write) {
-               rt_cache_flush((struct net *)__ctl->extra1);
+               rt_cache_flush(net);
+               fnhe_genid_bump(net);
                return 0;
        }
 
@@ -2609,6 +2631,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
 static __net_init int rt_genid_init(struct net *net)
 {
        atomic_set(&net->rt_genid, 0);
+       atomic_set(&net->fnhe_genid, 0);
        get_random_bytes(&net->ipv4.dev_addr_genid,
                         sizeof(net->ipv4.dev_addr_genid));
        return 0;
index ab450c099aa49a3d4b68ca531e7f5426a8eabaf1..b5d4ad9880532ae749fa952ceedf64be9b6b7ea7 100644 (file)
@@ -436,6 +436,8 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
        struct sock *sk = sock->sk;
        const struct tcp_sock *tp = tcp_sk(sk);
 
+       sock_rps_record_flow(sk);
+
        sock_poll_wait(file, sk_sleep(sk), wait);
        if (sk->sk_state == TCP_LISTEN)
                return inet_csk_listen_poll(sk);
@@ -2917,6 +2919,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
                               SKB_GSO_TCP_ECN |
                               SKB_GSO_TCPV6 |
                               SKB_GSO_GRE |
+                              SKB_GSO_MPLS |
                               SKB_GSO_UDP_TUNNEL |
                               0) ||
                             !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
@@ -2988,7 +2991,8 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
                swap(gso_skb->truesize, skb->truesize);
        }
 
-       delta = htonl(oldlen + (skb->tail - skb->transport_header) +
+       delta = htonl(oldlen + (skb_tail_pointer(skb) -
+                               skb_transport_header(skb)) +
                      skb->data_len);
        th->check = ~csum_fold((__force __wsum)((__force u32)th->check +
                                (__force u32)delta));
@@ -3115,9 +3119,8 @@ int tcp_gro_complete(struct sk_buff *skb)
 EXPORT_SYMBOL(tcp_gro_complete);
 
 #ifdef CONFIG_TCP_MD5SIG
-static unsigned long tcp_md5sig_users;
-static struct tcp_md5sig_pool __percpu *tcp_md5sig_pool;
-static DEFINE_SPINLOCK(tcp_md5sig_pool_lock);
+static struct tcp_md5sig_pool __percpu *tcp_md5sig_pool __read_mostly;
+static DEFINE_MUTEX(tcp_md5sig_mutex);
 
 static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool __percpu *pool)
 {
@@ -3132,30 +3135,14 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool __percpu *pool)
        free_percpu(pool);
 }
 
-void tcp_free_md5sig_pool(void)
-{
-       struct tcp_md5sig_pool __percpu *pool = NULL;
-
-       spin_lock_bh(&tcp_md5sig_pool_lock);
-       if (--tcp_md5sig_users == 0) {
-               pool = tcp_md5sig_pool;
-               tcp_md5sig_pool = NULL;
-       }
-       spin_unlock_bh(&tcp_md5sig_pool_lock);
-       if (pool)
-               __tcp_free_md5sig_pool(pool);
-}
-EXPORT_SYMBOL(tcp_free_md5sig_pool);
-
-static struct tcp_md5sig_pool __percpu *
-__tcp_alloc_md5sig_pool(struct sock *sk)
+static void __tcp_alloc_md5sig_pool(void)
 {
        int cpu;
        struct tcp_md5sig_pool __percpu *pool;
 
        pool = alloc_percpu(struct tcp_md5sig_pool);
        if (!pool)
-               return NULL;
+               return;
 
        for_each_possible_cpu(cpu) {
                struct crypto_hash *hash;
@@ -3166,53 +3153,27 @@ __tcp_alloc_md5sig_pool(struct sock *sk)
 
                per_cpu_ptr(pool, cpu)->md5_desc.tfm = hash;
        }
-       return pool;
+       /* before setting tcp_md5sig_pool, we must commit all writes
+        * to memory. See ACCESS_ONCE() in tcp_get_md5sig_pool()
+        */
+       smp_wmb();
+       tcp_md5sig_pool = pool;
+       return;
 out_free:
        __tcp_free_md5sig_pool(pool);
-       return NULL;
 }
 
-struct tcp_md5sig_pool __percpu *tcp_alloc_md5sig_pool(struct sock *sk)
+bool tcp_alloc_md5sig_pool(void)
 {
-       struct tcp_md5sig_pool __percpu *pool;
-       bool alloc = false;
-
-retry:
-       spin_lock_bh(&tcp_md5sig_pool_lock);
-       pool = tcp_md5sig_pool;
-       if (tcp_md5sig_users++ == 0) {
-               alloc = true;
-               spin_unlock_bh(&tcp_md5sig_pool_lock);
-       } else if (!pool) {
-               tcp_md5sig_users--;
-               spin_unlock_bh(&tcp_md5sig_pool_lock);
-               cpu_relax();
-               goto retry;
-       } else
-               spin_unlock_bh(&tcp_md5sig_pool_lock);
-
-       if (alloc) {
-               /* we cannot hold spinlock here because this may sleep. */
-               struct tcp_md5sig_pool __percpu *p;
-
-               p = __tcp_alloc_md5sig_pool(sk);
-               spin_lock_bh(&tcp_md5sig_pool_lock);
-               if (!p) {
-                       tcp_md5sig_users--;
-                       spin_unlock_bh(&tcp_md5sig_pool_lock);
-                       return NULL;
-               }
-               pool = tcp_md5sig_pool;
-               if (pool) {
-                       /* oops, it has already been assigned. */
-                       spin_unlock_bh(&tcp_md5sig_pool_lock);
-                       __tcp_free_md5sig_pool(p);
-               } else {
-                       tcp_md5sig_pool = pool = p;
-                       spin_unlock_bh(&tcp_md5sig_pool_lock);
-               }
+       if (unlikely(!tcp_md5sig_pool)) {
+               mutex_lock(&tcp_md5sig_mutex);
+
+               if (!tcp_md5sig_pool)
+                       __tcp_alloc_md5sig_pool();
+
+               mutex_unlock(&tcp_md5sig_mutex);
        }
-       return pool;
+       return tcp_md5sig_pool != NULL;
 }
 EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
 
@@ -3229,28 +3190,15 @@ struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
        struct tcp_md5sig_pool __percpu *p;
 
        local_bh_disable();
-
-       spin_lock(&tcp_md5sig_pool_lock);
-       p = tcp_md5sig_pool;
+       p = ACCESS_ONCE(tcp_md5sig_pool);
        if (p)
-               tcp_md5sig_users++;
-       spin_unlock(&tcp_md5sig_pool_lock);
-
-       if (p)
-               return this_cpu_ptr(p);
+               return __this_cpu_ptr(p);
 
        local_bh_enable();
        return NULL;
 }
 EXPORT_SYMBOL(tcp_get_md5sig_pool);
 
-void tcp_put_md5sig_pool(void)
-{
-       local_bh_enable();
-       tcp_free_md5sig_pool();
-}
-EXPORT_SYMBOL(tcp_put_md5sig_pool);
-
 int tcp_md5_hash_header(struct tcp_md5sig_pool *hp,
                        const struct tcphdr *th)
 {
index 9c6225780bd5aafdb175a762d45c704e82416582..907311c9a0121226209a93f381bdd0d6774e5c54 100644 (file)
@@ -360,9 +360,7 @@ static void tcp_fixup_rcvbuf(struct sock *sk)
        if (mss > 1460)
                icwnd = max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2);
 
-       rcvmem = SKB_TRUESIZE(mss + MAX_TCP_HEADER);
-       while (tcp_win_from_space(rcvmem) < mss)
-               rcvmem += 128;
+       rcvmem = 2 * SKB_TRUESIZE(mss + MAX_TCP_HEADER);
 
        rcvmem *= icwnd;
 
@@ -1257,8 +1255,6 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
 
        if (skb == tp->retransmit_skb_hint)
                tp->retransmit_skb_hint = prev;
-       if (skb == tp->scoreboard_skb_hint)
-               tp->scoreboard_skb_hint = prev;
        if (skb == tp->lost_skb_hint) {
                tp->lost_skb_hint = prev;
                tp->lost_cnt_hint -= tcp_skb_pcount(prev);
@@ -1966,20 +1962,6 @@ static bool tcp_pause_early_retransmit(struct sock *sk, int flag)
        return true;
 }
 
-static inline int tcp_skb_timedout(const struct sock *sk,
-                                  const struct sk_buff *skb)
-{
-       return tcp_time_stamp - TCP_SKB_CB(skb)->when > inet_csk(sk)->icsk_rto;
-}
-
-static inline int tcp_head_timedout(const struct sock *sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-
-       return tp->packets_out &&
-              tcp_skb_timedout(sk, tcp_write_queue_head(sk));
-}
-
 /* Linux NewReno/SACK/FACK/ECN state machine.
  * --------------------------------------
  *
@@ -2086,12 +2068,6 @@ static bool tcp_time_to_recover(struct sock *sk, int flag)
        if (tcp_dupack_heuristics(tp) > tp->reordering)
                return true;
 
-       /* Trick#3 : when we use RFC2988 timer restart, fast
-        * retransmit can be triggered by timeout of queue head.
-        */
-       if (tcp_is_fack(tp) && tcp_head_timedout(sk))
-               return true;
-
        /* Trick#4: It is still not OK... But will it be useful to delay
         * recovery more?
         */
@@ -2128,44 +2104,6 @@ static bool tcp_time_to_recover(struct sock *sk, int flag)
        return false;
 }
 
-/* New heuristics: it is possible only after we switched to restart timer
- * each time when something is ACKed. Hence, we can detect timed out packets
- * during fast retransmit without falling to slow start.
- *
- * Usefulness of this as is very questionable, since we should know which of
- * the segments is the next to timeout which is relatively expensive to find
- * in general case unless we add some data structure just for that. The
- * current approach certainly won't find the right one too often and when it
- * finally does find _something_ it usually marks large part of the window
- * right away (because a retransmission with a larger timestamp blocks the
- * loop from advancing). -ij
- */
-static void tcp_timeout_skbs(struct sock *sk)
-{
-       struct tcp_sock *tp = tcp_sk(sk);
-       struct sk_buff *skb;
-
-       if (!tcp_is_fack(tp) || !tcp_head_timedout(sk))
-               return;
-
-       skb = tp->scoreboard_skb_hint;
-       if (tp->scoreboard_skb_hint == NULL)
-               skb = tcp_write_queue_head(sk);
-
-       tcp_for_write_queue_from(skb, sk) {
-               if (skb == tcp_send_head(sk))
-                       break;
-               if (!tcp_skb_timedout(sk, skb))
-                       break;
-
-               tcp_skb_mark_lost(tp, skb);
-       }
-
-       tp->scoreboard_skb_hint = skb;
-
-       tcp_verify_left_out(tp);
-}
-
 /* Detect loss in event "A" above by marking head of queue up as lost.
  * For FACK or non-SACK(Reno) senders, the first "packets" number of segments
  * are considered lost. For RFC3517 SACK, a segment is considered lost if it
@@ -2251,8 +2189,6 @@ static void tcp_update_scoreboard(struct sock *sk, int fast_rexmit)
                else if (fast_rexmit)
                        tcp_mark_head_lost(sk, 1, 1);
        }
-
-       tcp_timeout_skbs(sk);
 }
 
 /* CWND moderation, preventing bursts due to too big ACKs
@@ -2307,10 +2243,22 @@ static void DBGUNDO(struct sock *sk, const char *msg)
 #define DBGUNDO(x...) do { } while (0)
 #endif
 
-static void tcp_undo_cwr(struct sock *sk, const bool undo_ssthresh)
+static void tcp_undo_cwnd_reduction(struct sock *sk, bool unmark_loss)
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
+       if (unmark_loss) {
+               struct sk_buff *skb;
+
+               tcp_for_write_queue(skb, sk) {
+                       if (skb == tcp_send_head(sk))
+                               break;
+                       TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
+               }
+               tp->lost_out = 0;
+               tcp_clear_all_retrans_hints(tp);
+       }
+
        if (tp->prior_ssthresh) {
                const struct inet_connection_sock *icsk = inet_csk(sk);
 
@@ -2319,7 +2267,7 @@ static void tcp_undo_cwr(struct sock *sk, const bool undo_ssthresh)
                else
                        tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh << 1);
 
-               if (undo_ssthresh && tp->prior_ssthresh > tp->snd_ssthresh) {
+               if (tp->prior_ssthresh > tp->snd_ssthresh) {
                        tp->snd_ssthresh = tp->prior_ssthresh;
                        TCP_ECN_withdraw_cwr(tp);
                }
@@ -2327,6 +2275,7 @@ static void tcp_undo_cwr(struct sock *sk, const bool undo_ssthresh)
                tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh);
        }
        tp->snd_cwnd_stamp = tcp_time_stamp;
+       tp->undo_marker = 0;
 }
 
 static inline bool tcp_may_undo(const struct tcp_sock *tp)
@@ -2346,14 +2295,13 @@ static bool tcp_try_undo_recovery(struct sock *sk)
                 * or our original transmission succeeded.
                 */
                DBGUNDO(sk, inet_csk(sk)->icsk_ca_state == TCP_CA_Loss ? "loss" : "retrans");
-               tcp_undo_cwr(sk, true);
+               tcp_undo_cwnd_reduction(sk, false);
                if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss)
                        mib_idx = LINUX_MIB_TCPLOSSUNDO;
                else
                        mib_idx = LINUX_MIB_TCPFULLUNDO;
 
                NET_INC_STATS_BH(sock_net(sk), mib_idx);
-               tp->undo_marker = 0;
        }
        if (tp->snd_una == tp->high_seq && tcp_is_reno(tp)) {
                /* Hold old state until something *above* high_seq
@@ -2367,16 +2315,17 @@ static bool tcp_try_undo_recovery(struct sock *sk)
 }
 
 /* Try to undo cwnd reduction, because D-SACKs acked all retransmitted data */
-static void tcp_try_undo_dsack(struct sock *sk)
+static bool tcp_try_undo_dsack(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
        if (tp->undo_marker && !tp->undo_retrans) {
                DBGUNDO(sk, "D-SACK");
-               tcp_undo_cwr(sk, true);
-               tp->undo_marker = 0;
+               tcp_undo_cwnd_reduction(sk, false);
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO);
+               return true;
        }
+       return false;
 }
 
 /* We can clear retrans_stamp when there are no retransmissions in the
@@ -2408,60 +2357,20 @@ static bool tcp_any_retrans_done(const struct sock *sk)
        return false;
 }
 
-/* Undo during fast recovery after partial ACK. */
-
-static int tcp_try_undo_partial(struct sock *sk, int acked)
-{
-       struct tcp_sock *tp = tcp_sk(sk);
-       /* Partial ACK arrived. Force Hoe's retransmit. */
-       int failed = tcp_is_reno(tp) || (tcp_fackets_out(tp) > tp->reordering);
-
-       if (tcp_may_undo(tp)) {
-               /* Plain luck! Hole if filled with delayed
-                * packet, rather than with a retransmit.
-                */
-               if (!tcp_any_retrans_done(sk))
-                       tp->retrans_stamp = 0;
-
-               tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1);
-
-               DBGUNDO(sk, "Hoe");
-               tcp_undo_cwr(sk, false);
-               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO);
-
-               /* So... Do not make Hoe's retransmit yet.
-                * If the first packet was delayed, the rest
-                * ones are most probably delayed as well.
-                */
-               failed = 0;
-       }
-       return failed;
-}
-
 /* Undo during loss recovery after partial ACK or using F-RTO. */
 static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo)
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
        if (frto_undo || tcp_may_undo(tp)) {
-               struct sk_buff *skb;
-               tcp_for_write_queue(skb, sk) {
-                       if (skb == tcp_send_head(sk))
-                               break;
-                       TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
-               }
-
-               tcp_clear_all_retrans_hints(tp);
+               tcp_undo_cwnd_reduction(sk, true);
 
                DBGUNDO(sk, "partial loss");
-               tp->lost_out = 0;
-               tcp_undo_cwr(sk, true);
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSUNDO);
                if (frto_undo)
                        NET_INC_STATS_BH(sock_net(sk),
                                         LINUX_MIB_TCPSPURIOUSRTOS);
                inet_csk(sk)->icsk_retransmits = 0;
-               tp->undo_marker = 0;
                if (frto_undo || tcp_is_sack(tp))
                        tcp_set_ca_state(sk, TCP_CA_Open);
                return true;
@@ -2494,12 +2403,14 @@ static void tcp_init_cwnd_reduction(struct sock *sk, const bool set_ssthresh)
        TCP_ECN_queue_cwr(tp);
 }
 
-static void tcp_cwnd_reduction(struct sock *sk, int newly_acked_sacked,
+static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked,
                               int fast_rexmit)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        int sndcnt = 0;
        int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp);
+       int newly_acked_sacked = prior_unsacked -
+                                (tp->packets_out - tp->sacked_out);
 
        tp->prr_delivered += newly_acked_sacked;
        if (tcp_packets_in_flight(tp) > tp->snd_ssthresh) {
@@ -2556,7 +2467,7 @@ static void tcp_try_keep_open(struct sock *sk)
        }
 }
 
-static void tcp_try_to_open(struct sock *sk, int flag, int newly_acked_sacked)
+static void tcp_try_to_open(struct sock *sk, int flag, const int prior_unsacked)
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
@@ -2573,7 +2484,7 @@ static void tcp_try_to_open(struct sock *sk, int flag, int newly_acked_sacked)
                if (inet_csk(sk)->icsk_ca_state != TCP_CA_Open)
                        tcp_moderate_cwnd(tp);
        } else {
-               tcp_cwnd_reduction(sk, newly_acked_sacked, 0);
+               tcp_cwnd_reduction(sk, prior_unsacked, 0);
        }
 }
 
@@ -2731,6 +2642,40 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
        tcp_xmit_retransmit_queue(sk);
 }
 
+/* Undo during fast recovery after partial ACK. */
+static bool tcp_try_undo_partial(struct sock *sk, const int acked,
+                                const int prior_unsacked)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+
+       if (tp->undo_marker && tcp_packet_delayed(tp)) {
+               /* Plain luck! Hole if filled with delayed
+                * packet, rather than with a retransmit.
+                */
+               tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1);
+
+               /* We are getting evidence that the reordering degree is higher
+                * than we realized. If there are no retransmits out then we
+                * can undo. Otherwise we clock out new packets but do not
+                * mark more packets lost or retransmit more.
+                */
+               if (tp->retrans_out) {
+                       tcp_cwnd_reduction(sk, prior_unsacked, 0);
+                       return true;
+               }
+
+               if (!tcp_any_retrans_done(sk))
+                       tp->retrans_stamp = 0;
+
+               DBGUNDO(sk, "partial recovery");
+               tcp_undo_cwnd_reduction(sk, true);
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO);
+               tcp_try_keep_open(sk);
+               return true;
+       }
+       return false;
+}
+
 /* Process an event, which can update packets-in-flight not trivially.
  * Main goal of this function is to calculate new estimate for left_out,
  * taking into account both packets sitting in receiver's buffer and
@@ -2742,15 +2687,14 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
  * It does _not_ decide what to send, it is made in function
  * tcp_xmit_retransmit_queue().
  */
-static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
-                                 int prior_sacked, int prior_packets,
+static void tcp_fastretrans_alert(struct sock *sk, const int acked,
+                                 const int prior_unsacked,
                                  bool is_dupack, int flag)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
-       int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) &&
+       bool do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) &&
                                    (tcp_fackets_out(tp) > tp->reordering));
-       int newly_acked_sacked = 0;
        int fast_rexmit = 0;
 
        if (WARN_ON(!tp->packets_out && tp->sacked_out))
@@ -2802,10 +2746,17 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                if (!(flag & FLAG_SND_UNA_ADVANCED)) {
                        if (tcp_is_reno(tp) && is_dupack)
                                tcp_add_reno_sack(sk);
-               } else
-                       do_lost = tcp_try_undo_partial(sk, pkts_acked);
-               newly_acked_sacked = prior_packets - tp->packets_out +
-                                    tp->sacked_out - prior_sacked;
+               } else {
+                       if (tcp_try_undo_partial(sk, acked, prior_unsacked))
+                               return;
+                       /* Partial ACK arrived. Force fast retransmit. */
+                       do_lost = tcp_is_reno(tp) ||
+                                 tcp_fackets_out(tp) > tp->reordering;
+               }
+               if (tcp_try_undo_dsack(sk)) {
+                       tcp_try_keep_open(sk);
+                       return;
+               }
                break;
        case TCP_CA_Loss:
                tcp_process_loss(sk, flag, is_dupack);
@@ -2819,14 +2770,12 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                        if (is_dupack)
                                tcp_add_reno_sack(sk);
                }
-               newly_acked_sacked = prior_packets - tp->packets_out +
-                                    tp->sacked_out - prior_sacked;
 
                if (icsk->icsk_ca_state <= TCP_CA_Disorder)
                        tcp_try_undo_dsack(sk);
 
                if (!tcp_time_to_recover(sk, flag)) {
-                       tcp_try_to_open(sk, flag, newly_acked_sacked);
+                       tcp_try_to_open(sk, flag, prior_unsacked);
                        return;
                }
 
@@ -2846,9 +2795,9 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                fast_rexmit = 1;
        }
 
-       if (do_lost || (tcp_is_fack(tp) && tcp_head_timedout(sk)))
+       if (do_lost)
                tcp_update_scoreboard(sk, fast_rexmit);
-       tcp_cwnd_reduction(sk, newly_acked_sacked, fast_rexmit);
+       tcp_cwnd_reduction(sk, prior_unsacked, fast_rexmit);
        tcp_xmit_retransmit_queue(sk);
 }
 
@@ -3079,7 +3028,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
 
                tcp_unlink_write_queue(skb, sk);
                sk_wmem_free_skb(sk, skb);
-               tp->scoreboard_skb_hint = NULL;
                if (skb == tp->retransmit_skb_hint)
                        tp->retransmit_skb_hint = NULL;
                if (skb == tp->lost_skb_hint)
@@ -3333,9 +3281,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        u32 prior_in_flight;
        u32 prior_fackets;
        int prior_packets = tp->packets_out;
-       int prior_sacked = tp->sacked_out;
-       int pkts_acked = 0;
-       int previous_packets_out = 0;
+       const int prior_unsacked = tp->packets_out - tp->sacked_out;
+       int acked = 0; /* Number of packets newly acked */
 
        /* If the ack is older than previous acks
         * then we can probably ignore it.
@@ -3410,18 +3357,17 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
                goto no_queue;
 
        /* See if we can take anything off of the retransmit queue. */
-       previous_packets_out = tp->packets_out;
+       acked = tp->packets_out;
        flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una);
-
-       pkts_acked = previous_packets_out - tp->packets_out;
+       acked -= tp->packets_out;
 
        if (tcp_ack_is_dubious(sk, flag)) {
                /* Advance CWND, if state allows this. */
                if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(sk, flag))
                        tcp_cong_avoid(sk, ack, prior_in_flight);
                is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP));
-               tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
-                                     prior_packets, is_dupack, flag);
+               tcp_fastretrans_alert(sk, acked, prior_unsacked,
+                                     is_dupack, flag);
        } else {
                if (flag & FLAG_DATA_ACKED)
                        tcp_cong_avoid(sk, ack, prior_in_flight);
@@ -3443,8 +3389,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 no_queue:
        /* If data was DSACKed, see if we can undo a cwnd reduction. */
        if (flag & FLAG_DSACKING_ACK)
-               tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
-                                     prior_packets, is_dupack, flag);
+               tcp_fastretrans_alert(sk, acked, prior_unsacked,
+                                     is_dupack, flag);
        /* If this ack opens up a zero window, clear backoff.  It was
         * being used to time the probes, and is probably far higher than
         * it needs to be for normal retransmission.
@@ -3466,8 +3412,8 @@ old_ack:
         */
        if (TCP_SKB_CB(skb)->sacked) {
                flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una);
-               tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
-                                     prior_packets, is_dupack, flag);
+               tcp_fastretrans_alert(sk, acked, prior_unsacked,
+                                     is_dupack, flag);
        }
 
        SOCK_DEBUG(sk, "Ack %u before %u:%u\n", ack, tp->snd_una, tp->snd_nxt);
@@ -5601,6 +5547,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct request_sock *req;
        int queued = 0;
+       bool acceptable;
 
        tp->rx_opt.saw_tstamp = 0;
 
@@ -5671,157 +5618,147 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                return 0;
 
        /* step 5: check the ACK field */
-       if (true) {
-               int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH |
-                                                 FLAG_UPDATE_TS_RECENT) > 0;
-
-               switch (sk->sk_state) {
-               case TCP_SYN_RECV:
-                       if (acceptable) {
-                               /* Once we leave TCP_SYN_RECV, we no longer
-                                * need req so release it.
-                                */
-                               if (req) {
-                                       tcp_synack_rtt_meas(sk, req);
-                                       tp->total_retrans = req->num_retrans;
-
-                                       reqsk_fastopen_remove(sk, req, false);
-                               } else {
-                                       /* Make sure socket is routed, for
-                                        * correct metrics.
-                                        */
-                                       icsk->icsk_af_ops->rebuild_header(sk);
-                                       tcp_init_congestion_control(sk);
+       acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH |
+                                     FLAG_UPDATE_TS_RECENT) > 0;
 
-                                       tcp_mtup_init(sk);
-                                       tcp_init_buffer_space(sk);
-                                       tp->copied_seq = tp->rcv_nxt;
-                               }
-                               smp_mb();
-                               tcp_set_state(sk, TCP_ESTABLISHED);
-                               sk->sk_state_change(sk);
-
-                               /* Note, that this wakeup is only for marginal
-                                * crossed SYN case. Passively open sockets
-                                * are not waked up, because sk->sk_sleep ==
-                                * NULL and sk->sk_socket == NULL.
-                                */
-                               if (sk->sk_socket)
-                                       sk_wake_async(sk,
-                                                     SOCK_WAKE_IO, POLL_OUT);
-
-                               tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
-                               tp->snd_wnd = ntohs(th->window) <<
-                                             tp->rx_opt.snd_wscale;
-                               tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
-
-                               if (tp->rx_opt.tstamp_ok)
-                                       tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
-
-                               if (req) {
-                                       /* Re-arm the timer because data may
-                                        * have been sent out. This is similar
-                                        * to the regular data transmission case
-                                        * when new data has just been ack'ed.
-                                        *
-                                        * (TFO) - we could try to be more
-                                        * aggressive and retranmitting any data
-                                        * sooner based on when they were sent
-                                        * out.
-                                        */
-                                       tcp_rearm_rto(sk);
-                               } else
-                                       tcp_init_metrics(sk);
+       switch (sk->sk_state) {
+       case TCP_SYN_RECV:
+               if (!acceptable)
+                       return 1;
 
-                               /* Prevent spurious tcp_cwnd_restart() on
-                                * first data packet.
-                                */
-                               tp->lsndtime = tcp_time_stamp;
+               /* Once we leave TCP_SYN_RECV, we no longer need req
+                * so release it.
+                */
+               if (req) {
+                       tcp_synack_rtt_meas(sk, req);
+                       tp->total_retrans = req->num_retrans;
 
-                               tcp_initialize_rcv_mss(sk);
-                               tcp_fast_path_on(tp);
-                       } else {
-                               return 1;
-                       }
-                       break;
+                       reqsk_fastopen_remove(sk, req, false);
+               } else {
+                       /* Make sure socket is routed, for correct metrics. */
+                       icsk->icsk_af_ops->rebuild_header(sk);
+                       tcp_init_congestion_control(sk);
+
+                       tcp_mtup_init(sk);
+                       tcp_init_buffer_space(sk);
+                       tp->copied_seq = tp->rcv_nxt;
+               }
+               smp_mb();
+               tcp_set_state(sk, TCP_ESTABLISHED);
+               sk->sk_state_change(sk);
+
+               /* Note, that this wakeup is only for marginal crossed SYN case.
+                * Passively open sockets are not waked up, because
+                * sk->sk_sleep == NULL and sk->sk_socket == NULL.
+                */
+               if (sk->sk_socket)
+                       sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);
+
+               tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
+               tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale;
+               tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
+
+               if (tp->rx_opt.tstamp_ok)
+                       tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
 
-               case TCP_FIN_WAIT1:
-                       /* If we enter the TCP_FIN_WAIT1 state and we are a
-                        * Fast Open socket and this is the first acceptable
-                        * ACK we have received, this would have acknowledged
-                        * our SYNACK so stop the SYNACK timer.
+               if (req) {
+                       /* Re-arm the timer because data may have been sent out.
+                        * This is similar to the regular data transmission case
+                        * when new data has just been ack'ed.
+                        *
+                        * (TFO) - we could try to be more aggressive and
+                        * retransmitting any data sooner based on when they
+                        * are sent out.
                         */
-                       if (req != NULL) {
-                               /* Return RST if ack_seq is invalid.
-                                * Note that RFC793 only says to generate a
-                                * DUPACK for it but for TCP Fast Open it seems
-                                * better to treat this case like TCP_SYN_RECV
-                                * above.
-                                */
-                               if (!acceptable)
-                                       return 1;
-                               /* We no longer need the request sock. */
-                               reqsk_fastopen_remove(sk, req, false);
-                               tcp_rearm_rto(sk);
-                       }
-                       if (tp->snd_una == tp->write_seq) {
-                               struct dst_entry *dst;
-
-                               tcp_set_state(sk, TCP_FIN_WAIT2);
-                               sk->sk_shutdown |= SEND_SHUTDOWN;
-
-                               dst = __sk_dst_get(sk);
-                               if (dst)
-                                       dst_confirm(dst);
-
-                               if (!sock_flag(sk, SOCK_DEAD))
-                                       /* Wake up lingering close() */
-                                       sk->sk_state_change(sk);
-                               else {
-                                       int tmo;
-
-                                       if (tp->linger2 < 0 ||
-                                           (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
-                                            after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) {
-                                               tcp_done(sk);
-                                               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
-                                               return 1;
-                                       }
+                       tcp_rearm_rto(sk);
+               } else
+                       tcp_init_metrics(sk);
 
-                                       tmo = tcp_fin_time(sk);
-                                       if (tmo > TCP_TIMEWAIT_LEN) {
-                                               inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN);
-                                       } else if (th->fin || sock_owned_by_user(sk)) {
-                                               /* Bad case. We could lose such FIN otherwise.
-                                                * It is not a big problem, but it looks confusing
-                                                * and not so rare event. We still can lose it now,
-                                                * if it spins in bh_lock_sock(), but it is really
-                                                * marginal case.
-                                                */
-                                               inet_csk_reset_keepalive_timer(sk, tmo);
-                                       } else {
-                                               tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
-                                               goto discard;
-                                       }
-                               }
-                       }
-                       break;
+               /* Prevent spurious tcp_cwnd_restart() on first data packet */
+               tp->lsndtime = tcp_time_stamp;
 
-               case TCP_CLOSING:
-                       if (tp->snd_una == tp->write_seq) {
-                               tcp_time_wait(sk, TCP_TIME_WAIT, 0);
-                               goto discard;
-                       }
+               tcp_initialize_rcv_mss(sk);
+               tcp_fast_path_on(tp);
+               break;
+
+       case TCP_FIN_WAIT1: {
+               struct dst_entry *dst;
+               int tmo;
+
+               /* If we enter the TCP_FIN_WAIT1 state and we are a
+                * Fast Open socket and this is the first acceptable
+                * ACK we have received, this would have acknowledged
+                * our SYNACK so stop the SYNACK timer.
+                */
+               if (req != NULL) {
+                       /* Return RST if ack_seq is invalid.
+                        * Note that RFC793 only says to generate a
+                        * DUPACK for it but for TCP Fast Open it seems
+                        * better to treat this case like TCP_SYN_RECV
+                        * above.
+                        */
+                       if (!acceptable)
+                               return 1;
+                       /* We no longer need the request sock. */
+                       reqsk_fastopen_remove(sk, req, false);
+                       tcp_rearm_rto(sk);
+               }
+               if (tp->snd_una != tp->write_seq)
                        break;
 
-               case TCP_LAST_ACK:
-                       if (tp->snd_una == tp->write_seq) {
-                               tcp_update_metrics(sk);
-                               tcp_done(sk);
-                               goto discard;
-                       }
+               tcp_set_state(sk, TCP_FIN_WAIT2);
+               sk->sk_shutdown |= SEND_SHUTDOWN;
+
+               dst = __sk_dst_get(sk);
+               if (dst)
+                       dst_confirm(dst);
+
+               if (!sock_flag(sk, SOCK_DEAD)) {
+                       /* Wake up lingering close() */
+                       sk->sk_state_change(sk);
                        break;
                }
+
+               if (tp->linger2 < 0 ||
+                   (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+                    after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) {
+                       tcp_done(sk);
+                       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
+                       return 1;
+               }
+
+               tmo = tcp_fin_time(sk);
+               if (tmo > TCP_TIMEWAIT_LEN) {
+                       inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN);
+               } else if (th->fin || sock_owned_by_user(sk)) {
+                       /* Bad case. We could lose such FIN otherwise.
+                        * It is not a big problem, but it looks confusing
+                        * and not so rare event. We still can lose it now,
+                        * if it spins in bh_lock_sock(), but it is really
+                        * marginal case.
+                        */
+                       inet_csk_reset_keepalive_timer(sk, tmo);
+               } else {
+                       tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
+                       goto discard;
+               }
+               break;
+       }
+
+       case TCP_CLOSING:
+               if (tp->snd_una == tp->write_seq) {
+                       tcp_time_wait(sk, TCP_TIME_WAIT, 0);
+                       goto discard;
+               }
+               break;
+
+       case TCP_LAST_ACK:
+               if (tp->snd_una == tp->write_seq) {
+                       tcp_update_metrics(sk);
+                       tcp_done(sk);
+                       goto discard;
+               }
+               break;
        }
 
        /* step 6: check the URG bit */
index 719652305a2950a3407804136bf7f42dc1d18e15..d20ede0c9593c2b918fd5224661aa92b9bae8c46 100644 (file)
@@ -1026,7 +1026,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
        key = sock_kmalloc(sk, sizeof(*key), gfp);
        if (!key)
                return -ENOMEM;
-       if (hlist_empty(&md5sig->head) && !tcp_alloc_md5sig_pool(sk)) {
+       if (!tcp_alloc_md5sig_pool()) {
                sock_kfree_s(sk, key, sizeof(*key));
                return -ENOMEM;
        }
@@ -1044,9 +1044,7 @@ EXPORT_SYMBOL(tcp_md5_do_add);
 
 int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_md5sig_key *key;
-       struct tcp_md5sig_info *md5sig;
 
        key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET);
        if (!key)
@@ -1054,10 +1052,6 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family)
        hlist_del_rcu(&key->node);
        atomic_sub(sizeof(*key), &sk->sk_omem_alloc);
        kfree_rcu(key, rcu);
-       md5sig = rcu_dereference_protected(tp->md5sig_info,
-                                          sock_owned_by_user(sk));
-       if (hlist_empty(&md5sig->head))
-               tcp_free_md5sig_pool();
        return 0;
 }
 EXPORT_SYMBOL(tcp_md5_do_del);
@@ -1071,8 +1065,6 @@ static void tcp_clear_md5_list(struct sock *sk)
 
        md5sig = rcu_dereference_protected(tp->md5sig_info, 1);
 
-       if (!hlist_empty(&md5sig->head))
-               tcp_free_md5sig_pool();
        hlist_for_each_entry_safe(key, n, &md5sig->head, node) {
                hlist_del_rcu(&key->node);
                atomic_sub(sizeof(*key), &sk->sk_omem_alloc);
index 0f01788272595397cdc8c440f89d595bb6bed0dc..ab1c08658528e7737fd1683841a4d11701cbc0bb 100644 (file)
@@ -317,7 +317,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
                        key = tp->af_specific->md5_lookup(sk, sk);
                        if (key != NULL) {
                                tcptw->tw_md5_key = kmemdup(key, sizeof(*key), GFP_ATOMIC);
-                               if (tcptw->tw_md5_key && tcp_alloc_md5sig_pool(sk) == NULL)
+                               if (tcptw->tw_md5_key && !tcp_alloc_md5sig_pool())
                                        BUG();
                        }
                } while (0);
@@ -358,10 +358,8 @@ void tcp_twsk_destructor(struct sock *sk)
 #ifdef CONFIG_TCP_MD5SIG
        struct tcp_timewait_sock *twsk = tcp_twsk(sk);
 
-       if (twsk->tw_md5_key) {
-               tcp_free_md5sig_pool();
+       if (twsk->tw_md5_key)
                kfree_rcu(twsk->tw_md5_key, rcu);
-       }
 #endif
 }
 EXPORT_SYMBOL_GPL(tcp_twsk_destructor);
index 0bf5d399a03c1c0eaedeedd4a6a9db4ee2af68e6..c7338ec79cc07d5cffe87da992c77c36d845a5d7 100644 (file)
@@ -1967,6 +1967,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
        unsigned int mask = datagram_poll(file, sock, wait);
        struct sock *sk = sock->sk;
 
+       sock_rps_record_flow(sk);
+
        /* Check for false positives due to checksum errors */
        if ((mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) &&
            !(sk->sk_shutdown & RCV_SHUTDOWN) && !first_packet_length(sk))
@@ -2381,7 +2383,7 @@ struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 
                if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
                                      SKB_GSO_UDP_TUNNEL |
-                                     SKB_GSO_GRE) ||
+                                     SKB_GSO_GRE | SKB_GSO_MPLS) ||
                             !(type & (SKB_GSO_UDP))))
                        goto out;
 
index 05a5df2febc9d34ed22bdc8749b4a064c4550c14..06347dbd32c1ebe0d013f858de4a56abb66f3305 100644 (file)
@@ -63,7 +63,7 @@ static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
 static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = {
        .handler        =       xfrm_tunnel_rcv,
        .err_handler    =       xfrm_tunnel_err,
-       .priority       =       2,
+       .priority       =       3,
 };
 
 #if IS_ENABLED(CONFIG_IPV6)
index 9af088d2cdaab1f4489f092f9a473d70b5c49667..470a9c008e9b9e921045bb5b11b77569e53ac5c9 100644 (file)
@@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o
 ipv6-objs :=   af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
                addrlabel.o \
                route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
-               raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
+               raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \
                exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o
 
 ipv6-offload :=        ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o
index 1bbf744c2cc35e7953b9580db08a357f4e829a04..21010fddb203cc768901625cf6c17e1cb0f7c654 100644 (file)
@@ -1126,8 +1126,7 @@ retry:
 
        ift = !max_addresses ||
              ipv6_count_addresses(idev) < max_addresses ?
-               ipv6_add_addr(idev, &addr, tmp_plen,
-                             ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK,
+               ipv6_add_addr(idev, &addr, tmp_plen, ipv6_addr_scope(&addr),
                              addr_flags) : NULL;
        if (IS_ERR_OR_NULL(ift)) {
                in6_ifa_put(ifp);
@@ -2402,6 +2401,7 @@ err_exit:
  *     Manual configuration of address on an interface
  */
 static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx,
+                         const struct in6_addr *peer_pfx,
                          unsigned int plen, __u8 ifa_flags, __u32 prefered_lft,
                          __u32 valid_lft)
 {
@@ -2457,6 +2457,8 @@ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *p
                ifp->valid_lft = valid_lft;
                ifp->prefered_lft = prefered_lft;
                ifp->tstamp = jiffies;
+               if (peer_pfx)
+                       ifp->peer_addr = *peer_pfx;
                spin_unlock_bh(&ifp->lock);
 
                addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
@@ -2526,7 +2528,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
                return -EFAULT;
 
        rtnl_lock();
-       err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr,
+       err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL,
                             ireq.ifr6_prefixlen, IFA_F_PERMANENT,
                             INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        rtnl_unlock();
@@ -2826,9 +2828,9 @@ static void addrconf_ip6_tnl_config(struct net_device *dev)
 }
 
 static int addrconf_notify(struct notifier_block *this, unsigned long event,
-                          void *data)
+                          void *ptr)
 {
-       struct net_device *dev = (struct net_device *) data;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct inet6_dev *idev = __in6_dev_get(dev);
        int run_pending = 0;
        int err;
@@ -3612,18 +3614,20 @@ restart:
        rcu_read_unlock_bh();
 }
 
-static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
+static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local,
+                                    struct in6_addr **peer_pfx)
 {
        struct in6_addr *pfx = NULL;
 
+       *peer_pfx = NULL;
+
        if (addr)
                pfx = nla_data(addr);
 
        if (local) {
                if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
-                       pfx = NULL;
-               else
-                       pfx = nla_data(local);
+                       *peer_pfx = pfx;
+               pfx = nla_data(local);
        }
 
        return pfx;
@@ -3641,7 +3645,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct net *net = sock_net(skb->sk);
        struct ifaddrmsg *ifm;
        struct nlattr *tb[IFA_MAX+1];
-       struct in6_addr *pfx;
+       struct in6_addr *pfx, *peer_pfx;
        int err;
 
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
@@ -3649,7 +3653,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
                return err;
 
        ifm = nlmsg_data(nlh);
-       pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
+       pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
        if (pfx == NULL)
                return -EINVAL;
 
@@ -3707,7 +3711,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct net *net = sock_net(skb->sk);
        struct ifaddrmsg *ifm;
        struct nlattr *tb[IFA_MAX+1];
-       struct in6_addr *pfx;
+       struct in6_addr *pfx, *peer_pfx;
        struct inet6_ifaddr *ifa;
        struct net_device *dev;
        u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
@@ -3719,7 +3723,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
                return err;
 
        ifm = nlmsg_data(nlh);
-       pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
+       pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
        if (pfx == NULL)
                return -EINVAL;
 
@@ -3747,7 +3751,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
                 * It would be best to check for !NLM_F_CREATE here but
                 * userspace alreay relies on not having to provide this.
                 */
-               return inet6_addr_add(net, ifm->ifa_index, pfx,
+               return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
                                      ifm->ifa_prefixlen, ifa_flags,
                                      preferred_lft, valid_lft);
        }
@@ -3804,6 +3808,7 @@ static inline int rt_scope(int ifa_scope)
 static inline int inet6_ifaddr_msgsize(void)
 {
        return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
+              + nla_total_size(16) /* IFA_LOCAL */
               + nla_total_size(16) /* IFA_ADDRESS */
               + nla_total_size(sizeof(struct ifa_cacheinfo));
 }
@@ -3842,13 +3847,22 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
                valid = INFINITY_LIFE_TIME;
        }
 
-       if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 ||
-           put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) {
-               nlmsg_cancel(skb, nlh);
-               return -EMSGSIZE;
-       }
+       if (!ipv6_addr_any(&ifa->peer_addr)) {
+               if (nla_put(skb, IFA_LOCAL, 16, &ifa->addr) < 0 ||
+                   nla_put(skb, IFA_ADDRESS, 16, &ifa->peer_addr) < 0)
+                       goto error;
+       } else
+               if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0)
+                       goto error;
+
+       if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
+               goto error;
 
        return nlmsg_end(skb, nlh);
+
+error:
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
@@ -4048,7 +4062,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh)
        struct net *net = sock_net(in_skb->sk);
        struct ifaddrmsg *ifm;
        struct nlattr *tb[IFA_MAX+1];
-       struct in6_addr *addr = NULL;
+       struct in6_addr *addr = NULL, *peer;
        struct net_device *dev = NULL;
        struct inet6_ifaddr *ifa;
        struct sk_buff *skb;
@@ -4058,7 +4072,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh)
        if (err < 0)
                goto errout;
 
-       addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
+       addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer);
        if (addr == NULL) {
                err = -EINVAL;
                goto errout;
@@ -4566,11 +4580,26 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
                        ip6_ins_rt(ifp->rt);
                if (ifp->idev->cnf.forwarding)
                        addrconf_join_anycast(ifp);
+               if (!ipv6_addr_any(&ifp->peer_addr))
+                       addrconf_prefix_route(&ifp->peer_addr, 128,
+                                             ifp->idev->dev, 0, 0);
                break;
        case RTM_DELADDR:
                if (ifp->idev->cnf.forwarding)
                        addrconf_leave_anycast(ifp);
                addrconf_leave_solict(ifp->idev, &ifp->addr);
+               if (!ipv6_addr_any(&ifp->peer_addr)) {
+                       struct rt6_info *rt;
+                       struct net_device *dev = ifp->idev->dev;
+
+                       rt = rt6_lookup(dev_net(dev), &ifp->peer_addr, NULL,
+                                       dev->ifindex, 1);
+                       if (rt) {
+                               dst_hold(&rt->dst);
+                               if (ip6_del_rt(rt))
+                                       dst_free(&rt->dst);
+                       }
+               }
                dst_hold(&ifp->rt->dst);
 
                if (ip6_del_rt(ifp->rt))
@@ -4618,13 +4647,16 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write,
 
 static void dev_disable_change(struct inet6_dev *idev)
 {
+       struct netdev_notifier_info info;
+
        if (!idev || !idev->dev)
                return;
 
+       netdev_notifier_info_init(&info, idev->dev);
        if (idev->cnf.disable_ipv6)
-               addrconf_notify(NULL, NETDEV_DOWN, idev->dev);
+               addrconf_notify(NULL, NETDEV_DOWN, &info);
        else
-               addrconf_notify(NULL, NETDEV_UP, idev->dev);
+               addrconf_notify(NULL, NETDEV_UP, &info);
 }
 
 static void addrconf_disable_change(struct net *net, __s32 newf)
index ab5c7ad482cded367c1180a3a3761615bc2a4d54..a5ac969aeefe5337d7fa4c5601912fb96b1a5496 100644 (file)
@@ -49,6 +49,7 @@
 #include <net/udp.h>
 #include <net/udplite.h>
 #include <net/tcp.h>
+#include <net/ping.h>
 #include <net/protocol.h>
 #include <net/inet_common.h>
 #include <net/route.h>
@@ -840,6 +841,9 @@ static int __init inet6_init(void)
        if (err)
                goto out_unregister_udplite_proto;
 
+       err = proto_register(&pingv6_prot, 1);
+       if (err)
+               goto out_unregister_ping_proto;
 
        /* We MUST register RAW sockets before we create the ICMP6,
         * IGMP6, or NDISC control sockets.
@@ -930,6 +934,10 @@ static int __init inet6_init(void)
        if (err)
                goto ipv6_packet_fail;
 
+       err = pingv6_init();
+       if (err)
+               goto pingv6_fail;
+
 #ifdef CONFIG_SYSCTL
        err = ipv6_sysctl_register();
        if (err)
@@ -942,6 +950,8 @@ out:
 sysctl_fail:
        ipv6_packet_cleanup();
 #endif
+pingv6_fail:
+       pingv6_exit();
 ipv6_packet_fail:
        tcpv6_exit();
 tcpv6_fail:
@@ -985,6 +995,8 @@ register_pernet_fail:
        rtnl_unregister_all(PF_INET6);
 out_sock_register_fail:
        rawv6_exit();
+out_unregister_ping_proto:
+       proto_unregister(&pingv6_prot);
 out_unregister_raw_proto:
        proto_unregister(&rawv6_prot);
 out_unregister_udplite_proto:
index 4b56cbbc789062d89c5a708386a03e5a8ded8bc6..197e6f4a2b7499c67440b66e04d646d631caefa5 100644 (file)
@@ -879,3 +879,30 @@ exit_f:
        return err;
 }
 EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl);
+
+void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
+                            __u16 srcp, __u16 destp, int bucket)
+{
+       struct ipv6_pinfo *np = inet6_sk(sp);
+       const struct in6_addr *dest, *src;
+
+       dest  = &np->daddr;
+       src   = &np->rcv_saddr;
+       seq_printf(seq,
+                  "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+                  "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n",
+                  bucket,
+                  src->s6_addr32[0], src->s6_addr32[1],
+                  src->s6_addr32[2], src->s6_addr32[3], srcp,
+                  dest->s6_addr32[0], dest->s6_addr32[1],
+                  dest->s6_addr32[2], dest->s6_addr32[3], destp,
+                  sp->sk_state,
+                  sk_wmem_alloc_get(sp),
+                  sk_rmem_alloc_get(sp),
+                  0, 0L, 0,
+                  from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
+                  0,
+                  sock_i_ino(sp),
+                  atomic_read(&sp->sk_refcnt), sp,
+                  atomic_read(&sp->sk_drops));
+}
index c5e83fae4df423ccbe02bed8bf31ffd415014ad2..140748debc4ade194e5e179636e94264da7e65a1 100644 (file)
@@ -115,7 +115,7 @@ EXPORT_SYMBOL(ipv6_skip_exthdr);
 int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
 {
        const unsigned char *nh = skb_network_header(skb);
-       int packet_len = skb->tail - skb->network_header;
+       int packet_len = skb_tail_pointer(skb) - skb_network_header(skb);
        struct ipv6_opt_hdr *hdr;
        int len;
 
index b4ff0a42b8c70248faf1b7298c1bec2cc79368ee..4b4890bbe16d9ccd9b694acd5771d16914a4ab66 100644 (file)
@@ -57,6 +57,7 @@
 
 #include <net/ipv6.h>
 #include <net/ip6_checksum.h>
+#include <net/ping.h>
 #include <net/protocol.h>
 #include <net/raw.h>
 #include <net/rawv6.h>
@@ -84,12 +85,18 @@ static inline struct sock *icmpv6_sk(struct net *net)
 static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                       u8 type, u8 code, int offset, __be32 info)
 {
+       /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */
+       struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset);
        struct net *net = dev_net(skb->dev);
 
        if (type == ICMPV6_PKT_TOOBIG)
                ip6_update_pmtu(skb, net, info, 0, 0);
        else if (type == NDISC_REDIRECT)
                ip6_redirect(skb, net, 0, 0);
+
+       if (!(type & ICMPV6_INFOMSG_MASK))
+               if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
+                       ping_err(skb, offset, info);
 }
 
 static int icmpv6_rcv(struct sk_buff *skb);
@@ -224,7 +231,8 @@ static bool opt_unrec(struct sk_buff *skb, __u32 offset)
        return (*op & 0xC0) == 0x80;
 }
 
-static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len)
+int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
+                              struct icmp6hdr *thdr, int len)
 {
        struct sk_buff *skb;
        struct icmp6hdr *icmp6h;
@@ -307,8 +315,8 @@ static void mip6_addr_swap(struct sk_buff *skb)
 static inline void mip6_addr_swap(struct sk_buff *skb) {}
 #endif
 
-static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
-                                            struct sock *sk, struct flowi6 *fl6)
+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;
@@ -391,7 +399,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
        int err = 0;
 
        if ((u8 *)hdr < skb->head ||
-           (skb->network_header + sizeof(*hdr)) > skb->tail)
+           (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb))
                return;
 
        /*
@@ -697,7 +705,8 @@ static int icmpv6_rcv(struct sk_buff *skb)
                skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len,
                                             IPPROTO_ICMPV6, 0));
                if (__skb_checksum_complete(skb)) {
-                       LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n",
+                       LIMIT_NETDEBUG(KERN_DEBUG
+                                      "ICMPv6 checksum failed [%pI6c > %pI6c]\n",
                                       saddr, daddr);
                        goto csum_error;
                }
@@ -718,7 +727,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
                break;
 
        case ICMPV6_ECHO_REPLY:
-               /* we couldn't care less */
+               ping_rcv(skb);
                break;
 
        case ICMPV6_PKT_TOOBIG:
index 71b766ee821d64fd10e99482b962ca6cea07cdad..a263b990ee11d7bf504512c4c722e927d1e8ed66 100644 (file)
@@ -98,6 +98,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
                       SKB_GSO_TCP_ECN |
                       SKB_GSO_GRE |
                       SKB_GSO_UDP_TUNNEL |
+                      SKB_GSO_MPLS |
                       SKB_GSO_TCPV6 |
                       0)))
                goto out;
index 241fb8ad9fcf28e2982f32e23ff9b7403ceef24a..583e8d435f9a2c47437d3897b7167ac4a4025a40 100644 (file)
@@ -1319,7 +1319,7 @@ static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc,
 static int ip6mr_device_event(struct notifier_block *this,
                              unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
        struct mr6_table *mrt;
        struct mif_device *v;
index bfa6cc36ef2ab33e6e2894e03bb07c50f56a5804..72c8bfe06bb4afa547db787756d974998f93d86f 100644 (file)
@@ -1409,8 +1409,9 @@ static void mld_sendpack(struct sk_buff *skb)
        idev = __in6_dev_get(skb->dev);
        IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 
-       payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
-       mldlen = skb->tail - skb->transport_header;
+       payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) -
+               sizeof(*pip6);
+       mldlen = skb_tail_pointer(skb) - skb_transport_header(skb);
        pip6->payload_len = htons(payload_len);
 
        pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
index 0f9bdc5ee9f38c70f1c4c265e8ebe43467d6b59a..9ac01dc9402e9337d4b27952127d229acbb6e062 100644 (file)
@@ -268,7 +268,8 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
        struct ipv6_opt_hdr *exthdr =
                                   (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
        const unsigned char *nh = skb_network_header(skb);
-       unsigned int packet_len = skb->tail - skb->network_header;
+       unsigned int packet_len = skb_tail_pointer(skb) -
+               skb_network_header(skb);
        int found_rhdr = 0;
 
        *nexthdr = &ipv6_hdr(skb)->nexthdr;
@@ -404,7 +405,8 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
        struct ipv6_opt_hdr *exthdr =
                                   (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
        const unsigned char *nh = skb_network_header(skb);
-       unsigned int packet_len = skb->tail - skb->network_header;
+       unsigned int packet_len = skb_tail_pointer(skb) -
+               skb_network_header(skb);
        int found_rhdr = 0;
 
        *nexthdr = &ipv6_hdr(skb)->nexthdr;
index 2712ab22a174087c09cc705e1f6adec2bd601154..781dd3c99680704d382ce093b2c5e32b86d95d89 100644 (file)
@@ -693,7 +693,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
        const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
        const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
        u8 *lladdr = NULL;
-       u32 ndoptlen = skb->tail - (skb->transport_header +
+       u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
                                    offsetof(struct nd_msg, opt));
        struct ndisc_options ndopts;
        struct net_device *dev = skb->dev;
@@ -853,7 +853,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
        const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
        const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
        u8 *lladdr = NULL;
-       u32 ndoptlen = skb->tail - (skb->transport_header +
+       u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
                                    offsetof(struct nd_msg, opt));
        struct ndisc_options ndopts;
        struct net_device *dev = skb->dev;
@@ -1069,7 +1069,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
 
        __u8 * opt = (__u8 *)(ra_msg + 1);
 
-       optlen = (skb->tail - skb->transport_header) - sizeof(struct ra_msg);
+       optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) -
+               sizeof(struct ra_msg);
 
        if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
                ND_PRINTK(2, warn, "RA: source address is not link-local\n");
@@ -1346,7 +1347,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
        u8 *hdr;
        struct ndisc_options ndopts;
        struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb);
-       u32 ndoptlen = skb->tail - (skb->transport_header +
+       u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
                                    offsetof(struct rd_msg, opt));
 
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
@@ -1568,7 +1569,7 @@ int ndisc_rcv(struct sk_buff *skb)
 
 static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
        struct inet6_dev *idev;
 
index 60e9053bab051abb1e69aadabcf36f39292d8e03..47bff610751922ebd80b21eb59387a334af9b3fb 100644 (file)
@@ -71,7 +71,7 @@ static int device_cmp(struct nf_conn *ct, void *ifindex)
 static int masq_device_event(struct notifier_block *this,
                             unsigned long event, void *ptr)
 {
-       const struct net_device *dev = ptr;
+       const struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
 
        if (event == NETDEV_DOWN)
@@ -89,8 +89,10 @@ static int masq_inet_event(struct notifier_block *this,
                           unsigned long event, void *ptr)
 {
        struct inet6_ifaddr *ifa = ptr;
+       struct netdev_notifier_info info;
 
-       return masq_device_event(this, event, ifa->idev->dev);
+       netdev_notifier_info_init(&info, ifa->idev->dev);
+       return masq_device_event(this, event, &info);
 }
 
 static struct notifier_block masq_inet_notifier = {
index c2e73e647e440745acd32dcaa1564031f4323e38..ab92a3673fbbddd9f3d32b69730c3b1b61fbcbde 100644 (file)
@@ -40,7 +40,8 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
        u16 offset = sizeof(struct ipv6hdr);
        struct ipv6_opt_hdr *exthdr =
                                (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
-       unsigned int packet_len = skb->tail - skb->network_header;
+       unsigned int packet_len = skb_tail_pointer(skb) -
+               skb_network_header(skb);
        int found_rhdr = 0;
        *nexthdr = &ipv6_hdr(skb)->nexthdr;
 
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
new file mode 100644 (file)
index 0000000..a431103
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             "Ping" sockets
+ *
+ *             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.
+ *
+ * Based on ipv4/ping.c code.
+ *
+ * Authors:    Lorenzo Colitti (IPv6 support)
+ *             Vasiliy Kulikov / Openwall (IPv4 implementation, for Linux 2.6),
+ *             Pavel Kankovsky (IPv4 implementation, for Linux 2.4.32)
+ *
+ */
+
+#include <net/addrconf.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/protocol.h>
+#include <net/udp.h>
+#include <net/transp_v6.h>
+#include <net/ping.h>
+
+struct proto pingv6_prot = {
+       .name =         "PINGv6",
+       .owner =        THIS_MODULE,
+       .init =         ping_init_sock,
+       .close =        ping_close,
+       .connect =      ip6_datagram_connect,
+       .disconnect =   udp_disconnect,
+       .setsockopt =   ipv6_setsockopt,
+       .getsockopt =   ipv6_getsockopt,
+       .sendmsg =      ping_v6_sendmsg,
+       .recvmsg =      ping_recvmsg,
+       .bind =         ping_bind,
+       .backlog_rcv =  ping_queue_rcv_skb,
+       .hash =         ping_hash,
+       .unhash =       ping_unhash,
+       .get_port =     ping_get_port,
+       .obj_size =     sizeof(struct raw6_sock),
+};
+EXPORT_SYMBOL_GPL(pingv6_prot);
+
+static struct inet_protosw pingv6_protosw = {
+       .type =      SOCK_DGRAM,
+       .protocol =  IPPROTO_ICMPV6,
+       .prot =      &pingv6_prot,
+       .ops =       &inet6_dgram_ops,
+       .no_check =  UDP_CSUM_DEFAULT,
+       .flags =     INET_PROTOSW_REUSE,
+};
+
+
+/* Compatibility glue so we can support IPv6 when it's compiled as a module */
+int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+{
+       return -EAFNOSUPPORT;
+}
+int dummy_ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
+                                struct sk_buff *skb)
+{
+       return -EAFNOSUPPORT;
+}
+int dummy_icmpv6_err_convert(u8 type, u8 code, int *err)
+{
+       return -EAFNOSUPPORT;
+}
+void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
+                           __be16 port, u32 info, u8 *payload) {}
+int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
+                       const struct net_device *dev, int strict)
+{
+       return 0;
+}
+
+int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+                   size_t len)
+{
+       struct inet_sock *inet = inet_sk(sk);
+       struct ipv6_pinfo *np = inet6_sk(sk);
+       struct icmp6hdr user_icmph;
+       int addr_type;
+       struct in6_addr *daddr;
+       int iif = 0;
+       struct flowi6 fl6;
+       int err;
+       int hlimit;
+       struct dst_entry *dst;
+       struct rt6_info *rt;
+       struct pingfakehdr pfh;
+
+       pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num);
+
+       err = ping_common_sendmsg(AF_INET6, msg, len, &user_icmph,
+                                 sizeof(user_icmph));
+       if (err)
+               return err;
+
+       if (msg->msg_name) {
+               struct sockaddr_in6 *u = (struct sockaddr_in6 *) msg->msg_name;
+               if (msg->msg_namelen < sizeof(struct sockaddr_in6) ||
+                   u->sin6_family != AF_INET6) {
+                       return -EINVAL;
+               }
+               if (sk->sk_bound_dev_if &&
+                   sk->sk_bound_dev_if != u->sin6_scope_id) {
+                       return -EINVAL;
+               }
+               daddr = &(u->sin6_addr);
+               iif = u->sin6_scope_id;
+       } else {
+               if (sk->sk_state != TCP_ESTABLISHED)
+                       return -EDESTADDRREQ;
+               daddr = &np->daddr;
+       }
+
+       if (!iif)
+               iif = sk->sk_bound_dev_if;
+
+       addr_type = ipv6_addr_type(daddr);
+       if (__ipv6_addr_needs_scope_id(addr_type) && !iif)
+               return -EINVAL;
+       if (addr_type & IPV6_ADDR_MAPPED)
+               return -EINVAL;
+
+       /* TODO: use ip6_datagram_send_ctl to get options from cmsg */
+
+       memset(&fl6, 0, sizeof(fl6));
+
+       fl6.flowi6_proto = IPPROTO_ICMPV6;
+       fl6.saddr = np->saddr;
+       fl6.daddr = *daddr;
+       fl6.fl6_icmp_type = user_icmph.icmp6_type;
+       fl6.fl6_icmp_code = user_icmph.icmp6_code;
+       security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
+
+       if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
+               fl6.flowi6_oif = np->mcast_oif;
+       else if (!fl6.flowi6_oif)
+               fl6.flowi6_oif = np->ucast_oif;
+
+       dst = ip6_sk_dst_lookup_flow(sk, &fl6,  daddr, 1);
+       if (IS_ERR(dst))
+               return PTR_ERR(dst);
+       rt = (struct rt6_info *) dst;
+
+       np = inet6_sk(sk);
+       if (!np)
+               return -EBADF;
+
+       if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
+               fl6.flowi6_oif = np->mcast_oif;
+       else if (!fl6.flowi6_oif)
+               fl6.flowi6_oif = np->ucast_oif;
+
+       pfh.icmph.type = user_icmph.icmp6_type;
+       pfh.icmph.code = user_icmph.icmp6_code;
+       pfh.icmph.checksum = 0;
+       pfh.icmph.un.echo.id = inet->inet_sport;
+       pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence;
+       pfh.iov = msg->msg_iov;
+       pfh.wcheck = 0;
+       pfh.family = AF_INET6;
+
+       if (ipv6_addr_is_multicast(&fl6.daddr))
+               hlimit = np->mcast_hops;
+       else
+               hlimit = np->hop_limit;
+       if (hlimit < 0)
+               hlimit = ip6_dst_hoplimit(dst);
+
+       err = ip6_append_data(sk, ping_getfrag, &pfh, len,
+                             0, hlimit,
+                             np->tclass, NULL, &fl6, rt,
+                             MSG_DONTWAIT, np->dontfrag);
+
+       if (err) {
+               ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev,
+                                  ICMP6_MIB_OUTERRORS);
+               ip6_flush_pending_frames(sk);
+       } else {
+               err = icmpv6_push_pending_frames(sk, &fl6,
+                                                (struct icmp6hdr *) &pfh.icmph,
+                                                len);
+       }
+
+       return err;
+}
+
+#ifdef CONFIG_PROC_FS
+static void *ping_v6_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       return ping_seq_start(seq, pos, AF_INET6);
+}
+
+int ping_v6_seq_show(struct seq_file *seq, void *v)
+{
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(seq, IPV6_SEQ_DGRAM_HEADER);
+       } else {
+               int bucket = ((struct ping_iter_state *) seq->private)->bucket;
+               struct inet_sock *inet = inet_sk(v);
+               __u16 srcp = ntohs(inet->inet_sport);
+               __u16 destp = ntohs(inet->inet_dport);
+               ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket);
+       }
+       return 0;
+}
+
+static struct ping_seq_afinfo ping_v6_seq_afinfo = {
+       .name           = "icmp6",
+       .family         = AF_INET6,
+       .seq_fops       = &ping_seq_fops,
+       .seq_ops        = {
+               .start          = ping_v6_seq_start,
+               .show           = ping_v6_seq_show,
+               .next           = ping_seq_next,
+               .stop           = ping_seq_stop,
+       },
+};
+
+static int __net_init ping_v6_proc_init_net(struct net *net)
+{
+       return ping_proc_register(net, &ping_v6_seq_afinfo);
+}
+
+static void __net_init ping_v6_proc_exit_net(struct net *net)
+{
+       return ping_proc_unregister(net, &ping_v6_seq_afinfo);
+}
+
+static struct pernet_operations ping_v6_net_ops = {
+       .init = ping_v6_proc_init_net,
+       .exit = ping_v6_proc_exit_net,
+};
+#endif
+
+int __init pingv6_init(void)
+{
+#ifdef CONFIG_PROC_FS
+       int ret = register_pernet_subsys(&ping_v6_net_ops);
+       if (ret)
+               return ret;
+#endif
+       pingv6_ops.ipv6_recv_error = ipv6_recv_error;
+       pingv6_ops.ip6_datagram_recv_ctl = ip6_datagram_recv_ctl;
+       pingv6_ops.icmpv6_err_convert = icmpv6_err_convert;
+       pingv6_ops.ipv6_icmp_error = ipv6_icmp_error;
+       pingv6_ops.ipv6_chk_addr = ipv6_chk_addr;
+       return inet6_register_protosw(&pingv6_protosw);
+}
+
+/* This never gets called because it's not possible to unload the ipv6 module,
+ * but just in case.
+ */
+void pingv6_exit(void)
+{
+       pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error;
+       pingv6_ops.ip6_datagram_recv_ctl = dummy_ip6_datagram_recv_ctl;
+       pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert;
+       pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error;
+       pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr;
+#ifdef CONFIG_PROC_FS
+       unregister_pernet_subsys(&ping_v6_net_ops);
+#endif
+       inet6_unregister_protosw(&pingv6_protosw);
+}
index eedff8ccded507cc977bd073dbbf334b2624033b..c45f7a5c36e96f98487ca194c5f08e5d0f931852 100644 (file)
@@ -1132,7 +1132,8 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
                spin_lock_bh(&sk->sk_receive_queue.lock);
                skb = skb_peek(&sk->sk_receive_queue);
                if (skb != NULL)
-                       amount = skb->tail - skb->transport_header;
+                       amount = skb_tail_pointer(skb) -
+                               skb_transport_header(skb);
                spin_unlock_bh(&sk->sk_receive_queue.lock);
                return put_user(amount, (int __user *)arg);
        }
@@ -1226,45 +1227,16 @@ struct proto rawv6_prot = {
 };
 
 #ifdef CONFIG_PROC_FS
-static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
-{
-       struct ipv6_pinfo *np = inet6_sk(sp);
-       const struct in6_addr *dest, *src;
-       __u16 destp, srcp;
-
-       dest  = &np->daddr;
-       src   = &np->rcv_saddr;
-       destp = 0;
-       srcp  = inet_sk(sp)->inet_num;
-       seq_printf(seq,
-                  "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-                  "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n",
-                  i,
-                  src->s6_addr32[0], src->s6_addr32[1],
-                  src->s6_addr32[2], src->s6_addr32[3], srcp,
-                  dest->s6_addr32[0], dest->s6_addr32[1],
-                  dest->s6_addr32[2], dest->s6_addr32[3], destp,
-                  sp->sk_state,
-                  sk_wmem_alloc_get(sp),
-                  sk_rmem_alloc_get(sp),
-                  0, 0L, 0,
-                  from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
-                  0,
-                  sock_i_ino(sp),
-                  atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
-}
-
 static int raw6_seq_show(struct seq_file *seq, void *v)
 {
-       if (v == SEQ_START_TOKEN)
-               seq_printf(seq,
-                          "  sl  "
-                          "local_address                         "
-                          "remote_address                        "
-                          "st tx_queue rx_queue tr tm->when retrnsmt"
-                          "   uid  timeout inode ref pointer drops\n");
-       else
-               raw6_sock_seq_show(seq, v, raw_seq_private(seq)->bucket);
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(seq, IPV6_SEQ_DGRAM_HEADER);
+       } else {
+               struct sock *sp = v;
+               __u16 srcp  = inet_sk(sp)->inet_num;
+               ip6_dgram_sock_seq_show(seq, v, srcp, 0,
+                                       raw_seq_private(seq)->bucket);
+       }
        return 0;
 }
 
index ad0aa6b0b86ae02f80b6b2184588605a3d5d7a6c..2b874185ebb2bb114a2a567fd99790a2bf7aff0e 100644 (file)
@@ -1649,7 +1649,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
        int optlen, on_link;
        u8 *lladdr;
 
-       optlen = skb->tail - skb->transport_header;
+       optlen = skb_tail_pointer(skb) - skb_transport_header(skb);
        optlen -= sizeof(*msg);
 
        if (optlen < 0) {
@@ -2681,9 +2681,9 @@ errout:
 }
 
 static int ip6_route_dev_notify(struct notifier_block *this,
-                               unsigned long event, void *data)
+                               unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *)data;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
 
        if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
index 335363478bbfa037e5a4ddc8c3020cc4eeae0a15..6b9c1f128eafdfd121e387c350fdc8ae25179e4f 100644 (file)
@@ -577,6 +577,10 @@ static int ipip6_rcv(struct sk_buff *skb)
        if (tunnel != NULL) {
                struct pcpu_tstats *tstats;
 
+               if (tunnel->parms.iph.protocol != IPPROTO_IPV6 &&
+                   tunnel->parms.iph.protocol != 0)
+                       goto out;
+
                secpath_reset(skb);
                skb->mac_header = skb->network_header;
                skb_reset_network_header(skb);
@@ -629,6 +633,35 @@ out:
        return 0;
 }
 
+static const struct tnl_ptk_info tpi = {
+       /* no tunnel info required for ipip. */
+       .proto = htons(ETH_P_IP),
+};
+
+static int ipip_rcv(struct sk_buff *skb)
+{
+       const struct iphdr *iph = ip_hdr(skb);
+       struct ip_tunnel *tunnel;
+
+       tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
+                                    iph->saddr, iph->daddr);
+       if (tunnel != NULL) {
+               if (tunnel->parms.iph.protocol != IPPROTO_IPIP &&
+                   tunnel->parms.iph.protocol != 0)
+                       goto drop;
+
+               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+                       goto drop;
+               return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
+       }
+
+       return 1;
+
+drop:
+       kfree_skb(skb);
+       return 0;
+}
+
 /*
  * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function
  * stores the embedded IPv4 address in v4dst and returns true.
@@ -877,6 +910,43 @@ tx_error:
        return NETDEV_TX_OK;
 }
 
+static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct ip_tunnel *tunnel = netdev_priv(dev);
+       const struct iphdr  *tiph = &tunnel->parms.iph;
+
+       if (likely(!skb->encapsulation)) {
+               skb_reset_inner_headers(skb);
+               skb->encapsulation = 1;
+       }
+
+       ip_tunnel_xmit(skb, dev, tiph, IPPROTO_IPIP);
+       return NETDEV_TX_OK;
+}
+
+static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
+                                  struct net_device *dev)
+{
+       switch (skb->protocol) {
+       case htons(ETH_P_IP):
+               ipip_tunnel_xmit(skb, dev);
+               break;
+       case htons(ETH_P_IPV6):
+               ipip6_tunnel_xmit(skb, dev);
+               break;
+       default:
+               goto tx_err;
+       }
+
+       return NETDEV_TX_OK;
+
+tx_err:
+       dev->stats.tx_errors++;
+       dev_kfree_skb(skb);
+       return NETDEV_TX_OK;
+
+}
+
 static void ipip6_tunnel_bind_dev(struct net_device *dev)
 {
        struct net_device *tdev = NULL;
@@ -1027,7 +1097,11 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
                        goto done;
 
                err = -EINVAL;
-               if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPV6 ||
+               if (p.iph.protocol != IPPROTO_IPV6 &&
+                   p.iph.protocol != IPPROTO_IPIP &&
+                   p.iph.protocol != 0)
+                       goto done;
+               if (p.iph.version != 4 ||
                    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
                        goto done;
                if (p.iph.ttl)
@@ -1164,7 +1238,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 
 static const struct net_device_ops ipip6_netdev_ops = {
        .ndo_uninit     = ipip6_tunnel_uninit,
-       .ndo_start_xmit = ipip6_tunnel_xmit,
+       .ndo_start_xmit = sit_tunnel_xmit,
        .ndo_do_ioctl   = ipip6_tunnel_ioctl,
        .ndo_change_mtu = ipip6_tunnel_change_mtu,
        .ndo_get_stats64 = ip_tunnel_get_stats64,
@@ -1232,6 +1306,22 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
        return 0;
 }
 
+static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+       u8 proto;
+
+       if (!data)
+               return 0;
+
+       proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+       if (proto != IPPROTO_IPV6 &&
+           proto != IPPROTO_IPIP &&
+           proto != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
 static void ipip6_netlink_parms(struct nlattr *data[],
                                struct ip_tunnel_parm *parms)
 {
@@ -1268,6 +1358,10 @@ static void ipip6_netlink_parms(struct nlattr *data[],
 
        if (data[IFLA_IPTUN_FLAGS])
                parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]);
+
+       if (data[IFLA_IPTUN_PROTO])
+               parms->iph.protocol = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+
 }
 
 #ifdef CONFIG_IPV6_SIT_6RD
@@ -1391,6 +1485,8 @@ static size_t ipip6_get_size(const struct net_device *dev)
                nla_total_size(1) +
                /* IFLA_IPTUN_FLAGS */
                nla_total_size(2) +
+               /* IFLA_IPTUN_PROTO */
+               nla_total_size(1) +
 #ifdef CONFIG_IPV6_SIT_6RD
                /* IFLA_IPTUN_6RD_PREFIX */
                nla_total_size(sizeof(struct in6_addr)) +
@@ -1416,6 +1512,7 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
            nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
            nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
                       !!(parm->iph.frag_off & htons(IP_DF))) ||
+           nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) ||
            nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags))
                goto nla_put_failure;
 
@@ -1445,6 +1542,7 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
        [IFLA_IPTUN_TOS]                = { .type = NLA_U8 },
        [IFLA_IPTUN_PMTUDISC]           = { .type = NLA_U8 },
        [IFLA_IPTUN_FLAGS]              = { .type = NLA_U16 },
+       [IFLA_IPTUN_PROTO]              = { .type = NLA_U8 },
 #ifdef CONFIG_IPV6_SIT_6RD
        [IFLA_IPTUN_6RD_PREFIX]         = { .len = sizeof(struct in6_addr) },
        [IFLA_IPTUN_6RD_RELAY_PREFIX]   = { .type = NLA_U32 },
@@ -1459,6 +1557,7 @@ static struct rtnl_link_ops sit_link_ops __read_mostly = {
        .policy         = ipip6_policy,
        .priv_size      = sizeof(struct ip_tunnel),
        .setup          = ipip6_tunnel_setup,
+       .validate       = ipip6_validate,
        .newlink        = ipip6_newlink,
        .changelink     = ipip6_changelink,
        .get_size       = ipip6_get_size,
@@ -1471,6 +1570,12 @@ static struct xfrm_tunnel sit_handler __read_mostly = {
        .priority       =       1,
 };
 
+static struct xfrm_tunnel ipip_handler __read_mostly = {
+       .handler        =       ipip_rcv,
+       .err_handler    =       ipip6_err,
+       .priority       =       2,
+};
+
 static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head)
 {
        int prio;
@@ -1553,6 +1658,7 @@ static void __exit sit_cleanup(void)
 {
        rtnl_link_unregister(&sit_link_ops);
        xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+       xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
 
        unregister_pernet_device(&sit_net_ops);
        rcu_barrier(); /* Wait for completion of call_rcu()'s */
@@ -1569,9 +1675,14 @@ static int __init sit_init(void)
                return err;
        err = xfrm4_tunnel_register(&sit_handler, AF_INET6);
        if (err < 0) {
-               pr_info("%s: can't add protocol\n", __func__);
+               pr_info("%s: can't register ip6ip4\n", __func__);
                goto xfrm_tunnel_failed;
        }
+       err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
+       if (err < 0) {
+               pr_info("%s: can't register ip4ip4\n", __func__);
+               goto xfrm_tunnel4_failed;
+       }
        err = rtnl_link_register(&sit_link_ops);
        if (err < 0)
                goto rtnl_link_failed;
@@ -1580,6 +1691,8 @@ out:
        return err;
 
 rtnl_link_failed:
+       xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+xfrm_tunnel4_failed:
        xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
 xfrm_tunnel_failed:
        unregister_pernet_device(&sit_net_ops);
index 42923b14dfa618ce83ba969c126611fe2ad4a828..b5808539cd5c50fd2d2cff7d99ee8acd0cde94e5 100644 (file)
@@ -1359,48 +1359,17 @@ static const struct inet6_protocol udpv6_protocol = {
 
 /* ------------------------------------------------------------------------ */
 #ifdef CONFIG_PROC_FS
-
-static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket)
-{
-       struct inet_sock *inet = inet_sk(sp);
-       struct ipv6_pinfo *np = inet6_sk(sp);
-       const struct in6_addr *dest, *src;
-       __u16 destp, srcp;
-
-       dest  = &np->daddr;
-       src   = &np->rcv_saddr;
-       destp = ntohs(inet->inet_dport);
-       srcp  = ntohs(inet->inet_sport);
-       seq_printf(seq,
-                  "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-                  "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n",
-                  bucket,
-                  src->s6_addr32[0], src->s6_addr32[1],
-                  src->s6_addr32[2], src->s6_addr32[3], srcp,
-                  dest->s6_addr32[0], dest->s6_addr32[1],
-                  dest->s6_addr32[2], dest->s6_addr32[3], destp,
-                  sp->sk_state,
-                  sk_wmem_alloc_get(sp),
-                  sk_rmem_alloc_get(sp),
-                  0, 0L, 0,
-                  from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
-                  0,
-                  sock_i_ino(sp),
-                  atomic_read(&sp->sk_refcnt), sp,
-                  atomic_read(&sp->sk_drops));
-}
-
 int udp6_seq_show(struct seq_file *seq, void *v)
 {
-       if (v == SEQ_START_TOKEN)
-               seq_printf(seq,
-                          "  sl  "
-                          "local_address                         "
-                          "remote_address                        "
-                          "st tx_queue rx_queue tr tm->when retrnsmt"
-                          "   uid  timeout inode ref pointer drops\n");
-       else
-               udp6_sock_seq_show(seq, v, ((struct udp_iter_state *)seq->private)->bucket);
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(seq, IPV6_SEQ_DGRAM_HEADER);
+       } else {
+               int bucket = ((struct udp_iter_state *)seq->private)->bucket;
+               struct inet_sock *inet = inet_sk(v);
+               __u16 srcp = ntohs(inet->inet_sport);
+               __u16 destp = ntohs(inet->inet_dport);
+               ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket);
+       }
        return 0;
 }
 
index d3cfaf9c7a0858d8bb1e9fd60c412c3b03cbf3e3..5d1b8d7ac9931c7d0cbe35c06318d08659a5af7b 100644 (file)
@@ -64,7 +64,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
                if (unlikely(type & ~(SKB_GSO_UDP |
                                      SKB_GSO_DODGY |
                                      SKB_GSO_UDP_TUNNEL |
-                                     SKB_GSO_GRE) ||
+                                     SKB_GSO_GRE |
+                                     SKB_GSO_MPLS) ||
                             !(type & (SKB_GSO_UDP))))
                        goto out;
 
index f547a47d381ca0596244bfbf692ef8134b508ccc..7a1e0fc1bd4dd2ca8f31d8a376d94a30406cb1e1 100644 (file)
@@ -330,7 +330,7 @@ static __inline__ void __ipxitf_put(struct ipx_interface *intrfc)
 static int ipxitf_device_event(struct notifier_block *notifier,
                                unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct ipx_interface *i, *tmp;
 
        if (!net_eq(dev_net(dev), &init_net))
index ae691651b72141d649a4cca1aaaedc8920db5192..168aff5e60de528194a1f4b8ea836cf394ea6613 100644 (file)
@@ -2293,7 +2293,7 @@ out_unlock:
 static int afiucv_netdev_event(struct notifier_block *this,
                               unsigned long event, void *ptr)
 {
-       struct net_device *event_dev = (struct net_device *)ptr;
+       struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
        struct sock *sk;
        struct iucv_sock *iucv;
 
index 98d20c0f6fed8829c1881e16b274c2bf97c589c4..7c3ba8628d4e6aefe6ce98747dada70bbc04ab55 100644 (file)
@@ -1747,10 +1747,9 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
 }
 
 static int netdev_notify(struct notifier_block *nb,
-                        unsigned long state,
-                        void *ndev)
+                        unsigned long state, void *ptr)
 {
-       struct net_device *dev = ndev;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct ieee80211_sub_if_data *sdata;
 
        if (state != NETDEV_CHANGENAME)
diff --git a/net/mpls/Kconfig b/net/mpls/Kconfig
new file mode 100644 (file)
index 0000000..37421db
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# MPLS configuration
+#
+config NET_MPLS_GSO
+       tristate "MPLS: GSO support"
+       help
+        This is helper module to allow segmentation of non-MPLS GSO packets
+        that have had MPLS stack entries pushed onto them and thus
+        become MPLS GSO packets.
diff --git a/net/mpls/Makefile b/net/mpls/Makefile
new file mode 100644 (file)
index 0000000..0a3c171
--- /dev/null
@@ -0,0 +1,4 @@
+#
+# Makefile for MPLS.
+#
+obj-y += mpls_gso.o
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c
new file mode 100644 (file)
index 0000000..1bec121
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *     MPLS GSO Support
+ *
+ *     Authors: Simon Horman (horms@verge.net.au)
+ *
+ *     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.
+ *
+ *     Based on: GSO portions of net/ipv4/gre.c
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/netdev_features.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+
+static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
+                                      netdev_features_t features)
+{
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+       netdev_features_t mpls_features;
+       __be16 mpls_protocol;
+
+       if (unlikely(skb_shinfo(skb)->gso_type &
+                               ~(SKB_GSO_TCPV4 |
+                                 SKB_GSO_TCPV6 |
+                                 SKB_GSO_UDP |
+                                 SKB_GSO_DODGY |
+                                 SKB_GSO_TCP_ECN |
+                                 SKB_GSO_GRE |
+                                 SKB_GSO_MPLS)))
+               goto out;
+
+       /* Setup inner SKB. */
+       mpls_protocol = skb->protocol;
+       skb->protocol = skb->inner_protocol;
+
+       /* Push back the mac header that skb_mac_gso_segment() has pulled.
+        * It will be re-pulled by the call to skb_mac_gso_segment() below
+        */
+       __skb_push(skb, skb->mac_len);
+
+       /* Segment inner packet. */
+       mpls_features = skb->dev->mpls_features & netif_skb_features(skb);
+       segs = skb_mac_gso_segment(skb, mpls_features);
+
+
+       /* Restore outer protocol. */
+       skb->protocol = mpls_protocol;
+
+       /* Re-pull the mac header that the call to skb_mac_gso_segment()
+        * above pulled.  It will be re-pushed after returning
+        * skb_mac_gso_segment(), an indirect caller of this function.
+        */
+       __skb_push(skb, skb->data - skb_mac_header(skb));
+
+out:
+       return segs;
+}
+
+static int mpls_gso_send_check(struct sk_buff *skb)
+{
+       return 0;
+}
+
+static struct packet_offload mpls_mc_offload = {
+       .type = cpu_to_be16(ETH_P_MPLS_MC),
+       .callbacks = {
+               .gso_send_check =       mpls_gso_send_check,
+               .gso_segment    =       mpls_gso_segment,
+       },
+};
+
+static struct packet_offload mpls_uc_offload = {
+       .type = cpu_to_be16(ETH_P_MPLS_UC),
+       .callbacks = {
+               .gso_send_check =       mpls_gso_send_check,
+               .gso_segment    =       mpls_gso_segment,
+       },
+};
+
+static int __init mpls_gso_init(void)
+{
+       pr_info("MPLS GSO support\n");
+
+       dev_add_offload(&mpls_uc_offload);
+       dev_add_offload(&mpls_mc_offload);
+
+       return 0;
+}
+
+static void __exit mpls_gso_exit(void)
+{
+       dev_remove_offload(&mpls_uc_offload);
+       dev_remove_offload(&mpls_mc_offload);
+}
+
+module_init(mpls_gso_init);
+module_exit(mpls_gso_exit);
+
+MODULE_DESCRIPTION("MPLS GSO support");
+MODULE_AUTHOR("Simon Horman (horms@verge.net.au)");
+MODULE_LICENSE("GPL");
index 5b142fb164801bee9ab126d00fa3e485cdf96c60..7c3ed429789e579759825b57e21f307b0a7dbe3a 100644 (file)
@@ -1487,9 +1487,9 @@ ip_vs_forget_dev(struct ip_vs_dest *dest, struct net_device *dev)
  * Currently only NETDEV_DOWN is handled to release refs to cached dsts
  */
 static int ip_vs_dst_event(struct notifier_block *this, unsigned long event,
-                           void *ptr)
+                          void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
        struct netns_ipvs *ipvs = net_ipvs(net);
        struct ip_vs_service *svc;
index 5fea563afe30421ccfb5d1dcd294a055144623e0..85e20a9190816f348a845937b8a4fe470a917744 100644 (file)
@@ -104,7 +104,7 @@ static void mangle_contents(struct sk_buff *skb,
        /* move post-replacement */
        memmove(data + match_offset + rep_len,
                data + match_offset + match_len,
-               skb->tail - (skb->network_header + dataoff +
+               skb_tail_pointer(skb) - (skb_network_header(skb) + dataoff +
                             match_offset + match_len));
 
        /* insert data from buffer */
index 4e27fa035814ab8a571268b3a9e4dd8b0cd7bce4..0f2ac8f2e7b76f504a991aab606f76f9ce7a773a 100644 (file)
@@ -800,7 +800,7 @@ static int
 nfqnl_rcv_dev_event(struct notifier_block *this,
                    unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        /* Drop any packets associated with the downed device */
        if (event == NETDEV_DOWN)
index bd93e51d30acc4eded7e5e4da0898e0838dd7c43..292934d234822a4a0b0088e030b316de05eee9bc 100644 (file)
@@ -200,7 +200,7 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 static int tee_netdev_event(struct notifier_block *this, unsigned long event,
                            void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct xt_tee_priv *priv;
 
        priv = container_of(this, struct xt_tee_priv, notifier);
index 8a6c6ea466d874dd34afd2013bef4f777a47db42..af3531926ee0c0339c6cc73725c50a1d7ec2a18d 100644 (file)
@@ -708,7 +708,7 @@ unlhsh_remove_return:
  * netlbl_unlhsh_netdev_handler - Network device notification handler
  * @this: notifier block
  * @event: the event
- * @ptr: the network device (cast to void)
+ * @ptr: the netdevice notifier info (cast to void)
  *
  * Description:
  * Handle network device events, although at present all we care about is a
@@ -717,10 +717,9 @@ unlhsh_remove_return:
  *
  */
 static int netlbl_unlhsh_netdev_handler(struct notifier_block *this,
-                                       unsigned long event,
-                                       void *ptr)
+                                       unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct netlbl_unlhsh_iface *iface = NULL;
 
        if (!net_eq(dev_net(dev), &init_net))
index ec0c80fde69f8e23f205d8cb17616c1486e9ce01..698814bfa7adfd4a58e9ec13f24eeb341ea86e08 100644 (file)
@@ -117,7 +117,7 @@ static void nr_kill_by_device(struct net_device *dev)
  */
 static int nr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (!net_eq(dev_net(dev), &init_net))
                return NOTIFY_DONE;
index ef4feec6cd845e67903706f448ccc5d1a8f96556..c3235675f35997169ad4961722344537005a8f6e 100644 (file)
@@ -78,7 +78,7 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
                           void *ptr)
 {
        struct ovs_net *ovs_net;
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct vport *vport = NULL;
 
        if (!ovs_is_internal_dev(dev))
index 8ec1bca7f85908c22534eb2023fef135859997c3..79fe63246b27acf7a4a026cb185f28f65ffec6c0 100644 (file)
@@ -3331,10 +3331,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 }
 
 
-static int packet_notifier(struct notifier_block *this, unsigned long msg, void *data)
+static int packet_notifier(struct notifier_block *this,
+                          unsigned long msg, void *ptr)
 {
        struct sock *sk;
-       struct net_device *dev = data;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
 
        rcu_read_lock();
index 45a7df6575ded371ef75fc11fc41a2b48371e51e..56a6146ac94bd331502294244ee2daa637f2054b 100644 (file)
@@ -292,9 +292,9 @@ static void phonet_route_autodel(struct net_device *dev)
 
 /* notify Phonet of device events */
 static int phonet_device_notify(struct notifier_block *me, unsigned long what,
-                               void *arg)
+                               void *ptr)
 {
-       struct net_device *dev = arg;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        switch (what) {
        case NETDEV_REGISTER:
index 9c834745159786e5e1d4338f51860be00943a0fd..e98fcfbe6007919d6c114708cde848a649bb2e4e 100644 (file)
@@ -202,10 +202,10 @@ static void rose_kill_by_device(struct net_device *dev)
 /*
  *     Handle device status changes.
  */
-static int rose_device_event(struct notifier_block *this, unsigned long event,
-       void *ptr)
+static int rose_device_event(struct notifier_block *this,
+                            unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (!net_eq(dev_net(dev), &init_net))
                return NOTIFY_DONE;
index 5d676edc22a66010ee93eea8b4663a45f60b4c75..977c10e0631b6dfe4ead45af617c0ad93c4a0759 100644 (file)
@@ -243,7 +243,7 @@ nla_put_failure:
 static int mirred_device_event(struct notifier_block *unused,
                               unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct tcf_mirred *m;
 
        if (event == NETDEV_UNREGISTER)
index e478d316602b1b9ca94100369e878f0a315a72cd..1aaf1b6e51a2be238bc47797597ed3bcb76de4b1 100644 (file)
@@ -116,14 +116,57 @@ struct tbf_sched_data {
        struct qdisc_watchdog watchdog; /* Watchdog timer */
 };
 
+
+/* GSO packet is too big, segment it so that tbf can transmit
+ * each segment in time
+ */
+static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
+{
+       struct tbf_sched_data *q = qdisc_priv(sch);
+       struct sk_buff *segs, *nskb;
+       netdev_features_t features = netif_skb_features(skb);
+       int ret, nb;
+
+       segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+
+       if (IS_ERR_OR_NULL(segs))
+               return qdisc_reshape_fail(skb, sch);
+
+       nb = 0;
+       while (segs) {
+               nskb = segs->next;
+               segs->next = NULL;
+               if (likely(segs->len <= q->max_size)) {
+                       qdisc_skb_cb(segs)->pkt_len = segs->len;
+                       ret = qdisc_enqueue(segs, q->qdisc);
+               } else {
+                       ret = qdisc_reshape_fail(skb, sch);
+               }
+               if (ret != NET_XMIT_SUCCESS) {
+                       if (net_xmit_drop_count(ret))
+                               sch->qstats.drops++;
+               } else {
+                       nb++;
+               }
+               segs = nskb;
+       }
+       sch->q.qlen += nb;
+       if (nb > 1)
+               qdisc_tree_decrease_qlen(sch, 1 - nb);
+       consume_skb(skb);
+       return nb > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
+}
+
 static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
        struct tbf_sched_data *q = qdisc_priv(sch);
        int ret;
 
-       if (qdisc_pkt_len(skb) > q->max_size)
+       if (qdisc_pkt_len(skb) > q->max_size) {
+               if (skb_is_gso(skb))
+                       return tbf_segment(skb, sch);
                return qdisc_reshape_fail(skb, sch);
-
+       }
        ret = qdisc_enqueue(skb, q->qdisc);
        if (ret != NET_XMIT_SUCCESS) {
                if (net_xmit_drop_count(ret))
index 4b2c83146aa7e5c47b46b8148d701a4fc3d2189e..6533d81a638de1c50b2047ea54e140b229f1e564 100644 (file)
@@ -589,7 +589,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
        struct sctp_association *asoc = NULL;
        struct sctp_transport *transport;
        struct inet_sock *inet;
-       sk_buff_data_t saveip, savesctp;
+       __u16 saveip, savesctp;
        int err;
        struct net *net = dev_net(skb->dev);
 
index 391a245d520316c865aad51424b94b9fe6fb8bf7..8ee553b499ce5f8b77b1bf2c9c6d4488f87a92d1 100644 (file)
@@ -153,7 +153,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct sctp_association *asoc;
        struct sctp_transport *transport;
        struct ipv6_pinfo *np;
-       sk_buff_data_t saveip, savesctp;
+       __be16 saveip, savesctp;
        int err;
        struct net *net = dev_net(skb->dev);
 
index 120a676a3360173311a7acb0a6499f0db921d5d9..fc60bea631691896380e94b68fb76c9454ddfa15 100644 (file)
@@ -251,9 +251,9 @@ static void disable_bearer(struct tipc_bearer *tb_ptr)
  * specified device.
  */
 static int recv_notification(struct notifier_block *nb, unsigned long evt,
-                            void *dv)
+                            void *ptr)
 {
-       struct net_device *dev = (struct net_device *)dv;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct eth_bearer *eb_ptr = &eth_bearers[0];
        struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
 
index 2a2864c25e15c6d9282357c3685008c67a73197a..baa9df4327d955472ae04d464c8958af4bae2356 100644 (file)
@@ -244,9 +244,9 @@ static void disable_bearer(struct tipc_bearer *tb_ptr)
  * specified device.
  */
 static int recv_notification(struct notifier_block *nb, unsigned long evt,
-                            void *dv)
+                            void *ptr)
 {
-       struct net_device *dev = (struct net_device *)dv;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct ib_bearer *ib_ptr = &ib_bearers[0];
        struct ib_bearer *stop = &ib_bearers[MAX_IB_BEARERS];
 
index 73405e00c800fd62ff703c9c030e31da70c69858..01e41191f1bf7f59c502f4c2499ad71304e6e4e9 100644 (file)
@@ -886,10 +886,9 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
 }
 
 static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
-                                        unsigned long state,
-                                        void *ndev)
+                                        unsigned long state, void *ptr)
 {
-       struct net_device *dev = ndev;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev;
        int ret;
index 37ca9694aabea14efd6308b59ced2e153ac30ae5..1d964e23853f22881151a6c113b813eb431b8d9c 100644 (file)
@@ -224,7 +224,7 @@ static void x25_kill_by_device(struct net_device *dev)
 static int x25_device_event(struct notifier_block *this, unsigned long event,
                            void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct x25_neigh *nb;
 
        if (!net_eq(dev_net(dev), &init_net))
index 0cf003dfa8fcd3d4f2f974f21649b164f76429b3..eb4a8428864879a1346fbd7895b4e5afaa4d91e3 100644 (file)
@@ -89,7 +89,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
 
                err = x->type->output(x, skb);
                if (err == -EINPROGRESS)
-                       goto out_exit;
+                       goto out;
 
 resume:
                if (err) {
@@ -107,15 +107,14 @@ resume:
                x = dst->xfrm;
        } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
 
-       err = 0;
+       return 0;
 
-out_exit:
-       return err;
 error:
        spin_unlock_bh(&x->lock);
 error_nolock:
        kfree_skb(skb);
-       goto out_exit;
+out:
+       return err;
 }
 
 int xfrm_output_resume(struct sk_buff *skb, int err)
index ea970b8002a20a614a5bc9fe89afa3c39b131180..e52cab3591dd78c373274bb64420f87383775e8c 100644 (file)
@@ -2785,7 +2785,7 @@ static void __net_init xfrm_dst_ops_init(struct net *net)
 
 static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        switch (event) {
        case NETDEV_DOWN:
index 47a49d1a6f6adf7b60873fcfb1249b1ee023f5b9..694e9e43855f15862227e6caf726189deec5f0fc 100644 (file)
@@ -264,7 +264,7 @@ static int sel_netif_avc_callback(u32 event)
 static int sel_netif_netdev_notifier_handler(struct notifier_block *this,
                                             unsigned long event, void *ptr)
 {
-       struct net_device *dev = ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
        if (dev_net(dev) != &init_net)
                return NOTIFY_DONE;